PHP中的等距柱状近似

Mar*_*ijn 5 php distance geo haversine

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

以供参考; 这是我使用的半正弦实现:

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;
}   
Run Code Online (Sandbox Code Playgroud)

dav*_*han 5

我不知道你从哪里得到你的公式。下面的 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑 修改 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;
}
Run Code Online (Sandbox Code Playgroud)

半正弦

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;
} 
Run Code Online (Sandbox Code Playgroud)

球余弦定律

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;
}
Run Code Online (Sandbox Code Playgroud)

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

公式结果

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

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

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

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

0,-179 到 0,-99 等距矩形 8898.107406 km 半正弦 8898.107406 km

0,-179 到 0,-79 等距矩形 11122.634257 km 半正弦 11122.634257 km

0,-179 到 0,-59 等距矩形 13347.161109 km 半正弦 13347.161109 km

0,-179 到 0,-39 等距矩形 15571.68796 km 半正弦 15571.68796 km

0,-179 到 0,-19 等距矩形 17796.214811 km 半正弦 17796.214811 km

0,-179 to 0,1 Equirectangular 19798.288978 km 半正弦 20020.741663 km

0,-179 到 0,21 等距柱状 17573.762126 km 半正弦 17796.214811 km

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

0,-179 到 0,61 等距柱状 13124.708423 km 半正弦 13347.161109 km

0,-179 到 0,81 等距柱状 10900.181572 km 半正弦 11122.634257 km

0,-179 到 0,101 等距矩形 8675.654721 km 半正弦 8898.107406 km

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

0,-179 到 0,141 等距矩形 4226.601018 km 半正弦 4449.053703 km

0,-179 to 0,161 Equirectangular 2002.074166 km 半正弦 2224.526851 km


exu*_*sum 0

您可以重复使用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;
Run Code Online (Sandbox Code Playgroud)