细分生成球面三角网格(matlab)
论文需要生成一个球面网格,最简单的想法是通过正多面体的细分来逼近球面。我们知道柏拉图多面体有五个,三个是由正三角形组成(正四,八,二十面体),一个由正方形组成(正六面体),一个由正五边形组成(正十二面体)。三角形的细分比较简单,而且保持拓扑可以连续细分。
由于只是为了得到图片,就直接用matlab来实现了,方便,matlab中画着三角网格可以用trimesh或者patch
Syntax
trimesh(Tri,X,Y,Z)
trimesh(Tri,X,Y,Z,C)
trimesh(...'PropertyName',PropertyValue...)
patch(X,Y,C)
patch(X,Y,Z,C)
patch(FV)
patch(...'PropertyName',propertyvalue...)
patch('PropertyName',propertyvalue,...)
但是都要用一个参数来指定每个三角面是由那些点组成(比如trimesh中的Tri)。我们用vertex储存点,face指定面由哪些点构成,细分的函数如下:
1 function [vertex, face] = Subdivision(vertex, face) 2 face_num = size(face, 1); 3 vertex_num = size(vertex, 1); 4 new_vertexs = zeros(face_num*3, 3); 5 new_faces = zeros(face_num*3, 3); 6 for i = 1 : face_num 7 new_vertexs(3*(i-1)+1, :)=(vertex(face(i, 1), :)+vertex(face(i, 2), :))/2; 8 new_vertexs(3*(i-1)+1, :)= new_vertexs(3*(i-1)+1, :)/norm(new_vertexs(3*(i-1)+1, :),2); 9 new_vertexs(3*(i-1)+2, :)=(vertex(face(i, 2), :)+vertex(face(i, 3), :))/2; 10 new_vertexs(3*(i-1)+2, :)= new_vertexs(3*(i-1)+2, :)/norm(new_vertexs(3*(i-1)+2, :),2); 11 new_vertexs(3*(i-1)+3, :)=(vertex(face(i, 3), :)+vertex(face(i, 1), :))/2; 12 new_vertexs(3*(i-1)+3, :)= new_vertexs(3*(i-1)+3, :)/norm(new_vertexs(3*(i-1)+3, :),2); 13 new_faces(3*(i-1)+1, :) = [face(i, 1), vertex_num+3*(i-1)+1, vertex_num+3*(i-1)+3]; 14 new_faces(3*(i-1)+2, :) = [face(i, 2), vertex_num+3*(i-1)+2, vertex_num+3*(i-1)+1]; 15 new_faces(3*(i-1)+3, :) = [face(i, 3), vertex_num+3*(i-1)+3, vertex_num+3*(i-1)+2]; 16 face(i, :) = [vertex_num+3*(i-1)+1, vertex_num+3*(i-1)+2, vertex_num+3*(i-1)+3]; 17 end 18 face = [face; new_faces]; 19 vertex = [vertex; new_vertexs];
先选择正四面体来细分,以下是正四面体,以及细分了两次三次四次的结果:
可以看到,用正四面体细分效果不太好,四次细分后虽然比较像球面,但是三角网格大小差别很大,因此改用正二十面体细分,获得正二十面体的数据比较麻烦,我在百度知道上找到一个matlab的代码,但是上面的细分函数要求细分对象是单位的,所以加上了平移和单位化。原来的face的顺序不一致,在画图的时候明暗会有问题,可以计算每个面的有向面积来判断点的顺序,不对的话反一下反向。
1 function [vertexs, faces]=GetRegularIcosahedron 2 t = 0:2*pi/5:(2*pi-2*pi/5); 3 vertexs = [cos(t'),sin(t'),zeros(5,1)]; 4 t = t'+pi/5; 5 a = 2*sin(pi/5); 6 vertexs=[vertexs;cos(t),sin(t),a*sqrt(3)*ones(5,1)/2]; 7 h = sqrt(0.75*a^2-cos(pi/5)^2); 8 vertexs = [0 0 -h;vertexs;0 0 a*sqrt(3)/2+h]; 9 vertexs = vertexs - [zeros(12,2), ones([12,1])*0.5]; 10 for i = 1 :12 11 vertexs(i, :) = vertexs(i, :)/norm(vertexs(i, :), 2); 12 end 13 faces = [1 2 3 14 1 3 4 15 1 4 5 16 1 5 6 17 1 6 2 18 2 3 7 19 2 6 11 20 2 7 11 21 3 7 8 22 3 4 8 23 4 8 9 24 4 5 9 25 5 9 10 26 5 6 10 27 6 10 11 28 7 8 12 29 8 9 12 30 9 10 12 31 10 11 12 32 7 11 12]; 33 change = 0; 34 for i =1 : 20 35 if(det([vertexs(faces(i, 1), :); 36 vertexs(faces(i, 2), :); 37 vertexs(faces(i, 3), :)])<0); 38 change = change+1; 39 faces(i, :) = [faces(i, 1);faces(i, 3);faces(i, 2)]; 40 end 41 end
以下是正二十面体以及细分一次两次三次的图像:
这就比较漂亮了。