PHP中的Equirectangular近似

时间:2014-12-01 14:59:35

标签: php distance geo haversine

我试图使用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的计算,但对于任何编程语言,我能找到的所有实现都使用相同的公式。我是否遗漏了一些重要的细节,或者这个公式真的不是胡子的替代品(忽略明显的准确度差异)?

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

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;
}   

2 个答案:

答案 0 :(得分:3)

我不知道你的配方在哪里。下面的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 Equirectangular 0 km Haversine 0 km

0,-179到0,-159 Equirectangular 2224.526851 km Haversine 2224.526851 km

0,-179到0,-139 Equirectangular 4449.053703 km Haversine 4449.053703 km

0,-179到0,-119 Equirectangular 6673.580554 km Haversine 6673.580554 km

0,-179到0,-99 Equirectangular 8898.107406 km Haversine 8898.107406 km

0,-179到0,-79 Equirectangular 11122.634257 km Haversine 11122.634257 km

0,-179到0,-59 Equirectangular 13347.161109 km Haversine 13347.161109 km

0,-179到0,-39 Equirectangular 15571.68796 km Haversine 15571.68796 km

0,-179到0,-19 Equirectangular 17796.214811 km Haversine 17796.214811 km

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 Equirectangular 15349.235275 km Haversine 15571.68796 km

0,-179到0,61 Equirectangular 13124.708423 km Haversine 13347.161109 km

0,-179到0,81 Equirectangular 10900.181572 km Haversine 11122.634257 km

0,-179到0,101 Equirectangular 8675.654721 km Haversine 8898.107406 km

0,-179到0,121 Equirectangular 6451.127869 km Haversine 6673.580554 km

0,-179到0,141 Equirectangular 4226.601018 km Haversine 4449.053703 km

0,-179到0,161 Equirectangular 2002.074166 km Haversine 2224.526851 km

答案 1 :(得分: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;