计算地理邻近度的公式

我需要在我的应用程序中实现Geo邻近search,但是我对使用正确的公式感到困惑。 在Web和StackOverflow中进行了一些search之后,我发现解决scheme是:

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

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

Haversine公式http://i46.tinypic.com/30shbn6.png

上面的屏幕截图是从真棒地理(邻近)searchMySQL文件,并使用以下function:

ASIN, SQRT, POWER, SIN, PI, COS 

我也看到了同样的公式 ( 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)))) 

这使用以下function:

 ACOS, COS, RADIANS, SIN 

我不是math专家,但这些公式是一样的吗? 我遇到了更多的变化和公式 (比如Cosines球形定律Vincenty的 公式 – 这似乎是最准确的),这让我更加困惑。

我需要select一个好的通用公式来在PHP / MySQL中实现。 任何人都可以解释我上面提到的公式之间的差异吗?

  • 哪一个是最快的计算?
  • 哪一个提供最准确的结果?
  • 在结果的速度/准确性方面哪一个最好?

我感谢您对这些问题的洞察力。


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

  • Vincenty公式
  • Haversine公式
  • Cosines的球形定律

Vincenty公式速度很慢,但是非常准确(低至0.5毫米)

Haversine公式比Vincenty公式要快得多,我能够在大约6秒内运行100万次计算,这是我所需要的。

Cosines公式球形定律显示几乎是Haversine公式的两倍精度差异对于大多数用例来说是疏忽大意的。


以下是一些testing地点:

  • Google总部37.422045-122.084347
  • 旧金山,CA37.77493-122.419416
  • 法国艾菲尔铁塔2.294407
  • 悉尼歌剧院151.214696

Google HQ – 旧金山,CA:

  • 49 087.066 meters公式: 49 087.066 meters
  • Haversine公式: 49 103.006 meters
  • 49 103.006 meters球形法则: 49 103.006 meters

Google总部 – 法国艾菲尔铁塔:

  • 8 989 724.399 meters公式: 8 989 724.399 meters
  • Haversine公式: 8 967 042.917 meters
  • 8 967 042.917 meters球形法则: 8 967 042.917 meters

Google总部 – 悉尼歌剧院:

  • 11 939 773.640 meters公式: 11 939 773.640 meters
  • Haversine公式: 11 952 717.240 meters
  • 余弦球面法则: 11 952 717.240 meters

正如你所看到的,Haversine公式和Cosines的球面定律之间没有明显的差别 ,但是与Vincenty公式相比,它们的距离偏移高达22公里 ,因为它使用椭球近似的地球而不是球面。

假定机器具有无限精度,余弦定律和半正式公式将给出相同的结果。 Haversine公式更适合浮点错误。 然而,今天的机器有15位有效数字的双精度,而余弦定律对你来说可能工作得很好。 这两个公式都假定为球形地球,而维迪斯的迭代解(最准确的)假定为椭球体地球(事实上地球甚至不是椭球体 – 它是大地水准面)。 一些参考文献: http : //www.movable-type.co.uk/scripts/gis-faq-5.1.html

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

哪一个计算速度最快?

从最快到最慢的顺序是:余弦定律(5 trig。calls) – > haversine(涉及sqrt) – > vicenty(必须在for循环中迭代求解)

哪一个最准确?

Vicenty。

哪一个是最好的速度和准确性都考虑?

如果你的问题领域是这样的,你想要计算的距离,地球可以被认为是平坦的,那么你可以工作(我不打算给细节)一个公式formsx = kx *经度差,y = ky *纬度差。 那么distance = sqrt(dx dx + dy dy)。 如果你的问题域是可以用距离平方来解决的话,那么你就不必采取sqrt,这个公式将会尽可能快地得到。 它具有附加的优点,可以计算vector距离 – x是东方向的距离,y是北方向的距离。 否则,尝试3,并select最适合你的情况。

所以你想要:

  • 按距离p0sortinglogging
  • 只select距p0的距离小于r的logging

诀窍是,你并不完全需要为此计算出大圆的距离! 你可以用任何一对点的函数来做一个真正的值,这个是与点之间的大圆距离严格一致的 。 有很多这样的函数,有些是比许多公式精确的大圆距计算快得多。 一个这样的函数是3D中的欧几里德距离。 将纬度和经度转换为球体上的三维点不涉及反三angular函数。

一旦你有了x,Y,Z,你可以意识到你实际上并不需要从p0到你的点的距离,因为你也可以用p0的切平面的距离。 该距离也严格按照大圆距离增长,并且从X,Y,Z作为线性组合来计算 – 甚至不需要平方根。 您只需预先计算与所需的大圆距离相对应的系数和截止距离。