用于计算地理邻近度的公式

时间:2010-01-19 19:25:08

标签: php mysql math geospatial geo

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

  1. 使用 Haversine公式
  2. 使用大圆距离公式
  3. 在数据库中使用空间搜索引擎
  4. 选项#3真的不适合我ATM。现在我有点困惑,因为我始终认为Great-Circle Distance FormulaHaversine Formula同义,但显然我错了?

    Haversine Formula http://i46.tinypic.com/30shbn6.png

    以上屏幕截图取自了很棒的 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's formulae < / strong> - 这似乎是最准确的),这让我更加困惑......

    我需要选择一个好的通用公式来实现PHP / MySQL。谁能解释一下我上面提到的公式之间的差异?

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

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


    基于theonlytheory回答,我测试了以下大圆距离公式:

    • Vincenty Formula
    • Haversine Formula
    • 余弦球面定律

    Vincenty Formula 死得很慢,但非常准确(低至0.5 mm)

    Haversine Formula 比Vincenty Formula更快,我能在大约6秒钟内完成100万次计算,这对我的需求几乎可以接受。

    余弦公式的球面定律显示几乎是Haversine公式的两倍,而精确度差异是疏忽对于大多数人来说用例。


    以下是一些测试地点:

    • Google总部37.422045-122.084347
    • 旧金山,加利福尼亚州37.77493-122.419416
    • 法国艾菲尔铁塔48.85822.294407
    • 悉尼歌剧院-33.856553151.214696

    Google总部 - 旧金山,加利福尼亚州:

    • Vincenty Formula:49 087.066 meters
    • Haversine公式:49 103.006 meters
    • 余弦球面定律:49 103.006 meters

    谷歌总部 - 法国艾菲尔铁塔:

    • Vincenty Formula:8 989 724.399 meters
    • Haversine公式:8 967 042.917 meters
    • 余弦球面定律:8 967 042.917 meters

    谷歌总部 - 悉尼歌剧院:

    • Vincenty Formula:11 939 773.640 meters
    • Haversine公式:11 952 717.240 meters
    • 余弦球面定律:11 952 717.240 meters

    正如你所看到的,在Haversine公式和余弦球面定律之间存在没有明显的差异,但两者的距离偏差高达22公里 Vincenty Formula因为它使用了地球的椭球近似而不是球形。

2 个答案:

答案 0 :(得分:35)

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

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

哪一个计算速度最快?

从最快到最慢的顺序是:余弦定律(5触发调用) - &gt; hasrsine(涉及sqrt) - &gt; Vicenty(必须在for循环中迭代解决)

哪一个最准确?

Vicenty。

当考虑速度和准确度时哪一个最好?

如果您的问题域是这样的,对于您尝试计算的距离,地球可以被认为是平坦的,那么您可以计算出(我不打算提供细节)x = kx *形式的公式经度差异,y = ky *纬度差异。然后距离= sqrt(dx dx + dy dy)。如果您的问题域可以通过距离平方来解决,那么您将不必采用sqrt,并且此公式将尽可能快地得到。它有一个额外的好处,你可以计算向量距离 - x是东方向的距离,y是北方向的距离。 否则,试验3并选择在您的情况下最有效的方法。

答案 1 :(得分:11)

所以你想:

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

诀窍在于你并不需要为此计算大圆距离!您可以使用任何函数从一对点到实数值,这些值严格地随着点之间的大圆距离而增长。有许多这样的函数,有些比计算精确大圆距离的公式要快得多。一个这样的函数是3D中的欧几里德距离。将纬度和经度转换为球体上的3D点不涉及反三角函数。

一旦你有x,Y,Z,你就会发现你实际上并不需要从p0到你的点的距离,因为你也可以使用p0处切线平面的距离。该距离也严格地随着大圆距离而增长,并且从X,Y,Z计算为线性组合 - 甚至不需要平方根。您只需要预先计算系数和与所需大圆距离相对应的截止距离。