我正在编写一个模拟程序,对映在球面表面上的网格进行操作。这个网格本身是一个细分的二十面体(不事先知道细分级别)。
对于一个正方形网格,很容易找到相邻的单元格,因为它们在x或y轴上会加或减1。但是对于这些三角形来说,情况完全不同,我的思维很难想象一种索引单元格的方法。
是否有任何坐标系统可以用于寻址二十面体的面,至少使得轻松获得与二十面体中任意单元格相邻的3个单元格?
我正在编写一个模拟程序,对映在球面表面上的网格进行操作。这个网格本身是一个细分的二十面体(不事先知道细分级别)。
对于一个正方形网格,很容易找到相邻的单元格,因为它们在x或y轴上会加或减1。但是对于这些三角形来说,情况完全不同,我的思维很难想象一种索引单元格的方法。
是否有任何坐标系统可以用于寻址二十面体的面,至少使得轻松获得与二十面体中任意单元格相邻的3个单元格?
ZxZ
,因此好的坐标由整数对(m,n)
给出。威廉·哈密顿在伊科西亚微积分中发现了一种非常有趣的解决这些问题的方法,并在伊科西亚游戏中推广。值得注意的是,在群和生成元的概念被发明(或至少被充分理解)之前,哈密顿就给出了二十面体旋转群的生成元(他用希腊字母iota和kappa代替了a和b)。然后,哈密顿使用他的伊科西亚微积分在十二面体的顶点图(或等价地,正二十面体的面图,因为十二面体和正二十面体是对偶的)上找到了一个哈密顿回路。请在此处查看图形。
那个图表可以用来按循环顺序从0到19索引二十面体的面。将十二面体的顶点图中的点从0到19沿着哈密顿回路编号,这对应于沿着哈密顿回路也编号相邻的二十面体面。给定一个面m,它的两个相邻面分别是m-1模20和m+1模20;第三个相邻面由graph中的虚线给出。也许有一个关于第三个相邻面的索引的好的公式或者模式,但我一时想不到;把它存储在表格中也很容易。我一直在考虑对面进行索引。使用三角形平铺维基百科页面上的图像,一个面将由无限平铺的大三角形部分组成。
对于二十面体的每个面,您可以将三角形映射到一个网格上,每个网格正方形分为两部分,例如(为了方便格式化的十六进制编号):
A
+
|\
|0\
+--+
|\2|\
|1\|3\
+--+--+
|\5|\7|\
|4\|6\|8\
+--+--+--+
|\A|\C|\E|\
|9\|B\|D\|F\
+--+--+--+--+
B C
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)
这样可以在不显式存储相邻信息的情况下轻松引用细分三角网格中的三角形。
问题在于当将其组织成一个二十面体时。计算相邻三角形的引用后,需要验证新的引用是否在边界内:
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
}
您需要为每个边存储邻接信息以及其类型(AB、BC、AC)。
您需要找出9种不同的可能映射,每种映射对应一种边缘类型的组合。例如,如果相邻的三角形横跨AC边缘,并且该边缘与相邻侧的AB边缘匹配,则
side = adjacent side (from table)
row = row
column = column - ((row * 2) + 1)
这种方法在某些方面更加复杂,但在其他方面更加简单。所有这些的优点包括:
将每个三角形分配一个元组{s,x,y}
是很简单的,其中s表示边,x,y
表示在该边内的位置:
/\ /Y
/__\
/\ /\
/__\/__\ ->X