4

我有一组相当大的 2D 点(~20000),对于 xy 平面中的每个点,我想确定集合中的哪个点最接近。(其实点的类型不同,我只想知道哪种类型最接近。而xy平面是位图,比如640x480。)

这个问题的答案“所有 k 最近的邻居在 2D,C++ ”我得到了制作网格的想法。我创建了 n*m C++ 向量并将点放入向量中,具体取决于它属于哪个 bin。这个想法是你只需要检查 bin 中点的距离,而不是所有点。如果 bin 中没有点,则继续以螺旋方式处理相邻的 bin。

不幸的是,我后来只看了 Oli Charlesworth 的评论:

不幸的是,不仅仅是相邻的(例如,考虑到单元格 2 中向东的点可能比单元格中正向东北的点更接近;这个问题在更高维度上会变得更糟)。另外,如果相邻的单元格中恰好有不到 10 个点怎么办?在实践中,您将需要“盘旋”。

幸运的是,我已经弄清楚了螺旋式代码(这里有一个不错的 C++ 版本,在同一个问题中还有其他版本)。但我仍然存在问题:

  • 如果我在一个单元格中找到一个命中,则相邻单元格中可能有一个更接近的命中(黄色是我的探针,红色是错误的选择,绿色是实际最近的点):

    在此处输入图像描述

  • 如果我在相邻的单元格中发现命中,则可能会在 2 步外的单元格中命中,正如 Oli Charlesworth 所说:

    在此处输入图像描述

  • 但更糟糕的是,如果我在两步外的牢房中发现命中,三步外的命中仍然可能会更近地命中!这意味着我必须考虑所有 dx,dy= -3...3 或 49 个单元格的单元格!

    在此处输入图像描述

现在,实际上这不会经常发生,因为我可以选择我的 bin 大小,这样单元格就足够填充了。不过,我希望得到一个正确的结果,而不是遍历所有点。

那么我如何找出何时停止“螺旋”或搜索?我听说有一种方法有多个重叠网格,但我不太明白。是否有可能挽救这种网格技术?

4

4 回答 4

2

对于您的任务,通常Point Quadtree使用 a ,尤其是当点分布不均匀时。

为了节省主内存,您还可以使用使用存储桶的 PM 或 PMR-Quadtree。

您在您的单元格中搜索,在最坏的情况下搜索该单元格周围的所有四边形单元格。

您也可以使用k-d tree.

于 2013-04-04T20:51:54.177 回答
2

由于您的位图尺寸不大,并且您想计算每个 (x,y)的最近点,您可以使用动态规划。

令为到集合中最近点V[i][j]的距离,但考虑集合中位于“矩形”[(1, 1), (i, j)] 中的点。(i,j)

那么V[i][j] = 0如果 中有一个点(i, j),或者的三个邻居之一在V[i][j] = min(V[i'][j'] + dist((i, j), (i', j')))哪里:(i', j')(i,j)

IE

  • (i - 1, j)
  • (i, j - 1)
  • (i - 1, j - 1)

这为您提供了最小距离,但仅适用于“左上”矩形。我们对“右上”、“左下”和“右下”方向做同样的事情,然后取最小值。

复杂度为 O(平面大小),这是最优的。

于 2013-04-04T20:20:30.220 回答
1

我正在尝试的解决方案

  • 首先制作一个网格,使每个框平均有 1 个(如果您想要更大的扫描,则更多)点。
  • 选择中心框。继续以循环方式选择邻居框,直到找到至少一个邻居。此时您可以选择 1 个或 9 个左右的框
  • 多选一层相邻框
  • 现在您有一个相当小的点列表,通常不超过 10 个,您可以将其打入距离公式以找到最近的邻居。

由于每个框平均有 1 个点,因此您将主要选择 9 个框并比较 9 个距离。可以根据您的数据集属性调整网格大小以获得更好的结果。

此外,如果您的数据有很大的差异,您可以尝试 2 个级别的网格(甚至更多),因此如果选择有效并且在单个查询中返回超过 50 个点,请使用 1/10 的网格开始下一次网格搜索尺寸 ...

于 2015-10-17T05:06:38.853 回答
0

一种解决方案是构建具有不同网格大小的多个分区。

假设您在 1、2、4、8、.. 级别创建分区

现在,在网格大小 1 中搜索一个点(您基本上是在 9 个方格中搜索)。如果搜索区域中有一个点,并且到该点的距离小于 1,则停止。否则移动到下一个网格大小。

与仅创建一级分区相比,您需要构建的网格数量大约是两倍。

于 2013-04-04T20:21:03.730 回答