找到一个点在内部并且最接近的球体的最快方法

Posted

技术标签:

【中文标题】找到一个点在内部并且最接近的球体的最快方法【英文标题】:Fastest way to find sphere a point is inside and closest to 【发布时间】:2018-06-13 18:54:28 【问题描述】:

在 3D 系统中,我有一堆不同半径的球体散布在各处。

确定一个点在哪个球体内的最快方法是什么,以及它是否在多个球体内 - 也是基于球体中心的最近球体。

bruteforce 方法是简单地遍历所有球体,计算到该点的距离,检查该距离是否小于球体的半径,然后找到距离最短的球体。

但是,我有几百万个点要检查(大约有 10 万个球体),所以这会非常慢。

我的另一个想法是构建某种 BVH Acceleration 结构,并为每个单元保存最接近的球体。但是,也存在一个单元格可能被两个或多个球体重叠的情况等。因此需要考虑很多边缘情况。

毕竟,BVH 树的计算不应该比蛮力慢。

有什么想法吗?

【问题讨论】:

检查距离平方是否小于半径平方。不需要所有那些缓慢的平方根。 对空间进行分区。 查找“八叉树”以了解空间分区的常用方法。 【参考方案1】:

我最终通过 OpenCL 在 GPU 上使用蛮力方法完成了它 - 超级快 :)

【讨论】:

【参考方案2】:

也许 清扫和修剪¹ 式的方法可以在这里工作?

Handwavy 算法(2D 案例):

    创建两个数组AxAy。 从 n 个圆中选择一个圆并投影到 x 轴上,即将圆心的 x 分量加上减去半径存储在 Ax 中。将圆也投影到 y 轴上。 对所有剩余的圆圈重复第 2 步。 将每个点的分量也存储在 AxAy 中。 排序AxAy

从这里开始,一个点 P 只能在一个球体 S 内,前提是它包含在 S 的所有三个区间内。

现在,可以确定每个点是否包含在球体中:迭代 Ax 并在每次“输入”间隔时递增计数器 k并在您“退出”一个间隔时减少 k。如果当您扫入一个点时计数器为 k,则该点包含在 k 个间隔的集合 I 中。检查该点是否包含在 Ay² 中任何对应的 I 区间内。

同样,AxAy 的排序应该有助于找到最接近某个点的球体。

我相信这种方法可以(大大)改进,并且在实践中并行化的蛮力可能会更快。

Handwavy 算法(3D 案例):类似于 2D 案例。

¹。 http://www.cs.jhu.edu/~cohen/Publications/icollide.pdf

²。我显然省略了很多 d̶e̶t̶a̶i̶l̶s̶̶I̶̶h̶a̶v̶e̶̶y̶e̶t̶̶t̶o̶̶f̶i̶g̶u̶r̶e̶̶o̶u̶t 无聊的簿记细节。

【讨论】:

以上是关于找到一个点在内部并且最接近的球体的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

找到最接近一组圆的点

加速算法在两个二维点数据集中找到最接近的项目

四叉树最近邻算法

Mongoose 地理空间查询查找所有包含给定点的用户球体

从最后可用数据创建 DataFrame 的最快方法

数百万个 3D 点:如何找到最接近给定点的 10 个?