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

Posted

技术标签:

【中文标题】在任意坐标周围找到半径为 r 的球体中的所有点【英文标题】:Find all points in sphere of radius r around arbitrary coordinate 【发布时间】:2012-06-15 15:32:40 【问题描述】:

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

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

-朴素算法,遍历所有点并计算距离

-将空间划分为长度为 R 的立方体的网格,并将点放入其中。这样,对于每个点,我只需要查询直接相邻的存储桶。这有显着的加速

-我尝试使用曼哈顿距离作为启发式方法。也就是说,在桶内,在计算到任何点的距离之前,使用曼哈顿距离过滤掉那些不可能在半径 R 内的(即曼哈顿距离

编辑:为了比较距离,我使用平方距离来避免使用 sqrt 函数。

显然,我能加快多少速度会有一些限制,但我现在可以使用任何建议来尝试。

这在算法层面可能并不重要,但我正在使用 C 语言工作。

【问题讨论】:

sqrt() 是一个昂贵的函数。为了加快速度,您应该将另一边平方并进行比较。 我已经这样做了。将编辑问题以反映这一点,谢谢。 我发现问题陈述难以解析。您是否试图找到任意点的 R 内的点子集(在您称为 N 的列表中)?什么是“元素”——N 中的点? 这似乎是对的。我进行了编辑,以使问题中的术语更加自洽。 我还是不清楚。从查询到查询有什么变化?积分列表?球的中心?半径?上述所有的?您谈到预处理是为了优化多个查询,但不清楚什么是不变的。 【参考方案1】:

将积分存储在具有三个维度的 k-d tree 中可能会提高速度。这将使您在 O(log n) 摊销时间内进行搜索。

【讨论】:

kdtree sphere 查询需要 O(n^(1-1/d)),而不是 O(log(n))。【参考方案2】:

不要比较半径,要比较半径的平方。原因是,如果两点之间的距离小于R,那么距离的平方小于R^2

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

【讨论】:

【参考方案3】:

我建议使用 K-D 树或 z 曲线: http://en.wikipedia.org/wiki/Z-order_%28curve%29

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

Nicolas Brodu's NEIGHAND 库完全按照您的意愿行事,改进了 bin-lattice 算法。

更多细节可以在他的文章中找到:Query Sphere Indexing for Neighborhood Requests

【讨论】:

【参考方案6】:

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

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

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

对于一个点 P(x, y, z) 和一个球体 S(x_s, y_s, z_s, radius),隶属度检验为:

(x - x_s)^2 + (x - y_s)^2 + (z - z_s)^2 < radius^2

其中radius^2 可以为查询中的所有点预先计算一次(避免任何平方根计算)。这些计算都是独立的,您可以并行计算多个点。使用 SSE 之类的东西,您可能一次可以做四个。如果您有很多点要测试,您可以拆分列表并进一步并行处理多个内核的工作。

【讨论】:

这当然有效。这就是我所说的朴素算法。我敢肯定,如果我只做 1 个查询,那将是最快的。我遇到的问题是我在 100k-1m 点上进行 10k-100k 查询。这变成了一个非常昂贵的步骤,即使尽可能并行。因此,如果有一种数据结构可以加速单个查询,它可能会更快,即使初始构建成本很高。 我明白了。我对这个问题感到困惑。我认为点列表因查询而异。感谢您的澄清。

以上是关于在任意坐标周围找到半径为 r 的球体中的所有点的主要内容,如果未能解决你的问题,请参考以下文章

已知一个圆经过三点,怎样求圆心坐标啊?

给定中心坐标(纬度/经度)、半径(米)和中心角(度)的球体(地球)上的圆弧面积 [关闭]

python程序设计:输入球体半径r,计算球体的体积和表面积

给定一个图像,一个像素点和一个以像素为单位的半径。如何找到它创建的圆形边框的像素坐标

如何在球体周围“包裹”方形图像

OPENGL初学