找到另一个点的某个半径内的所有点

时间:2015-06-29 17:11:35

标签: algorithm 2d point

我正在制作一个简单的游戏并偶然发现了这个问题。假设2D空间中的几个点。我想要的是让彼此接近的点以某种方式相互作用。

让我在这里画一张照片,以便更好地理解这个问题: image of the problem

现在,问题不是计算距离。我知道该怎么做。

起初我有大约10分,我可以简单地检查每个组合,但正如你已经可以假设的那样,随着点数的增加,这是非常低效的。如果我总共有一百万分,但所有这些分数彼此相距很远怎么办?

我试图找到一个合适的数据结构或一种方法来查看这个问题,所以每个点都只能考虑周围而不是整个空间。有没有任何已知的算法?我并不完全知道如何命名这个问题,所以我可以准确地说出我想要的内容。

如果你不知道这些已知的算法,那么所有的想法都是非常受欢迎的。

6 个答案:

答案 0 :(得分:10)

这是 range searching 问题。更具体地说 - 2-d循环范围报告问题。

引自"Solving Query-Retrieval Problems by Compacting Voronoi Diagrams" [Aggarwal, Hansen, Leighton, 1990]

  
      
  • 输入:欧几里德平面E²中n个点的集合P
  •   
  • 查询:查找E²中磁盘中包含的P的所有点,其中半径r以q为中心。
  •   

"Optimal Halfspace Range Reporting in Three Dimensions" [Afshani, Chan, 2009]中获得了最佳结果。他们的方法需要O(n)空间数据结构,该结构支持O(log n + k)最坏情况时间的查询。该结构可以通过在O(n log n)预期时间内运行的随机算法进行预处理。 (n是输入点的数量,输出点的数量为k)。

CGAL库支持循环范围搜索查询。请参阅here

答案 1 :(得分:5)

您仍然需要遍历每一点,但您可以执行两项优化:

1)你可以通过检查x1是否来消除明显的点。半径和y1<半径(就像布伦特在另一个答案中已提到的那样)。

2)您可以计算距离的平方并将其与允许半径的平方进行比较,而不是计算距离。这样可以避免执行昂贵的平方根计算。

这可能是您将获得的最佳表现。

答案 2 :(得分:3)

空间分区就是你想要的...... https://en.wikipedia.org/wiki/Quadtree

答案 3 :(得分:2)

如果您可以按x和y值对这些点进行排序,那么您可以快速选出那些位于中心点框内的点(二进制搜索?):x + - r,y + - r 。一旦你有了这个点的子集,那么你可以使用距离公式来看它们是否在半径范围内。

答案 4 :(得分:2)

这看起来像是最近邻居的问题。您应该使用kd树来存储点。

https://en.wikipedia.org/wiki/K-d_tree

答案 5 :(得分:0)

我假设您具有最小和最大X和Y坐标?如果是这样的话。

调用我们的半径R,Xmax-Xmin X和Ymax-Ymin Y。

具有[X / R,Y / R]双向链接列表的2D矩阵。将每个点结构放在正确的链表上。

要查找需要与之交互的点,只需检查您的单元格以及您的8个邻居。

示例:如果X和Y分别为100,R为1,则在单元格[43,77]中的43.2、77.1处放置一个点。您将检查单元格[42,76] [43,76] [44,76] [42,77] [43,77] [44,77] [42,78] [43,78] [44,78]比赛。请注意,并非您自己的框中的所有单元格都会匹配(例如43.9,77.9在同一列表中,但相距超过1个单位),并且您将始终需要检查所有8个邻居。

随着点的移动(听起来像它们会移动吗?),您只需断开它们的链接(使用双向链接列表即可轻松快捷)并在其新位置重新链接。移动任何点都是O(1)。全部移动为O(n)。

如果该数组大小提供了太多的单元格,则可以使用相同的算法和可能相同的代码制作更大的单元格;只是为较少的候选点做好实际接近做好准备。例如,如果R = 1且地图是R的一百万乘以R的一百万,那么您将无法制作那么大的2D数组。最好让每个单元格宽1000个单位?只要密度较低,就可以使用与以前相同的代码:仅将每个点与该单元格中的其他点以及相邻的8个单元格进行对照。为更多不在R范围内的候选人做好准备。

如果某些单元格会有很多点,每个单元格都有一个链表,那么该单元格应该有一个由X坐标索引的红黑树吗?即使在同一个单元中,绝大多数其他单元成员也距离太远,因此只需将树从X-R遍历到X + R。与其遍历所有点,而不是潜入每个人的树中,不如您可以遍历树,在R内寻找X坐标,如果/当发现它们时计算距离。当您从低X到高X遍历一个单元格的树时,只需在前R个条目中检查左侧树的相邻单元格即可。

您还可以转到小于R的像元。候选像的数量较少,但未能足够接近。例如,对于R / 2,您将检查25个链接列表而不是9个,但是平均(如果随机分布)要检查的点数为25/36分。这可能是次要的收获。