计算地理邻近度的公式


71

我需要在我的应用程序中实现地理邻近搜索,但是对于要使用的正确公式我非常困惑。在Web和StackOverflow中进行一些搜索后,我发现解决方案是:

  1. 使用Haversine公式
  2. 使用大圆距离公式
  3. 在数据库中使用空间搜索引擎

选项#3真的不是我的ATM选项。现在,我有点困惑了,因为我总是说大圆距离公式Haversine公式同义词,但显然我错了吗?

Haversine公式

上面的屏幕截图来自MySQL出色的Geo(邻近)搜索文件,并使用以下功能:

ASIN, SQRT, POWER, SIN, PI, COS

我还看到了同一个公式余弦的球形定律)的不同形式,例如:

(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

我不是数学专家,但是这些公式相同吗?我遇到了更多的变化和公式(例如余弦球形定律Vincenty的 公式-似乎是最准确的),这让我更加困惑...

我需要选择一个良好的通用公式以在PHP / MySQL中实现。谁能解释我上面提到的公式之间的区别?

  • 哪一个计算最快?
  • 哪一个提供最准确的结果?
  • 就结果的速度/准确性而言,哪一个最好?

感谢您对这些问题的见解。


基于唯一的理论答案,我测试了以下大圆距离公式:

  • 文森特公式
  • Haversine公式
  • 余弦球定律

Vincenty公式是死的慢,但是它是相当准确的(下降到0.5mm)

haversine公式是远远比Vincenty公式更快,我能够在大约6秒,这是我的需要非常接受试验1次亿次运算。

余弦公式的球面法发现是几乎快一倍的haversine公式和精度差是neglectfulness对于大多数使用情况。


以下是一些测试位置:

  • Google总部37.422045-122.084347
  • 加利福尼亚州旧金山37.77493-122.419416
  • 法国埃菲尔铁塔48.85822.294407
  • 悉尼歌剧院-33.856553151.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公式相比,两者的距离偏移都高达22公里,因为它使用的是地球的椭圆近似而不是球形。


1
很久以前,我在一个从未开始过的项目中遇到了类似的问题。.在我的笔记中,我找到了这个公式:AB=sqrt(pow(($Xb-$Xa),2)+pow(($Yb-$Ya),2)));,我从来不完全知道它的作用..希望能为您提供帮助;)
Strae 2010年

@DaNieL:检查唯一的理论答案,他解释了何时应该使用提供的公式。=)
Alix Axel,2010年

2
FWIW:对于那些被“ 3956”(即以英里为单位的地球半径)感到困惑的人来说,但是根据维基百科,如果您希望以KM为单位的距离进行工作,则应该将其近似为3959 en.wikipedia.org/wiki/Earth_radius是6371。我不确定这是否会影响您的答案@Alix,但取决于您使用单位的#号可能会关闭,而应该以英里为单位。
克里斯·马里西奇

如果您的“搜索范围”足够小(<500 km),则可以使用毕达哥拉斯对结果进行排序。距离不是精确的(世界不是平坦的,那太糟糕了),但是距离的顺序将是正确的。
鲁迪

1
顺便说一句:orig.lat - dest.lat坐标不是错[-180, 180]吗?如果orig.lat = -170和会发生什么dest.lat = 170?距离是340度?不,实际上只有20个。如果您正在使用实际的地球(地图集)坐标,该如何解决?
鲁迪

Answers:


36

假设机器精度无限,则余弦定律和Haversine公式将给出相同的结果。Haversine公式对浮点错误更健壮。但是,今天的机器具有15位有效数字量级的双精度,并且余弦定律可能对您来说很好。这两个公式都假设球面土,而维森特的迭代解(最精确)假定椭圆体土(实际上,地球甚至不是椭圆体-它是一个大地水准面)。一些参考:http : //www.movable-type.co.uk/scripts/gis-faq-5.1.html

会变得更好:请注意余弦定律中使用的纬度以及Haversine是地心纬度,这与大地纬度不同。对于一个球体,这两个是相同的。

哪一个计算最快?

从最快到最慢的顺序为:余弦定律(5次三角函数调用)-> hasrsine(涉及sqrt)-> Vicenty(必须在for循环中迭代解决)

哪一个最准确?

维森蒂。

同时考虑速度和准确性时,哪一个最好?

如果您的问题范围使得您要计算的距离可以认为地球是平坦的,那么您可以计算出一个公式,该公式为x = kx *经度差,y = ky *纬度差。然后距离= sqrt(dx dx + dy dy)。如果您的问题域可以用距离平方解决,那么您将不必使用sqrt,并且此公式将尽可能快地获得。它具有额外的优势,您可以计算矢量距离-x是向东的距离,y是向北的距离。否则,尝试使用3,然后选择最适合您的情况。


3
+1,很好的回答,谢谢。我仍然有一些疑问。我以为只有一种纬度,是什么将地心纬度和大地纬度区分开?Google在Google Maps API中提供什么样的自由度?关于您和DaNieL提供的公式,将地球视为平坦是什么意思?例如,如果我想知道纽约和悉尼之间的距离,该公式会返回准确的结果吗?
Alix Axel 2010年

1
我不知道Google在Google Maps API中提供哪种纬度,但我猜这将是大地纬度。如果距离在几千米的数量级,那么地球在这个比例下看起来很平坦-是吗?对于纽约->悉尼,您应该使用余弦法则。
morpheus 2010年

@theonlytheory:再次感谢,我还有最后一个问题:关于大圆距离公式,您什么也没说……您能否详细说明一下该公式与其他公式的区别?
Alix Axel 2010年

4
没有独特的大圈子公式。上面讨论的公式是用于计算大圆距的公式。您可以说它们都是大圈子公式。
morpheus 2010年

1
是的,WGS84纬度=大地纬度
地貌

12

因此,您要:

  • 按距p0的距离对记录进行排序
  • 仅选择距p0的距离小于r的记录

诀窍是您不需要为此计算大圆距离!您可以使用任何功能,从一对点到一个实际值,该严格随着点之间的大圆距离而增长。这样的函数有很多,对于精确的大圆距离,它们的计算比各种公式要快得多。这样的功能之一就是3D中的欧几里得距离。将经纬度转换为球面上的3D点不涉及反三角函数。

一旦有了x,Y,Z,您就可以意识到实际上并不需要从p0到您的点的距离,因为您也可以使用在p0处的切线平面的距离。该距离也严格地随较大的圆距而增长,并且是根据X,Y,Z作为线性组合计算得出的,甚至不需要平方根。您只需要预先计算与所需的大圆弧距离相对应的系数和截止距离即可。


1
这是一个非常好的主意。我通常不提交“好主意”帖子,但这太棒了!在查找表中为您的指标预先计算距离,然后您就可以离开!确实是非常好的建议。
埃里克·科普
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.