【问题标题】:Calculating short distances between lat/long points计算纬度/经度点之间的短距离
【发布时间】:2012-01-26 04:45:06
【问题描述】:

我有一个带有空间点的 MySQL 表,需要计算距离。我发现了很多关于使用 Haversine 公式执行此操作的材料,但是所有这些都假设点之间的距离很大。就我而言,我只关心短距离(

【问题讨论】:

  • 您可以将条目视为一个扁平三角形并简单地使用正弦定律。然而,Haversine 对于小距离或大距离都不会不准确......它比假设地球是平的更准确。 Haversine 是正弦定律的球面模拟的一个特例。

标签: mysql google-maps-api-3 trigonometry sqlgeography


【解决方案1】:

你的直觉是错误的。根据*(φ 是纬度,ψ 是经度),考虑半正弦公式和半正弦的定义:

还有一个相关的事实:对于较小的 θ 值,sin θ 大约等于 θ;更相关的是,它在 θ 中近似线性。因此,haversin θ 将近似为 (θ/2)²。当 θ 接近零时,这种近似变得更好

如果经纬度相近,则φ₂ - φ₁和ψ₂ - ψ₁,这里应用了半正弦函数,将接近于零,这意味着公式是近似的

(d/2r)² = ((φ₂ - φ₁) / 2)² + cos(φ₁) cos (φ₂) ((ψ₂ - ψ₁) / 2)²

现在请注意,这个公式在具有一些任意比例因子的二维中具有与欧几里得距离相同的形式(记住 (kx)² = k² x² 所以我们可以将常量移入和移出正方形):

kd² = k₂ ∆φ² + k ₃ Δψ²

最后,我断言这些任意比例因子与将纬度/经度变化转换为线性距离的比例因子相同。

因此,haversine 公式不会对于小距离变得不准确;在小距离的限制下,它与普通的欧几里得距离计算完全相同。

【讨论】:

    【解决方案2】:
    1. 使用几何数据类型的点值创建点 MyISAM 表

    2. 在这些点上创建一个空间索引

    使用 MBRContains() 查找值:

    SELECT  *
    FROM    table
    WHERE   MBRContains(LineFromText(CONCAT(
            '('
            , @lon + 10 / ( 111.1 / cos(RADIANS(@lon)))
            , ' '
            , @lat + 10 / 111.1
            , ','
            , @lon - 10 / ( 111.1 / cos(RADIANS(@lat)))
            , ' '
            , @lat - 10 / 111.1 
            , ')' )
            ,mypoint)
    

    ,或者,在 MySQL 5.1 及更高版本中:

    SELECT  *
    FROM    table
    WHERE   MBRContains
                    (
                    LineString
                            (
                            Point
                                    (
                                    @lon + 10 / ( 111.1 / COS(RADIANS(@lat))),
                                    @lat + 10 / 111.1
                                    ) 
                            Point
                                    (
                                    @lon - 10 / ( 111.1 / COS(RADIANS(@lat))),
                                    @lat - 10 / 111.1
                                    ) 
                            ),
                    mypoint
                    )
    

    这将选择大约在框内的所有点(@lat +/- 10 公里,@lon +/- 10 公里)。

    这实际上不是一个盒子,而是一个球面矩形:球体的经纬线段。这可能与弗朗茨约瑟夫地的普通矩形不同,但在大多数有人居住的地方都非常接近。

    应用额外的过滤来选择圆圈内的所有内容(不是正方形)

    可能应用额外的精细过滤来解决大圆距离(对于大距离)

    here following solution to click

    【讨论】: