具有高空间相干性的3D整数坐标的哈希码

时间:2012-03-25 06:40:57

标签: java coordinates hash

这是我在这些论坛上的第一个问题:)

我正在用Java编写一个空间八叉树体素系统的坐标类。这些坐标不是浮点坐标,它们是进入八叉树的4D整数索引(3个正常尺寸X,Y,Z和第四个深入到树中)。前3个值都是短路,最后一个维度是一个字节。在实际使用中,现在只使用短路的前11位,只有3位的字节,但这可能会有所改变。

现在我正在尝试为这个类写一个'好'的哈希函数。我正在努力解决的问题是坐标通常会在高度空间连贯的情况下使用(希望我在那里使用正确的术语)。我的意思是,通常会将坐标与其紧邻的邻居和其他附近坐标进行哈希处理。

是否有一种有效的做法可以使这些“彼此靠近”的坐标产生明显不同的哈希码?

2 个答案:

答案 0 :(得分:13)

你很幸运:有一种方法可以使用一种称为Z-order curve的东西来获得具有高空间连贯性的正确坐标编码。

技巧是交错不同坐标分量的位。所以,如果你有3个8位坐标,如:

[XXXXXXXX, YYYYYYYY, ZZZZZZZZ]

然后z曲线编码值将是一个24位值:

XYZXYZXYZXYZXYZXYZXYZXYZ

您可以根据需要扩展到更大的位数或坐标。

这种编码有效,因为在空间上很近的坐标主要在低阶位上有差异。因此,通过交错坐标,您可以将差异集中在编码值的低位。

另一个有趣的特性是较低的位描述了空间立方体内的坐标。所以最低3位地址位置有2x2x2立方体,最低6位地址位置在4 * 4 * 4立方体内,最低9位位置在8 * 8 * 8立方体内等等所以这实际上是一个非常理想的寻址系统八叉树内的对齐。

答案 1 :(得分:2)

“显着不同”实际上取决于您之后使用哈希码做什么。在某些情况下,它将通过hash % size进行循环铲斗选择,例如,size是您正在使用的哈希映射的大小。显然会随着时间的推移而改变。我通常会使用类似的东西:

int hash = 23;
hash = hash * 31 + x;
hash = hash * 31 + y;
hash = hash * 31 + z;
hash = hash * 31 + depth;
return hash;

(这基本上来自Effective Java。)显然,这意味着(x1, y1, z1)(x1 + 1, y1 - 31, z1)将具有相同的哈希码,但如果您最担心非常靠近邻居它应该不是问题。

编辑:迈克拉的答案很可能更好但代码更复杂。我会亲自尝试这个非常简单的方法,看看它是否足够足够用于实际用例。逐步使用更有效但更复杂的方法,直到找到一个足够好的方法。