如何在范围搜索中使用Morton Order?

时间:2012-10-07 21:11:17

标签: algorithm search range bit-manipulation z-order-curve

如果我有一个数据集,其中键是3D中的点,由3个带符号的64位整数表示。我想使用(排序的)键值存储来存储它们,其中键只是字节数组(但我可以指定一个比较器)。我想我可以通过使用位交错将所有这些点转换为字节数组,就像在How to compute a 3D Morton number

中使用Z / Morton顺序一样

除了获取单个点之外,没有Morton排序可以更简单地完成,我想进行范围搜索,我在一个与轴对齐的框中搜索。我将A和B分别定义为所有坐标最低的框角,以及所有坐标最高的对角。

现在我的问题是:

  1. 对于任何在逻辑上介于A和B之间的C点,C的Morton数是否也介于A和B的Morton数之间? (这不是莫顿的命令吗?)

  2. 如果1为否,A和B是否可以“舍入”到保证将包含C的值?

  3. 假设1或2是可能的,搜索返回也指向该框之外,我必须“后过滤”吗? “错误集”有多大(它取决于搜索的大小或位置)?

  4. 整数是否已签名会导致问题?如果是这样,是否有解决方法?

  5. 回顾一下,使用Morton Numbers只是实际问题的一种可能解决方案:当3D点必须映射到一维值时,如何有效地在3D整数空间中进行范围搜索?我希望通过使用min-key和max-key在数据库中执行单个范围选择来获得A和B之间的所有点,,理想情况下,在框外获得尽可能少的点尽可能。

3 个答案:

答案 0 :(得分:7)

4)是的,这个标志会引起一个问题,但要解决这个问题很简单。

在创建Morton编号之前,将x,y和z的符号位与X进行异或。

为什么会这样(使用1维签名字节代替):

二进制中的

-1是11111111

二进制中的

0是00000000

二进制的

1是00000001

您想要的顺序是-1,0,1,但当前的二进制顺序是0,1,-1。

-1 XOR 10000000 = 01111111

0 XOR 10000000 = 10000000

1 XOR 10000000 = 10000001

现在你的二进制订单是正确的

答案 1 :(得分:2)

好像我必须自己回答我的问题。答案将与z阶曲线相关,这就是我实际要求的。就我而言:

  1. 是。它总是像z阶曲线那样工作。
  2. 无关紧要,因为1)是真的。
  3. 这取决于区域的大小和位置,但最糟糕的情况是当你实际包含空间的中心时,而不是当你远离它时。对于任何维度,如果在每个维度中使用深度为N位的索引,则存在特殊情况,其中z顺序曲线为您提供完全匹配,并且您只在搜索框中获得点。满足以下条件时会发生这种情况:
    1. 搜索区域在所有维度上具有相同的大小,并且功率为2,2 ^ M,其中0 <= M <= N。
    2. 搜索区域是与所有轴对齐的超立方体。
    3. 搜索区域超立方角的所有坐标都是2 ^ M的倍数。 当满足所有这些条件时,搜索区域完全对应于子树节点,因此完全匹配。但是,在一般情况下,您可以做的最好的事情是找到最小的节点,它将保存所有所需的点,并在提供部分匹配的较小节点中递归细分,达到某个最大所需深度,以便更好地匹配使用多个查询的成本。查找包含该区域所有角的最小树节点等效于为所有角找到Morton代码的公共前缀。当使用单个查询时,返回区域之外的点数是查询的节点的体积减去搜索区域的体积。
  4. 我很确定这是一个问题,但我还没有找到相关信息。
  5. 我所说的似乎并不清楚,所以我会做一点ASCII艺术......

    2D中的基本Z阶(Morton阶)曲线如下所示(路径为A,B,C,D):

    x 0 1

    0 A B

    1 C D

    所以,A =(0,0)B =(0,1)C =(1,0)D =(1,1)

    现在2D中的基本希尔伯特曲线就像这样(路径是A,B,C,D):

    x 0 1

    0 A D

    1 B C

    所以,A =(0,0)B =(1,0)C =(1,1)D =(0,1)

    使用Z顺序(Morton顺序),曲线将从最低点A(0,0)开始,以最高点D(1,1)结束,同时覆盖其间的所有点。这使得范围搜索变得容易,并且它也可以在3D中工作。 3D框(0,0,0)到(1,1,1)中的所有点都在Morton订单代码(0,0,0)和(1,1,1)之间。

    使用希尔伯特曲线,从(0,0)开始到(0,1)结束(在3D中可能相似)。因此,从Hilbert代码(0,0)到(1,1)执行范围查询将找不到所有点。

    因此,如果我使用希尔伯特曲线来执行3D框(0,0,0)到(1,1,1)的范围查询(作为单个数据库查询),我需要一个函数告诉我应该用什么点作为第一点,我应该用什么点作为最后一点,因为(0,0,0)和(1,1,1)将不起作用

    那么,是否有这样的功能,你给你的8(用于3D)框坐标,它返回你的范围查询中使用的第一个和最后一个点?没有它,我不能用希尔伯特曲线来解决我的问题。

    或者,在伪SQL中:

    莫顿查询: SELECT键,数据FROM表WHERE(键&gt; = Morton(最低(框)))AND(键&lt; = Morton(最高(框)))

    希尔伯特查询: SELECT键,数据FROM表WHERE(键&gt; = Hilbert(XXX(方框)))AND(键&lt; = Hilbert(YYY(方框)))

    所以我需要XXX()和YYY()。

    [编辑]这个答案的一部分是针对一些其他答案,告诉我使用希尔伯特曲线,但后来删除了他们的答案。

答案 2 :(得分:-1)

一般来说,尝试将3维减少到1维并不是很多。您可以尝试的方法:找到主轴(即通过您的点做一条线),然后将点投影到线上。这为您提供了每个点所需的一维值。当您将方框的角投射到线上并采用这些值的封闭间隔时,您将获得搜索范围。