C++ 如何索引二十面体的面?

C++ 如何索引二十面体的面?,c++,math,geometry,C++,Math,Geometry,我正在写一个模拟,它作用于一个映射到球体表面的网格上。网格本身是一个细分的网格(但细分级别事先不知道) 使用正方形网格,很容易找到相邻的单元格,因为它们沿x轴或y轴都是正负1。但这些三角形根本不是这样,我的大脑很难想象出一种索引细胞的方法 是否有任何类型的坐标系可以用于处理二十面体的面,至少可以轻松地获得二十面体中任意单元相邻的3个单元?基本上,您希望将几何体预处理为特定的数据结构,以便快速查找三角形的相邻单元 如果这是你唯一的要求,你可以很容易地“推出你自己的”。例如,对于每个三角形,您将存储

我正在写一个模拟,它作用于一个映射到球体表面的网格上。网格本身是一个细分的网格(但细分级别事先不知道)

使用正方形网格,很容易找到相邻的单元格,因为它们沿x轴或y轴都是正负1。但这些三角形根本不是这样,我的大脑很难想象出一种索引细胞的方法


是否有任何类型的坐标系可以用于处理二十面体的面,至少可以轻松地获得二十面体中任意单元相邻的3个单元?

基本上,您希望将几何体预处理为特定的数据结构,以便快速查找三角形的相邻单元

如果这是你唯一的要求,你可以很容易地“推出你自己的”。例如,对于每个三角形,您将存储其三条边,作为指向边结构的指针或作为边表的索引。然后,对于每条边,存储其两个相邻的三角形(同样作为指针或三角形索引)

此设置允许您轻松地从三角形到其每条边,然后从边结构中查找其他相邻三角形

对于三角化曲面,有更高级的数据结构,允许执行更有趣的操作,例如或


如果您想使用预制库,则将执行您需要的操作以及更多操作。

为每个三角形指定一个元组
{s,x,y}
,其中s表示边,而
x,y
表示该边内的位置非常简单:

   /\ /Y
  /__\
 /\  /\
/__\/__\ ->X
这将有三角形{0,0}、{1,1}(中间)、{2,0}和{0,2}。在一个平面内(相同的s),x&y坐标告诉您哪些三角形是边界。对于30条边,您需要一个单独的表格,它表示每条边的两边有哪些三角形,以及它们的X、Y坐标是如何排序的


(你可能会想出一个智能编号而不是一个表格;我做不到。)

对于二十面体的每一侧,你可以将三角形映射到一个网格,每个网格正方形分成两部分,例如(为了方便格式化,索引的十六进制编号):

对于分为n次的边,边上有4n个三角形,因此可以为二十面体的每一侧创建一个该大小的数组,以存储任何每个三角形的数据以供模拟

对三角形的引用可以存储为(边、行、列)

行和列索引是基于0的。列索引基于行中三角形的数量(即每个网格正方形2个)

如果有side、row和column,则可以按如下方式将索引计算到side的数组中:

index = (row * row) + column
value = data[side][(row * row) + column]
因此,您可以将数据存储在二维数组中,并按如下方式访问数据:

index = (row * row) + column
value = data[side][(row * row) + column]
具有偶数列的三角形的相邻三角形:

(side, row, column - 1)
(side, row, column + 1)
(side, row + 1, column + 1)
(side, row, column - 1)
(side, row, column + 1)
(side, row - 1, column - 1)
具有奇数列的三角形的相邻三角形:

(side, row, column - 1)
(side, row, column + 1)
(side, row + 1, column + 1)
(side, row, column - 1)
(side, row, column + 1)
(side, row - 1, column - 1)
这使您可以在细分的三角形网格中轻松引用三角形,而无需显式存储邻接信息

关键是要把它组织成一个二十面体。计算对相邻三角形的引用后,需要验证新引用是否在边的边界内:

int rows = 1 << subdivision_count;
if(row >= rows)
{
    // compute (side, row, column) in adjacent side of icosahedron to B-C edge
}
else if(column < 0)
{
    // compute (side, row, column) in adjacent side of icosahedron to A-B edge
}
else if(column >= ((row * 2) + 1))
{
    // compute (side, row, column) in adjacent side of icosahedron to A-C edge
}

在某些方面,这是一种更复杂的方法,但在其他方面更简单。所有这些的优点是:

  • 不需要存储单个三角形的邻接信息,仅存储二十面体边的邻接信息
  • 如果为每侧存储a、B、C的三维位置,则可以为给定(边、行、列)参考的三角形计算三维三角形坐标,因此也无需为每个三角形存储这些坐标

  • 这是一个有趣的问题。确切的答案取决于你如何细分二十面体的面,你没有说。但我会给出一个框架来反驳这个问题

    首先,让我说一下,在正方形网格的情况下,我认为什么使问题变得简单:网格上有一个反映对称性的数学群结构。精确地说,有一对简单的变换(向上移位;向右移位),它们与它们的逆运算一起生成一个网格单元到另一个网格单元的每个变换。此外,上移和右移操作是相互转换的:应用操作序列的顺序不会改变结果。“向上”和“向右”操作在单元网格上生成可交换的变换组。这个群同构于
    ZxZ
    ,所以很好的坐标是由成对的整数
    (m,n)
    给出的

    二十面体上缺少这样的结构是你的问题之一。二十面体上有一个群结构,有两个生成器,有时称为“a”和“b”,其中“a”是180度旋转,将给定边映射到自身上,反转,b是给定面的120度旋转。问题是这个群是不可交换的,所以ab!=文学士。这严重地使群生成器的计算复杂化。另一个问题是,此方法三重覆盖每个面(每次旋转一次)。二十面体旋转对称群A5中有60个元素,但二十面体上只有20个面

    威廉·汉密尔顿在年发现了一种解决这些问题的非常有趣的方法,并在年推广。值得注意的是,汉密尔顿给出了二十面体旋转群的生成元(他用希腊的iota和kappa而不是a和b来表示),这是在群和生成元的概念真正被发明(或者至少被很好地理解)之前。然后,汉密尔顿用他的二十面体演算在十二面体顶点图(或者等价地,二十面体的面图,因为十二面体和二十面体彼此是对偶的)上找到一个哈密顿回路。请看图表

    该图可用于索引循环ord中二十面体的面