我试图使用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;
}
答案 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;