代码之家  ›  专栏  ›  技术社区  ›  kjagiello

三维距离检查中A点是否靠近B点?

  •  4
  • kjagiello  · 技术社区  · 14 年前

    我正在寻找有效的算法来检查是否一个点附近的另一个三维。

    sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2) < radius
    

    这似乎不是太快,实际上我不需要这么大的准确性。我还能怎么做?

    10 回复  |  直到 14 年前
        1
  •  24
  •   unwind    14 年前

    把电话拨到 sqrt() ,速度快得多:

    (((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2 < radius * radius
    

    当然,至少在很多情况下 radius * radius 可以提前计算并存储为 squaredRadius .

        2
  •  10
  •   Jack Ryan    14 年前

    如果你能满足于立方体距离而不是球面距离,那么一个非常简单的实现应该是这样的:

    Math.Abs(x2-x1) < radius && Math.Abs(y2-y1) < radius && Math.Abs(z2-z1) < radius 
    

    你可以使用你自己最喜欢的优化数学的方法。

    我还应该补充一点,如果其中一个维度的变化通常小于其他维度,那么最后一个维度将导致性能提升。例如,如果您主要处理“地面”X-Y平面上的对象,那么最后检查Z轴,因为您应该能够通过使用X和Y检查更早地排除碰撞。

        3
  •  3
  •   user218447    14 年前

    如果不需要大精度,可以检查第二个点是否在立方体(边长‘2a’)内,而不是第一个点位于中心的球体内:

    |x2-x1|<a && |y2-y1|<a && |z2-z1|<a
    
        4
  •  2
  •   DarthCoder    14 年前

    由于采用了流水线处理器结构,因此,在大多数情况下,两次计算FPU比一次分支更有效。在分支预测错误的情况下,您会拖延很长时间(以CPU的术语)。

    所以,我宁愿用计算的方法,而不是分支的方法。

        5
  •  1
  •   jk.    14 年前

    如果你不需要精确性,你可以检查你是否在立方体而不是球体中。

    这里也有一些选项,您可以选择包含球体(没有假阴性)的立方体,立方体的体积与球体相同(一些假阳性和阴性,但最大误差最小化),立方体包含在球体内(没有假阳性)。

    这种技术也很好地扩展到更高的维度。

    如果你想让所有的点靠近另一个点,某种形式的空间索引也可能是合适的(也许是kd树)

        6
  •  1
  •   ziggystar    14 年前

    如果必须对照许多其他点进行检查,可以考虑使用空间排序方法快速发现靠近某个位置的点。查看此链接: wiki link

        7
  •  0
  •   Mick    14 年前

    使用max(abs(x1-x2)、abs(y1-y2)、abs(z1-z2)

        8
  •  0
  •   Boolean    14 年前

    删除平方根后,如果值变大,则最好应用日志。

        9
  •  0
  •   Mr. Boy    14 年前

    如果我们要优化它,因为它运行了数十亿次,我会用 退绕 方法,然后使用simd对其进行并行化。有几种不同的方法可以做到这一点。你可以简单地在一个操作中做所有的减法(x2-x1,y2-y1,z2-z1),然后在一个操作中做乘法。这样你就不用重新设计你的算法就可以在方法内部进行网格化。

    或者您可以编写一个批量版本来计算(x2-x1)^2+(y2-y1)^2+(z2-z1)^2-r^2的许多元素,并将结果存储在一个数组中。您也许可以获得更好的吞吐量,但这意味着重新设计您的算法,并取决于测试的用途。

    如果你真的连续做了很多测试,你也可以使用类似openmp的东西轻松地优化这个。

        10
  •  0
  •   Mike Dunlavey    14 年前

    这就是立方体的距离,如果你做了很多点, 它只做第一次测试。

    close = (abs(x2-x1) < r && abs(y2-y1) < r && abs(z2-z1) < r);