Я пытаюсь вычислить расстояние между двумя координатами широты / долготы, используя формулу равностороннего приближения в PHP, но я получаю результаты, отличные от формулы haversine (которую, я знаю, правильно) для определенных координат долготы.
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;
}
Я не знаю, где вы получили свои формулы. Все три формулы ниже рассчитывают расстояние между двумя координатами.
равные прямоугольники
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 () для учета комментариев. Сделали значения lng абсолютными, используя функцию php abs (). Он начинает дрейфовать от Haversine, когда lng2 переходит от отрицательного к положительному.
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 То, что использовать, зависит от используемых расстояний. Ответ.
Для небольших расстояний (порядка 1 метра или менее) используйте Haversine. Для больших расстояний используйте сферический закон косинусов.
Результаты из формул
0, от -179 до 0, -179 равноугольные 0 км Haversine 0 км
0, от -179 до 0, -159 равносторонних 2224,526851 км Haversine 2224,526851 км
0, от -179 до 0, -139 равносторонних 4449,053703 км Haversine 4449,053703 км
0, от -179 до 0, -119 равносторонних 6673,580554 км Haversine 6673,580554 км
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,21111 км Haversine 17796,21111 км
0, от -179 до 0,1, равноугольные 19798.288978 км Haversine 20020.741663 км
0, от -179 до 0,21, равносторонний 17573,762126 км Haversine 17796,21111 км
0, от -179 до 0,41 равноугольная 15349,235275 км Haversine 15571,68796 км
0, от -179 до 0,61, равносторонние 13124,702323 км, Хаверсине 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 км Haversine 6673.580554 км
0, от -179 до 0,141, равноугольные 4226,601018 км Haversine 4449,053703 км
0, от -179 до 0,161, равноугольная 2002.074166 км Haversine 2224.526851 км
Вы повторно используете 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;