找到离给定点最近的点

Posted

技术标签:

【中文标题】找到离给定点最近的点【英文标题】:Finding the closest point to a given point 【发布时间】:2009-05-27 01:41:57 【问题描述】:

我已经到处搜索了这个,但我似乎找不到最好的方法。我有大约 22000 个纬度/经度点,我想找到最接近 iPhone 当前位置的点。我见过人们询问四叉树、Dijkstra 算法和空间数据库。哪个最适合 iPhone?空间数据库似乎最简单,但我不确定。

编辑:实际上有超过 20,000 点。你认为遍历所有这些是这样做的方法吗?不过感谢您的意见。

谢谢。

【问题讨论】:

过早的优化是万恶之源。特别是,我认为您无法在小于 O(n) 的时间内找到最小值(您必须至少检查每个元素一次以检查它是否最接近),所以我认为您唯一可以优化的是距离计算(仍然应该很快)。 看这个答案***.com/a/12997900/779408 【参考方案1】:

其实,Lat/Long 点最好使用Haversine(大圆)计算,否则距离越来越大会出错,尤其是使用Jherico's answer 中的简单三角函数时。

快速搜索提供了这个 javascript 示例:

var R = 6371; // km Radius of earth
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
        Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;

在数据结构方面,Geohash 值得一看。

【讨论】:

很高兴知道。然而,最初的问题不是关于距离的计算,而是关于要使用的数据结构。除非应用程序需要实时不断地重新计算,否则我同意 Jherico 的观点:简单的线性搜索就足够了。 @raindog-2:Jherico 和 Chaos 的答案都假设线性搜索 - O(N)。只是 Chaos 的答案给出了准确的计算,而 Jherico 的假设是平坦的地球。 非常正确 - 我会使用有序的距离集,然后第一个(或最后一个)点就是您感兴趣的点。 我只是想找到地球上最近的点,有大约 2k 点可供选择,这意味着大圆路线和简单三角之间的不准确度越来越高不会产生影响 好吧,即使在经度的环绕点有 2000 个点,您仍然可能有非常糟糕的选择。尤其是在两极附近。【参考方案2】:

如果你需要比 O(N) 更好的东西,你只能先支付 N lg N 来构建某种空间散列(四叉树、八叉树、散列网格或类似的)。然后每个测试将大约为 O(lg N),如果有很多一致性(通常有),通常可以通过缓存您检查的最后一个位置来更好地进行测试。

我可能会在欧拉(地心,XYZ)空间中构建一个八叉树,因为这可以让我获得“真实”的距离,而不是“扭曲”的纬度/经度距离。但是,在实践中,纬度/经度空间中的四叉树可能会运行得很好。命中后,您将保留该树节点(假设树在运行时未重新构建),并且下一个查询从该树节点开始遍历,并且只需要担心可能更接近的节点上一点离上一个答案更远了。

【讨论】:

【参考方案3】:

就像你在 iPhone 上一样,你可以使用 CoreLoaction 来执行地理距离 - 使用 CLLocation 的– getDistanceFrom:

我很想在所有 2k 点上使用蛮力线性搜索,如果这还不够快,请切换到 GeoHash 之类的东西来存储针对您的点的元数据进行搜索。

【讨论】:

【参考方案4】:

为什么不将地球平铺成区域? (想想十六进制。)然后,当您将点添加到列表中时,或者在一个大的预处理循环中,为每个点存储它所在的区域。

那么,在十六进制 X 中搜索点 A 附近的点时,只需要检查十六进制 X 中的点以及最多 3 个相邻的十六进制。

如果要检查的点仍然太多,请添加子区域。

【讨论】:

【参考方案5】:

您必须考虑到要使用 Dijkstra,您必须知道您在图中的节点位置,而不是您要解决的问题;你不在图中,但你想知道离你最近的点

很简单,正如 Chaos 告诉你的那样,你必须计算你的位置和所有 20.000 个点之间的所有距离,然后对它们进行排序

【讨论】:

【参考方案6】:

我认为这个算法有效:

创建一个按纬度排序的数组 创建一个按经度排序的数组

要找到最近的,首先按纬度找到最近的 在纬度数组中进行二进制搜索。做 经度数组相同。现在你有 2 分,1 纬度最近,经度最近。 通过勾股定理计算到每个点的距离。 最近的点获胜。

罗杰

【讨论】:

这是不正确的。想象一下您的参考点位于 (0,0)。 y 上最近的点可能在 (100,10),而 x 上最近的点可能在 (10,100)。您可能在 (11, 11) 有一个比这两个更近的点,但算法会错过它

以上是关于找到离给定点最近的点的主要内容,如果未能解决你的问题,请参考以下文章

快速算法在平面上找到离给定点最近的 x 个点

获取离质心最近的点,scikit-learn?

在数组中查找不等于给定点的最近点

最近的点对算法

平面最近点对

狄克斯特拉算法(图的最短路问题)