Клуб API Карт

Определение расстояние между двумя точками ТОЛЬКО по координатам longlat.

Пост в архиве.
mrdds
23 декабря 2010, 19:51

Здравствуйте,

Уже достаточное время мучаюсь с проблемой: пытаюсь рассчитать расстояние между двумя произвольными точками, которые находятся на удалении от 30 до 1500 метров друг от друга.

Используется PHP:

$cx=31.319738; //координата x первой точки
$cy=60.901638; //координата y первой точки

$x=31.333312; //координата x второй точки
$y=60.933981; //координата y второй точки

$mx=abs($cx-$x); //высчитываем разницу иксов (первый катет прямоугольного треугольника), функция abs(x) - возвращает модуль числаx x
$my=abs($cy-$y); //высчитываем разницу игреков (второй катет прямоугольного треугольника)

$dist=sqrt(pow($mx,2)+pow($my,2)); //Получаем расстояние до метро (длину гипотенузы по правилу гипотенуза равна корню из суммы квадратов катетов)

Если непонятно, поясняю: я представляю, что расстояние между двумя точками - это гипотенуза прямоугольного треугольника. Тогда разница между иксами каждой из двух точек будет одним из катетов, а другим катетом будет разница игреков этих же двух точек. Тогда, посчитав разницы иксов и игреков, можно по формуле вычислить длину гипотенузы (т.е. расстояние между двумя точками).

Я знаю, что это правило хорошо работает для декартовой системы координат, однако, оно должно более-менее работать и через координаты longlat, т.к. измеряемое расстояние между двумя точками пренебрежимо мало (от 30 до 1500 метров).

Однако, расстояние по данному алгоритму вычисляется неверно (например, расстояние1, расчитанное по этому алгоритму, превышает расстояние2 всего на 13%, тогда как в реальности расстояние1 равно 1450 метров, я расстояние2 равно 970 метров, то есть на самом делие разница достигает почти 50%).

Если кто-то сможет помочь, буду очень признателен.

С уважением, Александр.

14 комментариев
Может даже несмотря на маленькие растояния, нужно использовать формулы для сферической системы координат?
Вы не учитываете, что длина одного градуса параллели не равна длине одного градуса меридиана и, вообще говоря, меняется с широтой.

Расстояние между точками на сфере считается так.
Благодарю за ответы.
Дело в том, что расстояния очень небольшие (подправил код), и разница в координатах не больше 0.04 градуса (широты/долготы), а отклонение в расчетах (между высчитываемой и настоящей длиной) иногда в два раза.
Использую формулу из википедии


$distance=40000*acos(sin($cy)*sin($y)+cos($cy)*cos($y)*cos($cx-$x));
//$cy и $y - "широты" точек, $cx и $x - "долготы"


и все равно получаю неверный результат (который, кстати, близок к тому, что был получен по катетам).
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D1%80%D0%B0%D0%B4%D0%B8%D1%83%D1%81+%D0%B7%D0%B5%D0%BC%D0%BB%D0%B8
калькулятор жжот.
Это один.
Пунктом 2 можно вспомнить что косинусы вообще в радианах работают( sic! )

 в общем

 

    lat1=deg2rad(lat1);
    lng1=deg2rad(lng1);
    lat2=deg2rad(lat2);
    lng2=deg2rad(lng2);

    return Math.round( 6378137 * Math.acos( Math.cos( lat1 ) * Math.cos( lat2 ) * Math.cos( lng1 - lng2 ) + Math.sin( lat1 ) * Math.sin( lat2 ) ) );



thekashey, большое спасибо, теперь все заработало и расстояние определяется с минимальной погрешностью (3-5%)!
Если кому-нибудь понадобится, могу поделиться кодом на php.
Было бы здорово, если бы поделились ;)
Создайте дополнительный топик, в котором и раскажите о своей наработке. Разработчики, которые столкнутся с похожей проблемой, скажут вам спасибо :)
 
     function distance($lat1,$lng1,$lat2,$lng2)
     {
         // Convert degrees to radians.
        $lat1=deg2rad($lat1);
        $lng1=deg2rad($lng1);
        $lat2=deg2rad($lat2);
        $lng2=deg2rad($lng2);
     
        // Calculate delta longitude and latitude.
        $delta_lat=($lat2 - $lat1);
        $delta_lng=($lng2 - $lng1);
     
        return round( 6378137 * acos( cos( $lat1 ) * cos( $lat2 ) * cos( $lng1 - $lng2 ) + sin( $lat1 ) * sin( $lat2 ) ) );
     }

Саш - с тебя спасибо :)
Да, это, вообщем-то, оно и есть, вы меня опередили)

Что касается кода всей наработки, то она пока далека до завершения, так что наверное не имеет смысла выкладывать ее сейчас. Могу только сказать, что определяю координаты через http запрос к геокодеру с использованием curl, т.е. дистанция считается между стринговыми адресами, а-я "ул. красного курсанта, 17", "красносельская ул. 12" - 456 метров.
 
// Calculate delta longitude and latitude.
        $delta_lat=($lat2 - $lat1);
        $delta_lng=($lng2 - $lng1);
а зачем эти переменные? они же нигде не используются.

В вашей формуле ошибка!

Должно быть: 6378137 * acos( cos( $lat1 ) * cos( $lat2 ) * cos( $lng2 - $lng1) + sin( $lat1 ) * sin( $lat2 ) )

Или можно туда подставить $delta_lng

glebovglebovglebov
2 ноября 2012, 15:09

Или можно вспомнить что косинус четная функция

Да, с радостью посмотрел бы на код