【问题标题】:Equirectangular approximation in PHPPHP中的Equirectangular近似
【发布时间】:2015-01-29 14:54:23
【问题描述】:

我正在尝试使用 PHP 中的 equirectangular 近似公式计算两个纬度/经度坐标之间的距离,但对于某些经度坐标,我得到的结果与半正弦公式(我知道这是正确的)不同。

define('EARTH_RADIUS', 6371);

function equirectangularRad($latFrom, $lngFrom, $latTo, $lngTo) {
    $latDelta = $latTo - $latFrom;
    $lngDelta = $lngTo - $lngFrom;

    $x = $lngDelta * cos(($latFrom + $latTo) * .5);
    $radius = sqrt(($x * $x) + ($latDelta * $latDelta));

    return $radius * EARTH_RADIUS;
}

似乎总是计算穿过本初子午线而不是最短距离的距离。即沿赤道从坐标(lat=0,long=-180)到(lat=0,long=180),距离应该为零。相反,该函数返回地球沿赤道的周长;大约40030公里。

问题似乎源于$lngDelta 的计算,但对于任何编程语言,我能找到的所有实现都使用相同的公式。我是否遗漏了一些重要的细节,或者这个公式真的不能替代haversine(忽略明显的准确性差异)?

供参考;这是我使用的haversine实现:

function haversineRad($latFrom, $lngFrom, $latTo, $lngTo) {
    $latDelta = $latTo - $latFrom;
    $lngDelta = $lngTo - $lngFrom;              

    $latSin = sin($latDelta * .5);
    $lngSin = sin($lngDelta * .5);
    $radius = 2. * asin(sqrt(($latSin * $latSin) + cos($latFrom) * cos($latTo) * ($lngSin * $lngSin)));

    return $radius * EARTH_RADIUS;
}   

【问题讨论】:

  • $lngDelta = ($lngTo - $lngFrom) % 360;?
  • @mudasobwa,模 360(或者更确切地说 2 * pi)不起作用。某处需要反转。我使用$lngDelta = abs($lngTo - $lngFrom); $lngDelta = min($lngDelta, (2 * pi()) - $lngDelta); 取得了一些有限的成功,但这仍然会在两极处产生相当大的误差(我可以忍受)并且几乎将其减慢到大致与半正弦的速度(这使得使用等矩形近似毫无意义)。跨度>

标签: php distance geo haversine


【解决方案1】:

我不知道你从哪里得到你的公式。下面的3个公式都是计算2个坐标之间的距离。

等矩形

function Equirectangular($lat1,$lng1,$lat2,$lng2){
$x = deg2rad($lng2-$lng1) * cos(deg2rad($lat1+$lat2)/2);
$y = deg2rad($lat1-$lat2);
$R = 6372.8; // gives d in km
$distance = sqrt($x*$x + $y*$y) * $R;
return $distance;
}

编辑 修改 Equirectangular() 以考虑注释。使用 php abs() 函数将 lng 值设为绝对值。当 lng2 由负转正时,它开始从 Haversine 漂移。

function Equirectangular($lat1,$lng1,$lat2,$lng2){
$lng1 = abs($lng1);
$lng2 = abs($lng2);
$alpha = $lng2-$lng1;
$x = deg2rad($alpha) * cos(deg2rad($lat1+$lat2)/2);
$y = deg2rad($lat1-$lat2);
$R = 6372.8; // gives d in km
$distance = sqrt($x*$x + $y*$y) * $R;
return $distance;
}

Haversine

function Haversine($lat1,$lng1,$lat2,$lng2) {
  $deltaLat = $lat2 - $lat1 ;
  $deltaLng = $lng2 - $lng1 ;
  $earthRadius = 6372.8; // 3959 in miles.
  $alpha = $deltaLat/2;
  $beta = $deltaLng/2;
  $a = sin(deg2rad($alpha)) * sin(deg2rad($alpha)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin(deg2rad($beta)) * sin(deg2rad($beta)) ;
  $c = 2 * atan2(sqrt($a), sqrt(1-$a));
  $distance = $earthRadius * $c;
  return $distance;
} 

SphericalLawOfCosines

function SphericalLawOfCosines($lat1,$lng1,$lat2,$lng2) {
 $lat1 = deg2rad($lat1);
 $lat2 = deg2rad($lat2);
 $deltaLng = deg2rad($lng2-$lng1);
 $R = 6372.8; // gives d in km
$d = acos( sin($lat1)*sin($lat2) + cos($lat1)*cos($lat2) * cos($deltaLng) ) * $R;
return $d;
}

Equirectangular 是最简单但不太准确的方法。对于其他 2 使用的一个取决于所涉及的距离。请参阅此Answer。 对于小距离(大约 1 米或更短),请使用 Haversine。对于更大的距离,请使用余弦球定律。

公式的结果

0,-179 到 0,-179 等距矩形 0 公里半正弦 0 公里

0,-179 到 0,-159 等距矩形 2224.526851 公里半正弦 2224.526851 公里

0,-179 到 0,-139 等距矩形 4449.053703 公里半正弦 4449.053703 公里

0,-179 到 0,-119 等距矩形 6673.580554 km 正弦 6673.580554 km

0,-179 到 0,-99 等距矩形 8898.107406 公里 Haversine 8898.107406 公里

0,-179 到 0,-79 等距矩形 11122.634257 公里 Haversine 11122.634257 公里

0,-179 到 0,-59 等距矩形 13347.161109 公里 Haversine 13347.161109 公里

0,-179 到 0,-39 等距矩形 15571.68796 公里 Haversine 15571.68796 公里

0,-179 到 0,-19 等距矩形 17796.214811 公里 Haversine 17796.214811 公里

0,-179 到 0,1 Equirectangular 19798.288978 km Haversine 20020.741663 km

0,-179 到 0,21 Equirectangular 17573.762126 km Haversine 17796.214811 km

0,-179 到 0,41 等距矩形 15349.235275 公里半正弦 15571.68796 公里

0,-179 到 0,61 等距矩形 13124.708423 公里 Haversine 13347.161109 公里

0,-179 到 0,81 等距矩形 10900.181572 公里 Haversine 11122.634257 公里

0,-179 到 0,101 等距矩形 8675.654721 公里 Haversine 8898.107406 公里

0,-179 到 0,121 等距矩形 6451.127869 公里半正弦 6673.580554 公里

0,-179 到 0,141 等距矩形 4226.601018 公里 Haversine 4449.053703 公里

0,-179 到 0,161 等距矩形 2002.074166 公里 Haversine 2224.526851 公里

【讨论】:

  • 这些问题与我在问题中描述的问题相同:Equirectangular(0,-179,0,179) 返回 39819.030640452,Haversine(0,-179,0,179) 返回 222.45268514219。显然 Equirectangular 没有计算最短距离。 SphericalLawOfCosines 返回 222.45268514218,与 Haversine 几乎相同。 Equirectangular 公式在穿过 -180/180 度经线的距离时存在问题。
  • @Martijn 已修改Equirectangular()以考虑评论。
【解决方案2】:

你重复使用latDelta,其中一个用途是添加的,另一个是减去的。

http://www.movable-type.co.uk/scripts/latlong.html

有工作的javascript。

翻译..

$x = ($lngTo-$lngFrom) * cos(($latTo+$latFrom)/2);
$y = ($latTo-$latFrom)
$d = sqrt($x*$x + $y*$y) * EARTH_RADIUS;

【讨论】:

  • 我没有看到我的函数和该页面上的公式之间的区别。 (事实上​​,该页面被用作参考)。
猜你喜欢
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2016-01-22
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多