计算点之间的距离时不一致

Posted

技术标签:

【中文标题】计算点之间的距离时不一致【英文标题】:Incosistency when Calculating Distance Between Points 【发布时间】:2015-07-28 15:53:14 【问题描述】:

我在 SQL Server 中有一个函数可以计算两个指定点之间的距离。

该函数使用在 T-SQL 中编写为函数的 Haversine 公式的实现:

CREATE FUNCTION dbo.mpl_geo_distance
(
    @LAT1   FLOAT   ,
    @LON1   FLOAT   ,
    @LAT2   FLOAT   ,
    @LON2   FLOAT
)
  RETURNS FLOAT
  WITH ENCRYPTION
AS
BEGIN
    DECLARE @A AS FLOAT
    DECLARE @C AS FLOAT
    DECLARE @L1 AS FLOAT
    DECLARE @L2 AS FLOAT
    DECLARE @R1 AS FLOAT
    DECLARE @R2 AS FLOAT

    SET @R1 = RADIANS(@LAT1)
    SET @R2 = RADIANS(@LAT2)
    SET @L1 = RADIANS(@LAT2 - @LAT1)
    SET @L2 = RADIANS(@LON2 - @LON1)

    SET @A = SIN(@L1 / 2) * SIN(@L1 / 2) + COS(@R1) * COS(@R2) * SIN(@L2 / 2) * SIN(@L2 / 2)
    SET @C = 2 * ATN2(SQRT(@A), SQRT(1 - @A))
    RETURN 6371000 * @C
END

根据我在 SO 上阅读的一些答案,我决定尝试使用 GEOGRAPHY 类型和 STDistance。然而,这两种方法的结果是不同的(虽然差别不大):

-- Distance between London and Eiffel Tower
DECLARE @X GEOGRAPHY = 'POINT(51.5000 -0.1300)'
DECLARE @Y GEOGRAPHY = 'POINT(48.858093 2.294694)'
PRINT @X.STDistance(@Y)

PRINT dbo.mpl_geo_distance (51.5000, -0.1300, 48.858093, 2.294694)

产量:

397909

340704

哪个值更准确,我应该使用哪个?

【问题讨论】:

我认为你的纬度和经度倒数了。打印 dbo.mpl_geo_distance(-0.1300, 51.5000, 2.294694, 48.858093) 【参考方案1】:

Haversine 公式是一个估计值。如果您查看this site,它会显示各种计算,但请注意:

所有这些公式都是基于球形地球的计算(忽略椭球体效应)——对于大多数用途来说,这已经足够准确*了……[事实上,地球是非常轻微的椭球体;使用球形模型通常会产生高达 0.3% 的误差 - 请参阅注释了解更多详细信息]。

Wikipedia 声称错误可能更高:

当应用于地球时,这两个公式都只是一个近似值,它不是一个完美的球体:“地球半径”R 从两极的 6356.752 公里到赤道的 6378.137 公里不等。更重要的是,地球表面南北线的曲率半径在两极(≈6399.594 公里)比在赤道(≈6335.439 公里)大 1%——所以半正弦公式和余弦定律不能保证正确率优于0.5%

经过一番挖掘,我不完全确定 STDistance 是如何计算的,但 Microsoft say 这个:

STDistance() 返回两种地理类型之间最短的 LineString。这是测地线距离的近似值。普通地球模型上的 STDistance() 与精确测地线距离的偏差不超过 0.25%。这样可以避免混淆测地线类型中长度和距离之间的细微差别。

如果要相信各种来源,那么似乎 STDistance 可能比 Haversine 公式更准确。

【讨论】:

以上是关于计算点之间的距离时不一致的主要内容,如果未能解决你的问题,请参考以下文章

在开发与实时服务器之间切换时不一致?

在开发与实时服务器之间切换时不一致?

如何自动设置约束以使 UIView 之间的距离一致?

232和485接收数据不一致

使用SysV信号量时不一致

SwiftUI 填充距离不一致