重建上采样二十面体的面

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 个新面孔。您可以使用 catpermutereshape 来执行此操作,但它变得非常丑陋且难以理解。由于我们只有 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.