sierpinski垫片(3D)[误]

今天是因为可以用py而高兴的一天。

 

昨天老板淡淡地回了一句,sierpinski地毯画得挺好的。

 

我思考了五秒钟之后,想起来作业其实是sierpinski垫片。

 
 

 

 

三角垫片比地毯难做多了。

因为你用的像素点,其实是矩形,你可以把像素点当矩形用。

三角形,随机算法可以,你要我用传统算法来解那个三角垫片,我只想给你以窝jio。除非你给我一个三角网格。

所以在jpg里玩,没tai意nan思le。你说你解完,反不反走样。。。是吧。。。反走样很蠢,走样了很丑。

 

所以,我决定用.ply来存这玩意。。。话说,既然这么用,干脆搞个大新闻好了。

不然你说,在三维空间里存了一堆平面上的三角,哈哈哈哈哈次藕爆了。

 

 

 

可是道理我都懂,为啥底是矩形呢。。。[图片来自百度,侵删]

所以,我们要整个更好看的哈哈哈哈哈。

 

算法逻辑:

每个四面体生成四个小四面体并多出六个顶点。

最终是要输出三角面片,可是在这之前我一直是体在拆解啊。

所以我中间过程存储体的信息,最后一步拆成四个面就好了。

 

每一轮,四面体信息矩阵扩大四倍。

  每个四面体拆解都会成四个小四面体存入对应四行。

  顶点通过取中点取到六个,信息补上6个。

import numpy as np
import cv2

def beiup(x1,x2,x3,x4):
    x=np.zeros((6,3),dtype=float)
    for j in range(3):
        x[0][j]=(x1[j]+x2[j])/2
        x[1][j]=(x2[j]+x3[j])/2
        x[2][j]=(x3[j]+x1[j])/2
        x[3][j]=(x4[j]+x1[j])/2
        x[4][j]=(x4[j]+x2[j])/2
        x[5][j]=(x4[j]+x3[j])/2
    return x
def yeiup(yei,jsq):
    new=np.zeros((4,4),dtype=int)
    new[0][0]=yei[0]
    new[0][1]=jsq
    new[0][2]=jsq+2
    new[0][3]=jsq+3
    new[1][0]=jsq
    new[1][1]=yei[1]
    new[1][2]=jsq+1
    new[1][3]=jsq+4
    new[2][0]=jsq+2
    new[2][1]=jsq+1
    new[2][2]=yei[2]
    new[2][3]=jsq+5
    new[3][0]=jsq+3
    new[3][1]=jsq+4
    new[3][2]=jsq+5
    new[3][3]=yei[3]
    jsq+=6
    return new,jsq
def feiwrite(yeimat,times):
    k=4**times
    feimat=np.zeros((k*4,3),dtype=int)
    for i in range(k):
        feimat[i*4+0][0]=yeimat[i][0]
        feimat[i*4+0][1]=yeimat[i][2]
        feimat[i*4+0][2]=yeimat[i][1]
        feimat[i*4+1][0]=yeimat[i][0]
        feimat[i*4+1][1]=yeimat[i][1]
        feimat[i*4+1][2]=yeimat[i][3]
        feimat[i*4+2][0]=yeimat[i][0]
        feimat[i*4+2][1]=yeimat[i][3]
        feimat[i*4+2][2]=yeimat[i][2]
        feimat[i*4+3][0]=yeimat[i][1]
        feimat[i*4+3][1]=yeimat[i][2]
        feimat[i*4+3][2]=yeimat[i][3]
    return feimat        

def plywrite(fname,beimat,feimat,potnumber,trinumber):
    potpiplist=np.zeros((3),dtype=float)
    tripiplist=np.zeros((3),dtype=int)
    fply = open(fname,'w')
    fply.write('ply\n')
    fply.write('format ascii 1.0\n')
    fply.write('comment VCGLIB generated\n')
    fply.write('element vertex '+str(potnumber)+'\n')
    fply.write('property float x\n')
    fply.write('property float y\n')
    fply.write('property float z\n')
    fply.write('element face '+str(trinumber)+'\n')
    fply.write('property list uchar int vertex_indices\n')
    fply.write('end_header\n')
    for i in range(potnumber):
        potpiplist[0]=beimat[i][0]
        potpiplist[1]=beimat[i][1]
        potpiplist[2]=beimat[i][2]
        fply.write('%0.4f %0.4f %0.4f\n' %(potpiplist[0],potpiplist[1],potpiplist[2]))
    for i in range(trinumber):
        tripiplist[0]=feimat[i][0]
        tripiplist[1]=feimat[i][1]
        tripiplist[2]=feimat[i][2]
        fply.write('%d %d %d %d\n' %(3,tripiplist[0],tripiplist[1],tripiplist[2]))
    fply.close()
    return fname

    

解释一下变量名。

我最近在捣腾一个TPS的大项目。

 

ply文件有两个主要部分

一个是点坐标信息,beimat      顶点数*3,  float

一个是面片顶点信息,feimat   面片数*3,  int 对应beimat的第i个。 

以前没有四面体一说,yeimat   体数*4   ,  int

bei是我的名字,fei是我姐上的名。

口哼哼,我不管,反正项目我最后封装掉的。

beiup解决了如何拆出六个中点;

yeiup解决了如何拆出四个体;

feiwrite解决了如何从一个体拆除四个面片。

import numpy as np
import cv2
import tps
import sie

times=1
if times<4:
    beimat=np.zeros((600,3),dtype=float)
if times<6:
    beimat=np.zeros((2100,3),dtype=float)
if times<10:
    beimat=np.zeros((9000,3),dtype=float)

yeimat=np.zeros((1,4),dtype=int)
'''
0,0,0; 1,0,0; 0.5,g3/2,0 ;0.5 g3/6,g6/3)
'''
beimat[1][0]=1
beimat[2][0]=0.5
beimat[2][1]=(3**0.5)/2
beimat[3][0]=0.5
beimat[3][1]=(3**0.5)/6
beimat[3][2]=(6**0.5)/3

yeimat[0][1]=1
yeimat[0][2]=2
yeimat[0][3]=3
###end for setting

jsq=4
for k in range(times):
    yeinew=np.zeros((4**k*4,4),dtype=int)
    for n in range(4**k):
        beimat[jsq:jsq+6,:]=sie.beiup(beimat[int(yeimat[n][0])],beimat[int(yeimat[n][1])],beimat[int(yeimat[n][2])],beimat[int(yeimat[n][3])])
        [yeinew[4*n:4*n+4,:],jsq]=sie.yeiup(yeimat[n],jsq) 
    yeimat=yeinew

feimat=sie.feiwrite(yeimat,times)

    
fname=str("sie"+str(int(times))+".ply")
print(jsq)

fname=sie.plywrite(fname,beimat[0:jsq,:],feimat,jsq,4**times*4)

  

主程序有三部分:

决定beimat的大小

初始化第一个四面体(顶点坐标+编号)

主循环体+输出。

 

你说我不能算出来beimat应该有多大么?

毕竟是学树学的,这如果算不出来实在是无能。。。问题是,我有必要算么?

如果你要算的话,就是x=x*4-6的一个递归数列。。。可以,但没必要。

我jsq最后会告诉我有多少个坐标点的。。。我只要,一开始不把beimat设太小就好了。

这里四个是1-4次迭代;下方几个都是5/6次迭代。

 

 

 

 

 

 

嘿嘿嘿!py万岁!

 

posted @ 2019-11-20 13:55  wushibei  阅读(413)  评论(0)    收藏  举报