是点A在3D附近的B点 - 距离检查

时间:2010-01-22 10:21:40

标签: c++ algorithm performance distance

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

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

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

10 个答案:

答案 0 :(得分:24)

调整距离,然后将调用放到sqrt(),这要快得多:

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

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

答案 1 :(得分:10)

如果你能满足于立方体距离而不是球形距离,那么一个非常幼稚的实现就像这样:

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

如果它被证明是瓶颈,你可以使用自己喜欢的优化Math.Abs​​的方法。

我还应该补充一点,如果其中一个尺寸通常变化小于其他尺寸,那么将其放在最后一个尺寸应该会带来性能提升。例如,如果您主要处理“地面”x-y平面上的对象,则最后检查z轴,因为您应该能够通过使用x和y检查来更早地排除碰撞。

答案 2 :(得分:3)

如果你不需要很高的准确度,你可以检查第二个点是否在立方体内(边长'2a'),而不是球体,第一个点位于中心:

|x2-x1|<a && |y2-y1|<a && |z2-z1|<a

答案 3 :(得分:2)

由于采用流水线处理器架构,现在 - 在大多数情况下,两次FPU计算效率更高,分支一次。在分支错误预测的情况下,您将停滞多年(以cpu为单位)。

所以,我宁愿选择计算方式,而不是分支方式。

答案 4 :(得分:1)

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

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

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

如果你想得到另一个附近的所有点,某种形式的空间索引也可能是合适的(也许是kd-tree)

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

如果我们要优化它,因为它运行了数十亿次,我会通过使用展开方法解决这个问题,然后使用SIMD对其进行并行化。有几种不同的方法可以做到这一点。您可以简单地在一个op中进行所有减法(x2-x1,y2-y1,z2-z1),然后在一个op中进行乘法运算。这样你就可以在方法内部进行平行,而无需重新设计算法。

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

如果你真的连续做了很多测试,你也可以使用像OpenMP这样的东西轻松优化它。

答案 9 :(得分:0)

这就是立方体距离,如果你做了很多分数,那么大多数只会进行第一次测试。

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