计算地理接近度的公式
Posted
技术标签:
【中文标题】计算地理接近度的公式【英文标题】:Formulas to Calculate Geo Proximity 【发布时间】:2011-01-06 23:19:31 【问题描述】:我需要在我的应用程序中实现地理邻近搜索,但我对要使用的正确公式感到非常困惑。在网络和 *** 中进行了一些搜索后,我发现解决方案是:
-
使用 Haversine 公式
选项#3 对我的 ATM 来说真的不是一个选项。现在我有点困惑,因为我一直认为Great-Circle Distance Formula 和Haversine Formula 是同义词,但显然我错了?
上面的屏幕截图取自很棒的 Geo (proximity) Search with MySQL 论文,并使用了以下函数:
ASIN, SQRT, POWER, SIN, PI, COS
我还看到了相同公式 (Spherical Law of Cosines)的变体,例如:
(3956 * ACOS(COS(RADIANS(o_lat)) * COS(RADIANS(d_lat)) * COS(RADIANS(d_lon) - RADIANS(o_lon)) + SIN(RADIANS(o_lat)) * SIN(RADIANS(d_lat))))
使用以下函数:
ACOS, COS, RADIANS, SIN
我不是数学专家,但这些公式是否相同?我遇到了一些更多变体和公式(例如 Spherical Law of Cosines 和 Vincenty'sformulae - 这似乎是最准确的),这让我更加困惑......
我需要选择一个好的通用公式在 php/mysql 中实现。谁能解释一下我上面提到的公式之间的区别?
哪个计算速度最快? 哪一个提供的结果最准确? 就结果的速度/准确性而言,哪一个最好?感谢您对这些问题的见解。
根据theonlytheory 的回答,我测试了以下大圆距离公式:
文森提公式 Haversine 公式 余弦球定律Vincenty 公式非常缓慢,但 它非常准确(低至 0.5 毫米)。
Haversine 公式 比 Vincenty 公式快得多,我能够在大约 6 秒内运行 100 万次计算,这对于我的需求来说几乎是可以接受的。
余弦公式的球面定律显示几乎是Haversine公式的两倍,并且对于大多数情况精度差异是忽略不计用例。
以下是一些测试地点:
Google 总部(37.422045
、-122.084347
)
加利福尼亚州旧金山(37.77493
,-122.419416
)
法国埃菲尔铁塔 (48.8582
, 2.294407
)
悉尼歌剧院 (-33.856553
, 151.214696
)
Google 总部 - 加利福尼亚州旧金山:
文森蒂公式:49 087.066 meters
Haversine 公式:49 103.006 meters
球面余弦定律:49 103.006 meters
Google 总部 - 法国埃菲尔铁塔:
文森蒂公式:8 989 724.399 meters
Haversine 公式:8 967 042.917 meters
球面余弦定律:8 967 042.917 meters
Google 总部 - 悉尼歌剧院:
文森蒂公式:11 939 773.640 meters
Haversine 公式:11 952 717.240 meters
球面余弦定律:11 952 717.240 meters
如您所见,Haversine 公式和余弦球定律之间没有明显差异,但是与Vincenty 公式,因为它使用地球的椭球近似值而不是球形近似值。
【问题讨论】:
我很久以前遇到过类似的问题,在一个我从未开始的项目中..在我的笔记中我发现了这个公式:AB=sqrt(pow(($Xb-$Xa),2)+pow(($Yb-$Ya),2)));
,我从来不明白它到底是做什么的..希望可以帮助你;)
@DaNieL:检查 theonlytheory 答案,他解释了何时应该使用您提供的公式。 =)
FWIW:对于那些对以英里为单位的地球半径“3956”感到困惑的人,但是根据***,如果您希望使用以公里为单位的距离,这应该近似为 3959 en.wikipedia.org/wiki/Earth_radius那将是 6371。我不确定这是否会影响您的答案@Alix,但取决于您使用的单位可能会关闭,而应该以英里为单位。
如果您的“搜索范围”足够小(
顺便说一句:orig.lat - dest.lat
的坐标[-180, 180]
不是有问题吗?如果orig.lat = -170
和dest.lat = 170
会发生什么?距离是340度?不,实际上只有 20 个。如果您使用实际的地球(地图集)坐标,您将如何解决这个问题?
【参考方案1】:
假设一台具有无限精度的机器,余弦定律和Haversine 公式将给出相同的结果。 Haversine 公式对浮点错误更稳健。但是,今天的机器具有 15 位有效数字的双精度,余弦定律可能对您很有效。这两个公式都假设地球是球形的,而 Vicenty 的迭代解(最准确)假设地球是椭球体(实际上地球甚至不是椭球体——它是大地水准面)。一些参考资料: http://www.movable-type.co.uk/scripts/gis-faq-5.1.html
它变得更好:注意余弦定律中使用的纬度以及Haversine是地心纬度,与大地纬度不同。对于一个球体,这两个是一样的。
哪个计算速度最快?
从最快到最慢的顺序是:余弦定律(5 个三角函数调用)-> hasrsine(涉及 sqrt)-> Vicenty(必须在 for 循环中迭代地解决这个问题)
哪个最准确?
维森蒂。
同时考虑速度和准确性时,哪个最好?
如果您的问题域是,对于您要计算的距离,地球可以被认为是平坦的,那么您可以计算出(我不打算详细说明)x = kx * 形式的公式经度差,y = ky * 纬度差。然后距离 = sqrt(dxdx + dydy)。如果您的问题域可以通过距离平方来解决,那么您就不必使用 sqrt,并且这个公式将尽可能快。它还有一个额外的优势,您可以计算 vector 距离 - x 是东方向的距离,y 是北方向的距离。 否则,请尝试 3 种方法并选择最适合您情况的方法。
【讨论】:
+1,很好的答案,谢谢。不过我还是有些疑惑。我以为只有一种纬度,地心纬度和大地纬度有什么区别? Google 在 Google Maps API 中提供了什么样的纬度?关于你和 DaNieL 提供的公式,你认为地球是平的是什么意思?例如,如果我想知道纽约和悉尼之间的距离,该公式会返回准确的结果吗? 我不知道 Google 在 Google Maps API 中提供了什么样的纬度,但我猜它会是大地纬度。如果距离是几公里,那么地球在这个尺度上看起来是平的——不是吗?对于 NY -> Sydney,您应该使用余弦定律。 @theonlytheory:再次感谢,我还有最后一个问题:您没有提到大圆距离公式...您能否详细说明一下这个公式与所有其他公式的区别?其他人? 没有唯一的大圆公式。上面讨论的公式是计算大圆距离的公式。你可以说它们都是大圆公式。 是的,WGS84 纬度 = 大地纬度【参考方案2】:所以你想:
按距 p0 的距离对记录进行排序 只选择到 p0 的距离小于 r 的记录诀窍是您并不需要为此计算大圆距离!您可以使用任何函数从一对点到一个真正的值严格地随着点之间的大圆距离增长。有许多这样的函数,其中一些函数的计算速度比精确大圆距离的各种公式要快得多。一个这样的函数是 3D 中的欧几里得距离。将经纬度转换为球体上的 3D 点不涉及反三角函数。
一旦你有了 x,Y,Z,你就会意识到你实际上并不需要从 p0 到你的点的距离,因为你也可以使用到 p0 处的切平面的距离。该距离也严格地随着大圆距离而增长,并且是从 X、Y、Z 作为线性组合计算出来的——甚至不需要平方根。您只需要预先计算与所需大圆距离相对应的系数和截止距离。
【讨论】:
这是一个非常好的主意。我通常不提交“好主意”的帖子,但这太棒了!在查找表中为您的指标预先计算距离,然后您就可以走了!确实是非常好的建议。以上是关于计算地理接近度的公式的主要内容,如果未能解决你的问题,请参考以下文章