细分生成球面三角网格(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

以下是正二十面体以及细分一次两次三次的图像:

这就比较漂亮了。

原文地址:https://www.cnblogs.com/yezhangxiang/p/1991323.html