螺旋蜂窝马赛克和轴向hex坐标之间的转换

似乎有相当多的处理六边形网格的逻辑,使用轴向坐标系统,就像这里描述的那样 。

然而,在阅读有关六角格子的文章时,我碰到了螺旋蜂窝Mosiac的概念(这个镜子上的链接被破坏,内容从这里复制 ,大约在页面的一半)。 它似乎主要用于image processing,但从每个hex为每个hex分配一个唯一的,连续的基数为7的数字作为它的标识符是有趣的。

我不确定它对于任何事情都是有用的,但是我想知道: 是否可以在SHM编号系统和轴向坐标之间来回转换

两个系统都有方法将一个hex转换为其中心的笛卡尔坐标,所以大概可以从一个系统中计算出来,然后再计算出来。 但是,这是混乱和低效率,我相信有可能做得更好。

由于SHM的分形性质,所提供的示例代码中的转换例程依赖于一个循环; 似乎一般的解决scheme可能涉及一个系列?

带有SHM编号和轴向坐标的六角形网格示例。

感谢一个迷人的谜题! 是的,看起来我们可以做得比通过六边形中心的笛卡尔坐标转换更好。 它可以完全用整数math来完成,尽管我已经在下面的matrix中包含了一个有理数的元素来保持简洁。

你说得对,编码和解码过程都需要循环。 幸运的是,由于SHM工作在数量级上,循环永远不会需要超过Log_7(n + 1)次迭代,其中n是网格中的瓦片数量,这是非常合理的。

为了保持我的符号对称,我select使用如下所示的3坐标网格(你从Red Blob Games中调用“Cube Coordinates”的例子 )。 如果您愿意,可以省略z坐标,并用 – (x + y)replace.z的所有实例,以获得“轴向坐标”。

Red Blob Games的“Cube Coordinates”

为了代码的速度和清洁度,我建议使用查找表进行编码和解码。 首先,为了将SHM解码为立方体坐标,可以使用以下重复来构建表格:

Rotate(v) = (-vz, -vx, -vy) Decode[,] = 2D array of ordered triples, [7 x (max_order_of_magnitude + 1)] Decode[0, k] = (0, 0, 0) for all k = 0...max_order_of_magnitude Decode[1, 0] = (0, -1, 1) Decode[d + 1, k] = Rotate(Decode(d, k)) for d = 2...6, all k Decode[d, k + 1] = Decode(d, k) + 2 * Rotate(Decode(d, k)) for all d, k 

然后解码变得非常简单:

 SHMToPoint(code) { point = (0, 0, 0) order = 0 while(code > 0) { digit = code % 7 point += Decode(digit, order) code = floor(code/7) order++ } return point } 

这是因为表的第一行存储由数字0,1,2,3,4,5,6编码的单元的偏移量。下一行存储0,10,20,30,40和40的偏移量。 50,60等等。 通过将每个数量级贡献的偏移相加,可以解码表格范围内的任意点。

对于编码,我认为下面的方法将工作,但我会承认我没有testing过。 它使用一个更简单的查找表:

 Encode = [0, 5, 1, 6, 3, 4, 2] 

和一个旋转和缩放matrix:

 Untwist = | 5 -4 2 | | 2 5 -4 | |-4 2 5 | * 1/21 

要将立方体坐标编码为SHM,则…

 PointToSHM(point) { code = 0 magnitude = 1 while(point != (0, 0, 0)) { digitIndex = (((point.x - 2 * point.y) % 7) + 7) % 7 code += magnitude *Encode[digitIndex] point = Untwist * (point - Decode[digit, 0]) // treating "point" as a column vector, and rounding if necessary magnitude *= 7 } return code } 

请注意,此处生成的代码(以及上面解码的代码)是标准数字格式(即,SHM图中标记为“10”的单元格将被分配以10为底的代码,或者以二进制的111代码)。 如果你想以7为基础显示它,你需要在将其转换为string时使用相应的基数。

这是通过在每次迭代中计算SHM码的最低有效位数来实现的(使用这些数字重复定期平铺平面的事实 – LUT是从(0,0,0)读取的数字序列,到(6,0,-6),它在每一行的偏移处重复)。 接下来,通过先前从解码表中减去相应的偏移量,将该数字清零,然后使用Untwistmatrix将分形缩小一级。 这就像一个基数为7的右移,以几何forms – 把下一个数字带到最低位,把单元“10”带到“1”等等,我们可以再次使用相同的技巧来读取在下一个循环的数字。

我希望这对你有用!