确定给定半径算法内的点
Posted
技术标签:
【中文标题】确定给定半径算法内的点【英文标题】:Determine points within a given radius algorithm 【发布时间】:2011-04-25 18:18:36 【问题描述】:我不确定这是什么数学概念来支持我的问题。 ^^
假设我们有 PointA 作为参考。问题是在给定半径内找到 PointA 周围的点(使用坐标)。我的方法是计算每个点的距离(毕达哥拉斯),然后与给定的半径进行比较。我确信这在复杂性方面会很糟糕。
您可以建议什么算法? 一个指出事情的示例代码将不胜感激。谢谢。
【问题讨论】:
您想要一个函数来返回与给定坐标对之间的距离小于一定距离的每个整数坐标对吗?或者你有一组漂浮的物体,你想知道哪些物体在半径内? 你可能想看看这个 SO 答案:***.com/questions/1318595/… 【参考方案1】:如果您的点没有被索引,那实际上是一个最佳算法。有 n 个点,在没有任何其他索引的情况下,搜索所有点需要 O(n) 时间。
一种微优化是跳过 sqrt 操作,并将坐标增量的平方和与所需半径的平方进行比较。
如果您要针对同一个数据集进行多个查询,您可以使用各种索引方案,这些方案需要一些时间来计算 (O(n log n)),但可以加快查找速度 (O (m + log n),其中 m 是找到的点数。)
kd-trees 可能是从那里开始的地方。
【讨论】:
我想补充一点,如果您确信坐标都小于 sqrt(DBL_MAX),则只能跳过 sqrt 操作,这通常是这种情况。除非结果距离溢出,否则计算欧几里得距离的数值稳定方法不会溢出。 @Anonymous 我知道这是一个老问题.. 但是你将如何索引这些点?谢谢。【参考方案2】:我首先在圆圈周围创建一个盒子,然后首先测试盒子内是否有任何东西。那么你可能一直在避免计算 sqrts 和 squares。选择盒子的一个边缘(比如左边的那个)并计算它的 x 值:
xMin = xOrigin - radius
然后是任何满足的东西
xTest < xMin
可以忽略。对所有四个面重复类似的操作。测试失败的那一刻,然后停止在该点上工作。不要做不必要的计算。
这告诉您一个点很近但不一定在半径内。接下来计算:
abs(sqr(xOrigin - xTest) - sqr(yOrigin - yTest))
如果这小于半径*半径(您预先计算以避免使用平方根),那么您在半径内有一个点。
这是我能想到的最好的数据,首先是预先构建数据。
【讨论】:
【参考方案3】:这里唯一的复杂性是距离的计算。只需筛选并简化该计算即可。
如果您的“中心”是 A(x,y),那么对于任何点 B(x1, y1),请考虑:
1/ 如果 B 在您要求的点 B 的距离 d 内,那么 x-x1 < d
和 y-y1 < d
。首先检查这些条件以过滤任何“容易实现的目标”排除项。
2/ 不是计算距离,而是计算距离的平方并将其与最大允许距离的平方进行比较(显然,您应该预先计算和参考,而不是每次都重新计算)。这意味着不必为每个点计算平方根。
这些都是很小的优化,但假设这些点是未排序且随机的,这是您将获得的最佳效果。
【讨论】:
【参考方案4】:最佳答案取决于维度的数量。我假设您在 2D 或 3D 空间中工作。
一个简单的方法是制作一个单元格大小的统一网格,比如“R”。然后将所有点固定到各自的单元格。
每个查询点只与少数几个单元格相交,比如 9 个。那么您只需要检查相交的单元格。
更有效的方法是构建四叉树或 KD-tree(还有很多其他选项,但对于 2D,四叉树或 KD-tree 可以)。
在层次结构中检查圆-矩形的交点是必要的,但这在KD-Tree最近邻算法中有描述(你只需要稍微修改一下)。
如果您真的关心性能,可以构建多个网格(移动或旋转)并始终选择单元格最集中在该点上的那个,以便将搜索限制在最少数量的单元格上。
【讨论】:
以上是关于确定给定半径算法内的点的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB:如何确定 GeoJson LineString 和具有半径的点的交集