Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在统一网格上查找到点云中最近点的距离_Algorithm - Fatal编程技术网

Algorithm 在统一网格上查找到点云中最近点的距离

Algorithm 在统一网格上查找到点云中最近点的距离,algorithm,Algorithm,我有一个大小为AxBxC的3D网格,网格中的点之间的距离d相等。给定多个点,根据以下假设,找到每个网格点到最近点的距离(每个网格点应包含到点云中最近点的距离)的最佳方法是什么 假设A、B和C相对于d相当大,给出的网格可能为500x500x500,并且大约有一百万个点 还假设,如果到最近点的距离超过D,我们不关心最近点距离,可以安全地将其设置为某个较大的数字(D可能是D的2到10倍) 由于将有大量网格点和点可供搜索,一个简单的穷举: for each grid point: for each

我有一个大小为AxBxC的3D网格,网格中的点之间的距离d相等。给定多个点,根据以下假设,找到每个网格点到最近点的距离(每个网格点应包含到点云中最近点的距离)的最佳方法是什么

假设A、B和C相对于d相当大,给出的网格可能为500x500x500,并且大约有一百万个点

还假设,如果到最近点的距离超过D,我们不关心最近点距离,可以安全地将其设置为某个较大的数字(D可能是D的2到10倍)

由于将有大量网格点和点可供搜索,一个简单的穷举:

for each grid point:
   for each point:
     if distance between points < minDistance:
       minDistance = distance between points

基本上:将点放入桶中,向外进行径向搜索,直到为每个网格点找到一个点。这是解决问题的好方法,还是有更好/更快的方法?最好采用有利于并行化的解决方案

看一看。它们是一种数据结构,通常用于高效地划分3d空间,以提高查找空间上彼此相邻的对象的效率。

一种方法,可能适合也可能不适合您的应用程序,就是重塑你的思维,将每个网格“点”定义为一个立方体的中心,这个立方体将你的空间划分为多个单元。然后,您将拥有一个此类单元的3D阵列,并将点存储在单元中——选择最合适的数据结构。用你自己的话来说,首先把分数放在桶里

我猜您可能正在运行某种大规模模拟,我建议的方法在此类应用程序中并不罕见。在每个时间步(如果我猜对了的话),您必须重新计算从单元到最近点的距离,并将点从一个单元移动到另一个单元。这将很容易并行化


编辑:用谷歌搜索粒子和粒子网格可能会给你带来一些想法。

你可以在你的采样点上建立一个(维基百科),然后为你的每个网格点询问它。维基百科页面上提到了很多算法。也许八叉树、kd树或R树是合适的。

事实上,我认为我有更好的方法,因为网格点的数量远大于采样点的数量。让| Grid |=N,| Samples |=M,那么最近邻搜索算法将类似于O(nlgm),因为您需要查找所有N个网格点,并且每个查找都是(最佳情况)O(lgm)

而是在采样点上循环。为每个栅格点存储到目前为止找到的最近的采样点。对于每个采样点,只需检查采样距离D内的所有栅格点,以查看当前采样是否比任何先前处理的采样更接近

运行时间为O(N+(D/D)^3m),当D/D较小时,运行时间应更好


即使当D/D更大时,如果您能制定一个截止策略,您可能仍然可以。例如,如果我们正在检查距离样本5的网格点,并且该网格点已标记为距离前一个样本1,则不需要检查“超出”该网格点的所有网格点,因为前一个样本保证比我们正在处理的当前样本更近。你所要做的就是(我认为这并不容易,但应该是可行的)定义“超越”的含义,并找出如何迭代网格以避免对“超越”这些网格点的区域进行任何工作。

关于Keith Randall方法的说明, 围绕起始点展开壳或立方体:
可以按各种顺序展开。下面是一些python风格的伪代码:

S = set of 1m startpoints
near = grid 500x500x500 -> nearest s in S
    initially s for s in S, else 0
for r in 1 .. D:
    for s in S:
        nnew = 0 
        for p in shell of radius r around s:
            if near[p] == 0:
                near[p] = s
                nnew += 1
        if nnew == 0:
            remove s from S  # bonk, stop expanding from s
“从s开始停止扩张”在1d中可以(砰左,砰右); 但是2d/3d壳是不规则的。
一次完成整个立方体更容易/更快:

near = grid 500x500x500 -> { dist, nearest s in S }
    initially { 0, s } for s in self, else { infinity, 0 }
for s in S:
    for p in approximatecube of radius D around s:
        if |p - s| < near[p].dist:  # is s nearer ?
            near[p] = { |p - s|, s }
也是fwiw,, 根据埃里克的数字,平均有500^3/1M~2^7~5^3个空的 每个采样点。 所以我最初认为5x5x5立方体大约有1M个采样点 将覆盖整个网格的大部分。
并非如此,~1/e的网格点保持为空——泊松分布。

还搜索“3d voronoi图”。@starblue由于OP正在处理晶格,我不理解voronoi图的相关性。OP有晶格点和采样点。您可以使用样本点制作一个Voronoi图,并使用晶格点进行查询。但是3d Voronoi图很昂贵,不确定这是不是最好的策略。在长期运行的科学模拟中,在每个时间步构建10^6个点的3d Voronoi图的想法让我一想到就头疼:-(我认为@Mark强调了一个非常重要的点:这是一次计算还是云移动,并且在每一步之间进行相同的计算?如果要链接多个计算,则易于更新的结构将是至关重要的,因此它将形成解决方案…抱歉,我没有指出这一点d确实会移动,每次都必须重新计算。
near = grid 500x500x500 -> { dist, nearest s in S }
    initially { 0, s } for s in self, else { infinity, 0 }
for s in S:
    for p in approximatecube of radius D around s:
        if |p - s| < near[p].dist:  # is s nearer ?
            near[p] = { |p - s|, s }
0 1 2 3 4 
1 1 2 3 4 
2 2 3 4 4
3 3 4 4
4 4 4