重建上采样二十面体的面
Reconstructing faces of an upsampled icosahedron
我试图通过在每条边的中点添加新顶点并重新计算面来在 MATLAB 中对二十面体进行上采样。我已经设法放置了新顶点,但我不知道如何重新计算新面孔。
我希望每个顶点都连接到它最近的邻居以形成一个新的、上采样的二十面体。
示例数据:
S.vertices = ...
[0.5000 0.1625 0.8507;
0.5000 0.6882 0.5257;
0.8507 0.2764 0.4472;
0.8090 0.5878 0.0000;
0.3090 0.9511 0.0000;
0.0000 0.5257 0.8507;
-0.5000 0.6882 0.5257;
0.0000 0.8944 0.4472;
-0.3090 0.9511 0.0000;
-0.8090 0.5878 0.0000;
-0.5000 0.1625 0.8507;
-0.8090 -0.2629 0.5257;
-0.8507 0.2764 0.4472;
-1.0000 0.0000 0.0000;
-0.8090 -0.5878 0.0000;
-0.3090 -0.4253 0.8507;
-0.0000 -0.8507 0.5257;
-0.5257 -0.7236 0.4472;
-0.3090 -0.9511 0.0000;
0.3090 -0.9511 0.0000;
0.3090 -0.4253 0.8507;
0.8090 -0.2629 0.5257;
0.5257 -0.7236 0.4472;
0.8090 -0.5878 0.0000;
1.0000 -0.0000 0.0000;
0.0000 0.0000 1.0000;
0.5000 0.1625 -0.8507;
0.5000 0.6882 -0.5257;
0.8507 0.2764 -0.4472;
0.0000 0.5257 -0.8507;
-0.5000 0.6882 -0.5257;
0.0000 0.8944 -0.4472;
-0.5000 0.1625 -0.8507;
-0.8090 -0.2629 -0.5257;
-0.8507 0.2764 -0.4472;
-0.3090 -0.4253 -0.8507;
-0.0000 -0.8507 -0.5257;
-0.5257 -0.7236 -0.4472;
0.3090 -0.4253 -0.8507;
0.8090 -0.2629 -0.5257;
0.5257 -0.7236 -0.4472;
0.0000 0.0000 -1.0000];
S.faces = ...
[13 14 12;
12 15 18;
1 3 2;
25 22 24;
12 16 11;
22 23 24;
17 21 16;
18 17 16;
23 17 20;
18 16 12;
26 6 11;
11 13 12;
14 15 12;
19 18 15;
17 23 21;
8 9 7;
10 14 13;
7 9 10;
13 7 10;
11 7 13;
6 8 7;
21 26 16;
6 7 11;
2 8 6;
2 5 8;
8 5 9;
26 1 6;
4 5 2;
6 1 2;
21 23 22;
2 3 4;
1 21 22;
3 25 4;
16 26 11;
21 1 26;
19 17 18;
19 20 17;
23 20 24;
3 22 25;
3 1 22;
27 29 28;
34 36 33;
37 39 36;
38 37 36;
38 36 34;
42 30 33;
33 35 34;
37 41 39;
33 31 35;
30 32 31;
39 42 36;
30 31 33;
28 32 30;
42 27 30;
30 27 28;
39 41 40;
27 39 40;
36 42 33;
39 27 42;
29 27 40;
35 14 34;
34 15 38;
25 40 24;
40 41 24;
41 37 20;
14 15 34;
19 38 15;
32 9 31;
10 14 35;
31 9 10;
35 31 10;
28 5 32;
32 5 9;
4 5 28;
28 29 4;
29 25 4;
19 37 38;
19 20 37;
41 20 24;
29 40 25];
代码:
% Center icosahedron on the origin.
offset = mean(S.vertices);
S.vertices = S.vertices - offset;
% Calculate radius.
radius = mean(pdist2([0 0 0], S.vertices));
% Get all edges.
edges = [S.faces(:,1),S.faces(:,2); ...
S.faces(:,1),S.faces(:,3); ...
S.faces(:,2),S.faces(:,3)];
% Find midpoints of each edge.
V = (S.vertices(edges(:,1),:) + S.vertices(edges(:,2),:)) / 2;
% Convert to spherical, fix radius, and convert back to cartesian.
[theta,phi] = cart2sph(V(:,1),V(:,2),V(:,3));
[V(:,1),V(:,2),V(:,3)] = sph2cart(theta,phi,radius);
% Add new points, fix faces.
S.vertices = [S.vertices;V];
% Some clever trick to build the new faces matrix.
对于三角形{1, 2, 3}
,细分将创建3个新顶点{a, b, c}
:
1
o
/ \
/ \
a o-----o c
/ \ / \
/ \ / \
o-----o-----o
2 b 3
它还将创建 4 个新面孔:
[c 1 a], [a 2 b], [b 3 c], and [a b c]
您的代码在 V
中创建新顶点的坐标,这样所有三角形的 a
顶点排在第一位,然后是 c
顶点,然后是b
个顶点。
首先让我们生成这些顶点的索引。新索引从 size(S.vertices)+1
开始,共有 3*size(S.faces)
个。让我们也将每个现有面的新顶点分组在一起。
% before updating S.vertices...
Vx = reshape(1:size(V,1), [], 3) + size(S.vertices, 1);
这为我们提供了 Vx(f,:)
中所有新的 [a b c]
面(实际上,按 [a c b]
的顺序)和 Vx(:,1)
中的 a
个顶点, Vx(:,3)
<-- 不是 2! 中的 b
个顶点,Vx(:,2)
中的 c
个顶点。现在我们需要为每个现有面孔创建其他 3 个新面孔。您可以使用 cat
、permute
和 reshape
来执行此操作,但它变得非常丑陋且难以理解。由于我们只有 9 个顶点进入这些面,因此更容易手动插入它们以创建 m x 9
矩阵,然后重塑为 m*3 x 3
:
% face format: [c 1 a, a 2 b, b 3 c]
Fx = [Vx(:,2) S.faces(:,1) Vx(:,1)
Vx(:,1) S.faces(:,2) Vx(:,3)
Vx(:,3) S.faces(:,3) Vx(:,2)];
% now reshape to [c 1 a; a 2 b; b 3 c]
Fx = reshape(Fx.', 3, []).';
现在剩下的就是更新S
:
S.vertices = [S.vertices;V];
S.faces = [S.faces; Fx; Vx]; % oops... you probably don't want the old faces in there. they're being replaced.
我试图通过在每条边的中点添加新顶点并重新计算面来在 MATLAB 中对二十面体进行上采样。我已经设法放置了新顶点,但我不知道如何重新计算新面孔。
我希望每个顶点都连接到它最近的邻居以形成一个新的、上采样的二十面体。
示例数据:
S.vertices = ...
[0.5000 0.1625 0.8507;
0.5000 0.6882 0.5257;
0.8507 0.2764 0.4472;
0.8090 0.5878 0.0000;
0.3090 0.9511 0.0000;
0.0000 0.5257 0.8507;
-0.5000 0.6882 0.5257;
0.0000 0.8944 0.4472;
-0.3090 0.9511 0.0000;
-0.8090 0.5878 0.0000;
-0.5000 0.1625 0.8507;
-0.8090 -0.2629 0.5257;
-0.8507 0.2764 0.4472;
-1.0000 0.0000 0.0000;
-0.8090 -0.5878 0.0000;
-0.3090 -0.4253 0.8507;
-0.0000 -0.8507 0.5257;
-0.5257 -0.7236 0.4472;
-0.3090 -0.9511 0.0000;
0.3090 -0.9511 0.0000;
0.3090 -0.4253 0.8507;
0.8090 -0.2629 0.5257;
0.5257 -0.7236 0.4472;
0.8090 -0.5878 0.0000;
1.0000 -0.0000 0.0000;
0.0000 0.0000 1.0000;
0.5000 0.1625 -0.8507;
0.5000 0.6882 -0.5257;
0.8507 0.2764 -0.4472;
0.0000 0.5257 -0.8507;
-0.5000 0.6882 -0.5257;
0.0000 0.8944 -0.4472;
-0.5000 0.1625 -0.8507;
-0.8090 -0.2629 -0.5257;
-0.8507 0.2764 -0.4472;
-0.3090 -0.4253 -0.8507;
-0.0000 -0.8507 -0.5257;
-0.5257 -0.7236 -0.4472;
0.3090 -0.4253 -0.8507;
0.8090 -0.2629 -0.5257;
0.5257 -0.7236 -0.4472;
0.0000 0.0000 -1.0000];
S.faces = ...
[13 14 12;
12 15 18;
1 3 2;
25 22 24;
12 16 11;
22 23 24;
17 21 16;
18 17 16;
23 17 20;
18 16 12;
26 6 11;
11 13 12;
14 15 12;
19 18 15;
17 23 21;
8 9 7;
10 14 13;
7 9 10;
13 7 10;
11 7 13;
6 8 7;
21 26 16;
6 7 11;
2 8 6;
2 5 8;
8 5 9;
26 1 6;
4 5 2;
6 1 2;
21 23 22;
2 3 4;
1 21 22;
3 25 4;
16 26 11;
21 1 26;
19 17 18;
19 20 17;
23 20 24;
3 22 25;
3 1 22;
27 29 28;
34 36 33;
37 39 36;
38 37 36;
38 36 34;
42 30 33;
33 35 34;
37 41 39;
33 31 35;
30 32 31;
39 42 36;
30 31 33;
28 32 30;
42 27 30;
30 27 28;
39 41 40;
27 39 40;
36 42 33;
39 27 42;
29 27 40;
35 14 34;
34 15 38;
25 40 24;
40 41 24;
41 37 20;
14 15 34;
19 38 15;
32 9 31;
10 14 35;
31 9 10;
35 31 10;
28 5 32;
32 5 9;
4 5 28;
28 29 4;
29 25 4;
19 37 38;
19 20 37;
41 20 24;
29 40 25];
代码:
% Center icosahedron on the origin.
offset = mean(S.vertices);
S.vertices = S.vertices - offset;
% Calculate radius.
radius = mean(pdist2([0 0 0], S.vertices));
% Get all edges.
edges = [S.faces(:,1),S.faces(:,2); ...
S.faces(:,1),S.faces(:,3); ...
S.faces(:,2),S.faces(:,3)];
% Find midpoints of each edge.
V = (S.vertices(edges(:,1),:) + S.vertices(edges(:,2),:)) / 2;
% Convert to spherical, fix radius, and convert back to cartesian.
[theta,phi] = cart2sph(V(:,1),V(:,2),V(:,3));
[V(:,1),V(:,2),V(:,3)] = sph2cart(theta,phi,radius);
% Add new points, fix faces.
S.vertices = [S.vertices;V];
% Some clever trick to build the new faces matrix.
对于三角形{1, 2, 3}
,细分将创建3个新顶点{a, b, c}
:
1
o
/ \
/ \
a o-----o c
/ \ / \
/ \ / \
o-----o-----o
2 b 3
它还将创建 4 个新面孔:
[c 1 a], [a 2 b], [b 3 c], and [a b c]
您的代码在 V
中创建新顶点的坐标,这样所有三角形的 a
顶点排在第一位,然后是 c
顶点,然后是b
个顶点。
首先让我们生成这些顶点的索引。新索引从 size(S.vertices)+1
开始,共有 3*size(S.faces)
个。让我们也将每个现有面的新顶点分组在一起。
% before updating S.vertices...
Vx = reshape(1:size(V,1), [], 3) + size(S.vertices, 1);
这为我们提供了 Vx(f,:)
中所有新的 [a b c]
面(实际上,按 [a c b]
的顺序)和 Vx(:,1)
中的 a
个顶点, Vx(:,3)
<-- 不是 2! 中的 b
个顶点,Vx(:,2)
中的 c
个顶点。现在我们需要为每个现有面孔创建其他 3 个新面孔。您可以使用 cat
、permute
和 reshape
来执行此操作,但它变得非常丑陋且难以理解。由于我们只有 9 个顶点进入这些面,因此更容易手动插入它们以创建 m x 9
矩阵,然后重塑为 m*3 x 3
:
% face format: [c 1 a, a 2 b, b 3 c]
Fx = [Vx(:,2) S.faces(:,1) Vx(:,1)
Vx(:,1) S.faces(:,2) Vx(:,3)
Vx(:,3) S.faces(:,3) Vx(:,2)];
% now reshape to [c 1 a; a 2 b; b 3 c]
Fx = reshape(Fx.', 3, []).';
现在剩下的就是更新S
:
S.vertices = [S.vertices;V];
S.faces = [S.faces; Fx; Vx]; % oops... you probably don't want the old faces in there. they're being replaced.