查找最近点的算法


18

我列出了几百个城市的纬度/经度。给定另一个位置(也是经度/纬度),我需要找到最近的城市。

由于我不使用任何GIS,因此到目前为止,显而易见的算法是对所有城市进行循环,以计算点之间的距离。

建立循环对我来说是切实可行的,但是有一些易于实现的算法可以更有效地完成该任务吗?还是一些可以帮助解决该问题的轻量级Java库?

注意:我不需要/不需要完整的GIS解决方案或繁杂的库。我更喜欢一个不太好但最简单,更轻松的解决方案,因为这是我唯一需要解决的问题。


因此,距离不正确没关系吗?而且您不想考虑可能使一个城市远于另一城市的道路(对角线与正方形)吗?
Brad Nesom 2011年

是的,道路对我来说并不重要。我需要线性距离最近的城市,因为这是为了天气预报。
lujop 2011年

1
天气预报?我希望您拥有一台超级计算机和训练有素的气象学家队伍。
迈克尔·托德

迈克尔的预言已经完成,只有我要选最接近的一个:)
lujop 2011年

Answers:


24

我在20年前设计桌面GIS时就对这个问题进行了精确调查。我们需要交互地找到点到点的距离;我们的目标是在不到1/2秒的时间内完成数千个点的计算。测试(在25 MHz 486 PC上!)显示,我们可以完全按照您的描述(使用简单的简单算法)计算所有距离,以至于无法创建更复杂的解决方案(例如四叉树结构) 。

为了计算到单个“探针”点的距离,您可以选择(a)使用以探针点为中心的等距投影来投影所有点,或者(b)采用球形地球模型并使用Haversine公式。如果您需要椭圆模型的精度,则第一个方法是合适的。在这两种情况下,计算都相当快,大概只需不到1000个滴答声:您可以使用一个处理器每秒查询大约一百万点。

够快吗?如果不是这样,则蛮力方法可以很容易地进行并行化,并直接根据处理器的数量进行缩放:只需在处理器之间划分点,然后对每个处理器找到的最接近的像素进行最终比较。

如果需要走得更快,可以使用各种近似值来筛选点。例如,如果您的纬度在-88到+88之间,并且到目前为止找到的最近点是200公里,则任何纬度与探测点的纬度相差2度以上的点都不可能更近(因为在地球,一度的纬度超过约110公里)。在许多情况下,这种预筛选可以使您每秒处理数亿个点。


1
有关Haversine
ub

4

我同意其他人的看法,即简单的循环对于“几百个城市”应该有效。

在您的应用程序中,处理椭球距离可能是主要的矫kill过正-您可能正在处理位置几乎不超过几米的天气预报。球面几何非常简单,您可以轻松地在循环中完成。

它甚至可能更简单(例如,将delta lat用作y并将delta lon * cos(lat)用作x并找到最小值x ^ 2 + y ^ 2)。您正在使用目标纬度的余弦,而该余弦仅计算一次。对于遥远的城市,这将越来越不准确,但是无论如何它们都会被拒绝,所以不要紧。假设您最近的城市通常在几百公里之内,则使用此方法与使用更精确的公式得出不同结果(最近的城市)的可能性很小,并且只有当差异足够小而“哪个预测更大时”才会发生准确”可能仍然取决于其他因素(例如:在噪声中损失)。

除非您使用嵌入式系统或慢速解释器,否则您可能可以负担得起仅使用其他人建议的球形形式。


1

这是已经说过的内容的补充,但我想我会指出选择合适的数据结构的重要性。我为.NET中的K函数编写了自己的代码,发现使用有效的集合可以大大加快工作速度。抱歉,我不知道确切速度的O表示法。我使用两个字典作为x和y坐标,并以点ID作为键。我不知道Java,所以什么也没建议。

干杯,大卫

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.