【问题标题】:which data structure is appropriate to query "all points within distance d from point p"哪种数据结构适合查询“距点 p 距离 d 内的所有点”
【发布时间】:2010-11-22 01:27:22
【问题描述】:

我有一个 3D 点云,我想有效地查询距离任意点 p(不一定是存储的点云的一部分)在距离 d 内的所有点

查询看起来像

Pointcloud getAllPoints(Point p, float d);

什么加速结构适合这个?范围树似乎只适用于查询矩形体积,而不是球体体积(当然我可以查询球体的边界框,然后整理出所有距离大于 d 的顶点 - 但也许有更好的方法这个??)

谢谢!

根据 Novelocrats 的建议,我尝试定义结构所需的功能:

SearchStructure Create(Set<Point> cloud) 
Set<Point> Query(SearchStructure S, Point p, float maxDistance)
SearchStructure Remove(Point p)
SearchStructure Insert(Point p)
SearchStructure Displace(Set<Point> displacement) //where each value describes an offsetVector to the currently present points

通常,在 n 次查询之后,点会发生位移,并且会进行一些(不是很多!)插入和删除。与所有点的边界框相比,偏移向量非常小

【问题讨论】:

  • 我认为线性时间创建可能要求太多,并且可能会阻止人们对主要问题提供好的答案。您是否也在不断地查询新的点云?如果新的点云是对现有点云进行更改的结果,那么修改结构可能会更便宜。
  • "Query" 中只有一个 'r'。我建议为后代解决这个问题。
  • Novelocrat:你是对的 - 新的点云是对旧点云的修改,但非常困难(所有点都在移动,每个点都在另一个方向上,此外,可能会添加不存在的新点之前)所以我认为每次重新创建地图将是最好的。在点云移动之前,对于包含 n 个点的地图,大约会有 n 个这样的查询
  • 为了与许多算法文本的风格保持一致,您可能希望以过程形式指定所有所需的操作: SearchStructure Create(Set cloud) Set Query(SearchStructure S, Point p, float maxDistance) 注意非成员样式;这使某人更容易查看此描述并快速了解您希望解决的问题。
  • 您应该指定这些结构在程序运行时将如何变化,而不是假定完全重建将是最好的方法。计算几何学家做了一些非常聪明的工作。考虑到他们的主要历史资金来源之一(美国海军研究办公室),移动点将是一个非常有趣的话题。您应该将所有这些信息折叠到问题中。

标签: data-structures 3d geometry distance spatial


【解决方案1】:

具有与距离相等的键和作为点本身的值的地图将允许您查询小于给定距离或在给定范围内的所有点。

【讨论】:

  • 距离不能是关键,因为 p 是一个任意点(所以 p 是查询的一个参数 - 我对此不够具体)
  • 一旦您指定了填充数据结构的点。改变点,重新填充。我认为它仍然有效。
  • 每个查询中的点是不同的。更新到点 p 的所有距离已经需要 O(n) 时间
  • 是的,我同意,但我看不出有什么出路。你呢?
【解决方案2】:

嗯,这取决于您需要数据结构的其他用途。

您可以有一个从点 p 到其他点的距离列表,按距离排序,并使用哈希图将这些列表映射到点。

map:
p1 -> [{p2, d12}, {p4, d14}, {p3, d13}]
p2 -> ...
...

您可以在地图中查找该点,并迭代列表直到距离高于所需距离。

【讨论】:

    【解决方案3】:

    您想要的是一种分解空间的结构,以便可以有效地找到特定区域。正确分解的 octreekD-tree 应该可以让您很好地做到这一点,因为您只会“打开”包含您的点 p 的树部分来查看对于附近的点。这应该让您对需要比较距离的额外点设置一个相当低的渐近界限(知道在某种程度的分解之下,所有点都足够接近)。不幸的是,我不太了解这方面的文献,无法提供更详细的指示。我遇到这些东西是来自 Barnes-Hut n-Body 模拟算法。

    这是与此密切相关的another question。 和another。 还有a third,提到了一个我以前没有听说过的数据结构(Hilbert R-Trees)。

    【讨论】:

    • 我想到了八叉树,但它似乎不合适,因为实际上可能存在范围 d 内的点,它们位于 p 本身之外的另一个部分中。所以必须查询与 p 和 d 定义的球体相交的所有部分
    • 这是一个很好的观点。如果有一些八叉树的范围树变体,那么你就是黄金。
    • SciPy 有一个 KDTree 实现,并且它有一个名为 query_ball_point 的函数正是这样做的。
    【解决方案4】:

    我不了解您的 API,您可以将 PointCloud 中位于任意球体内的所有点四舍五入,但您还说点云是存储的?在这种情况下,您不应该获得给定球体内的点云列表,否则存储点云有什么意义(请原谅双关语)?

    与其尝试提​​前定义 API,不如在需要时定义它。没有必要实现永远不会使用的东西,更不用说优化永远不会被调用的函数(当然,除非它是为了好玩:))。

    我认为您应该实现边界框剔除,然后将更详细的球体搜索作为第一个实现。也许它并没有你想象的那么严重,也许你会有更严重的瓶颈需要考虑。当您真正看到一切都按计划协同工作时,以后总是可以进行优化。

    【讨论】:

      【解决方案5】:

      VTK 可以帮忙:

      void vtkAbstractPointLocator::FindPointsWithinRadius (
      double R, double x, double y, double z, vtkIdList * result
      )

      vtkAbstractPointLocator 的子类包含用于搜索加速的不同数据结构:常规桶、kd 树和八叉树。

      【讨论】:

        【解决方案6】:

        看看A Template for the Nearest Neighbor Problem (Larry Andrews at DDJ)。它只有 2D,具有 O(log n) 的检索复杂度,但它也可能被用于 3D。

        【讨论】:

          猜你喜欢
          • 2016-01-13
          • 2015-10-11
          • 1970-01-01
          • 2020-04-07
          • 1970-01-01
          • 1970-01-01
          • 2012-09-10
          • 1970-01-01
          相关资源
          最近更新 更多