Algorithm 找到半径为r的球体中围绕任意坐标的所有点

Algorithm 找到半径为r的球体中围绕任意坐标的所有点,algorithm,Algorithm,我在寻找一个有效的算法,对于一个已知高度、宽度和长度的空间,给定一个固定半径R,以及一个点列表N,在该空间中有三维坐标,将找到网格上任意点的固定半径R内的所有点。此查询将使用不同的点进行多次,因此,作为快速查询的交换,一个昂贵的预处理/排序步骤可能是值得的。对于我正在开发的应用程序来说,这是一个有点瓶颈的步骤,所以任何时候我可以切断它都是有用的 到目前为止我已经尝试过的事情: -朴素算法,迭代所有点并计算距离 -将空间划分为一个具有长度为R的立方体的网格,并将点放入其中。这样,对于每个点,我只需

我在寻找一个有效的算法,对于一个已知高度、宽度和长度的空间,给定一个固定半径R,以及一个点列表N,在该空间中有三维坐标,将找到网格上任意点的固定半径R内的所有点。此查询将使用不同的点进行多次,因此,作为快速查询的交换,一个昂贵的预处理/排序步骤可能是值得的。对于我正在开发的应用程序来说,这是一个有点瓶颈的步骤,所以任何时候我可以切断它都是有用的

到目前为止我已经尝试过的事情:

-朴素算法,迭代所有点并计算距离

-将空间划分为一个具有长度为R的立方体的网格,并将点放入其中。这样,对于每个点,我只需要查询紧邻的桶。这大大加快了速度


-我试着用曼哈顿距离作为启发。也就是说,在桶内,在计算到任何点的距离之前,使用曼哈顿距离过滤掉那些不可能在半径R内的距离(也就是说,曼哈顿距离的人不在半径上进行比较,而是在半径的平方上进行比较。原因是,如果两点之间的距离小于
R
,那么距离的平方小于
R^2


这样,当您使用距离公式时,您不需要计算平方根,这是一个非常昂贵的操作。

将点存储在三维空间中可能会获得速度优势。这将使您在O(logn)摊销时间内进行搜索。

我建议使用K-D树或z曲线:

怎么样?(参考Topcoder教程)它可以扩展到n维,而且编码更简单。

[我可能误解了这个问题。我发现问题陈述很难解析。]

在过去,设计一种带有“提前退出”的算法通常是很好的,这种算法会进行测试,以避免更昂贵的计算。在现代处理器中,分支预测的失败通常非常昂贵,而那些提前退出的测试实际上比完整的计算更昂贵。(唯一确定的方法是测量。)

在这种情况下,计算非常简单,因此最好避免构建数据结构或进行任何巧妙的早期检查,而是尝试优化、矢量化和并行化以获得所需的吞吐量

对于点p(x,y,z)和球体S(x_S,y_S,z_S,半径),隶属度测试为:

(x - x_s)^2 + (x - y_s)^2 + (z - z_s)^2 < radius^2
(x-x-us)^2+(x-y-us)^2+(z-z-us)^2
其中,
半径^2
可以为查询中的所有点预先计算一次(避免任何平方根计算)。这些计算都是独立的,您可以并行计算多个点。使用SSE之类的工具,您可能一次可以进行四个点的计算。如果您有多个点要测试,您可以拆分列表,并进一步将工作并行化到多个核中。

库完全按照您的要求执行,改进bin lattice al戈里希姆


更多细节可以在他的文章中找到:

sqrt()
是一个昂贵的函数。要加快速度,你只需将另一面平方并进行比较。我已经这样做了。我将编辑问题以反映这一点,谢谢。我发现问题陈述很难解析。你是否正在尝试找到点的子集(在您称为N的列表中)在任意点的R范围内的?什么是“元素”--N中的点?似乎是这样。我已经进行了编辑,以使问题中的术语更加自洽。我仍然不清楚。在不同的查询中会有什么变化?点列表?圆心?半径?所有这些?您谈到预处理是为了优化多个查询,但不清楚是什么是不变的。这当然有效。这就是我所说的朴素算法。我确信如果我只做一个查询,它会是最快的。我的问题是,我在100k-1m点上做10k-100k查询。这会变成一个非常昂贵的步骤,即使尽可能并行化。因此,如果有一个数据结构可以加快单个查询的速度,可能会更快,即使初始构造很昂贵。我明白了。我对这个问题感到困惑。我认为不同查询的点列表是不同的。感谢您的澄清。kdtree球体查询需要O(n^(1-1/d)),而不是O(log(n))。