Расчет расстояний между городами по их координатам
Расчет расстояний между точками по их координатам на плоскости элементарен, на поверхности Земли — немного посложнее: мы рассмотрим измерение расстояния и начального азимута между точками без проекционных преобразований.
Для начала разберемся в терминологии.
Введение
Длина дуги большого круга – кратчайшее расстояние между любыми двумя точками находящимися на поверхности сферы, измеренное вдоль линии соединяющей эти две точки (такая линия носит название ортодромии) и проходящей по поверхности сферы или другой поверхности вращения.
Сферическая геометрия отличается от обычной Эвклидовой и уравнения расстояния также принимают другую форму. В Эвклидовой геометрии, кратчайшее расстояние между двумя точками – прямая линия. На сфере, прямых линий не бывает. Эти линии на сфере являются частью больших кругов – окружностей, центры которых совпадают с центром сферы.
Начальный азимут — азимут, взяв который при начале движения из точки А, следуя по большому кругу на кратчайшее расстояние до точки B, конечной точкой будет точка B. При движении из точки A в точку B по линии большого круга азимут из текущего положения на конечную точку B постоянно меняется. Начальный азимут отличен от постоянного, следуя которому, азимут из текущей точки на конечную не меняется, но маршрут следования не является кратчайшим расстоянием между двумя точками.
Через любые две точки на поверхности сферы, если они не прямо противоположны друг другу (то есть не являются антиподами), можно провести уникальный большой круг. Две точки, разделяют большой круг на две дуги. Длина короткой дуги – кратчайшее расстояние между двумя точками. Между двумя точками-антиподами можно провести бесконечное количество больших кругов, но расстояние между ними будет одинаково на любом круге и равно половине окружности круга, или π*R, где R – радиус сферы.
На плоскости (в прямоугольной системе координат), большие круги и их фрагменты, как было упомянуто выше, представляют собой дуги во всех проекциях, кроме гномонической, где большие круги — прямые линии. На практике это означает, что самолеты и другой авиатранспорт всегда использует маршрут минимального расстояния между точками для экономии топлива, то есть полет осуществляется по расстоянию большого круга, на плоскости это выглядит как дуга.
Форма Земли может быть описана как сфера, поэтому уравнения для вычисления расстояний на большом круге важны для вычисления кратчайшего расстояния между точками на поверхности Земли и часто используются в навигации.
Вычисление расстояния этим методом более эффективно и во многих случаях более точно, чем вычисление его для спроектированных координат (в прямоугольных системах координат), поскольку, во-первых, для этого не надо переводить географические координаты в прямоугольную систему координат (осуществлять проекционные преобразования) и, во-вторых, многие проекции, если неправильно выбраны, могу привести к значительным искажениям длин в силу особенностей проекционных искажений.
Известно, что более точно описывает форму Земли не сфера, а эллипсоид, однако в данной статье рассматривается вычисление расстояний именно на сфере, для вычислений используется сфера радиусом 6372795 метров, что может привести к ошибке вычисления расстояний порядка 0.5%.
Формулы
Существует три способа расчета сферического расстояния большого круга.
1. Сферическая теорема косинусов
В случае маленьких расстояний и небольшой разрядности вычисления (количество знаков после запятой), использование формулы может приводить к значительным ошибкам связанным с округлением.
φ1, λ1; φ2, λ2 — широта и долгота двух точек в радианах
Δλ — разница координат по долготе
Δδ — угловая разница
Δδ = arccos {sin φ1 sin φ2 + cos φ1 cos φ2 cos Δλ}
Для перевода углового расстояния в метрическое, нужно угловую разницу умножить на радиус Земли (6372795 метров), единицы конечного расстояния будут равны единицам, в которых выражен радиус (в данном случае — метры).
2. Формула гаверсинусов
Используется, чтобы избежать проблем с небольшими расстояниями.
3. Модификация для антиподов
Предыдущая формула также подвержена проблеме точек-антиподов, чтобы ее решить используется следующая ее модификация.
Моя реализация на РНР
// Радиус земли
define('EARTH_RADIUS', 6372795);
/*
* Расстояние между двумя точками
* $φA, $λA - широта, долгота 1-й точки,
* $φB, $λB - широта, долгота 2-й точки
* Написано по мотивам http://gis-lab.info/qa/great-circles.html
* Михаил Кобзарев <mikhail@kobzarev.com>
*
*/
function calculateTheDistance ($φA, $λA, $φB, $λB) {
// перевести координаты в радианы
$lat1 = $φA * M_PI / 180;
$lat2 = $φB * M_PI / 180;
$long1 = $λA * M_PI / 180;
$long2 = $λB * M_PI / 180;
// косинусы и синусы широт и разницы долгот
$cl1 = cos($lat1);
$cl2 = cos($lat2);
$sl1 = sin($lat1);
$sl2 = sin($lat2);
$delta = $long2 - $long1;
$cdelta = cos($delta);
$sdelta = sin($delta);
// вычисления длины большого круга
$y = sqrt(pow($cl2 * $sdelta, 2) + pow($cl1 * $sl2 - $sl1 * $cl2 * $cdelta, 2));
$x = $sl1 * $sl2 + $cl1 * $cl2 * $cdelta;
//
$ad = atan2($y, $x);
$dist = $ad * EARTH_RADIUS;
return $dist;
}
Пример вызова функции:
$lat1 = 77.1539;
$long1 = -139.398;
$lat2 = -77.1804;
$long2 = -139.55;
echo calculateTheDistance($lat1, $long1, $lat2, $long2) . " метров";
// Вернет "17166029 метров"
Статья взята с сайта gis-lab.info Автор: Максим Дубинин
Ссылки
- Вычисление расстояния и начального азимута между двумя точками на сфере(официальный источник)
- Haversine formula
- Способы расчета сферического расстояния большого круга
- Сферическая система координат
- Сферические координаты
- Calculate distance, bearing and more between Latitude/Longitude points
Мы не против когда используют материалы нашего сайта, но их использование должно сопровождаться _четким_ указанием источника.
Согласитесь, взять 1 в 1 авторский текст и иллюстрации и дать источник в разделе ссылки среди других никак не определяет кто же написал этот текст и создал эти иллюстрации.
Надеюсь на понимание и исправление этого мелкого недоразумения. Автор статьи.
Максим, приношу извинения. Пометил ваше авторство более заметным способом. Спасибо за понимание.
суперский
Легко разобраться в большом разнообразии гис, если знать цели применения
А дистанция в каких единицах выражается???
> единицы конечного расстояния будут равны единицам,
> в которых выражен радиус
> (в данном случае – метры).
Да нет, в метрах
Спасибо, уже исправил. (Сам провожу вычисления в километрах)
У меня проблема. Я считал аналогичным способом опираясь на координаты с карт гугл. Потом пересчитал по Вашим формулам. Результат один и тот же. Но он не совпадает в полтора раза с данными померяными линейкой в том же гугл earth.
как получить результат приближенный к картам?
Кривизну учитывали?
А как её нужно учесть?
Просьба привести примеры методов дающих хорошую точность вычислений.
Добрый день! Дополните статью примером вызова Вашей функции. Как правильно передать в функцию координаты точек? Спасибо!
Дополнил статью примером вызова функции расчета расстояния.
спасибо, кому надо адаптировал для javascript
много лишнего, вот переписал в соответствии с более правильным алгоритмом построенным на основе Ортодомии:
Интересный алгоритм, спасибо, постараюсь добавить в статью!
Существует Vincenty формула, которая позволяет со значительной точностью рассчитываеть расстояние между пунками на Земле. Формула базируется на представлении Земли в виде эллипсоида. Причем можно использовать варианты WGS-84, на котором базируется современная геодезия, либо альтернативы. Для WGS-84 a=6378137m, b=6356752.314245m. Саму формулу легко найти на страницах. Точность около 0.115 mm
помогите как можно расчитать расстояние между несколькими точками есть масив данных выводится через WHILE в PHP, грубо говоря есть х точек (трек) нужно расчитать его длину.
Так в чем проблема? Примените функцию
calculateTheDistance
в цикле.А тут долгота с широтой не перепутаны случайно? А то у меня с гуглом совпало, только после того, как поменял их местами.
Чувак! ТЫ реально прав! ЛЮДИ МЕНЯЙТЕ ИХ МЕСТАМИ тут есть ОШИБКА. Над Поменять координаты местами
Ошибка в моей реализации на РНР?
syntax error, unexpected ‘$’, expecting ‘&’ or variable
Вы о чем?
Большое спасибо, за подбор формул, очень помогли!
Не за что 🙂
Добрый день!
Спасибо — очень пригодилось!
Может вы сможете помочь мне с еще одной проблемой (которую я давно не могу решить, обгуглил уже все вдоль и поперек)
Задача следующая: необходимо получить координаты вершин многоугольника имя координаты (lat,lng) центра и радиус (в км или м — не важно)
Натолкните на мысль….
Может квадрата, раз радиус есть? Получается надо найти вершины квадрата, в который вписана окружность с известным радиусом и центром?
Спасибо за метод
Всегда пожалуйста!
Всем, привет. Переписал на Java. Странно но у меня не получается.
77.1539/-139.398 -77.1804/-139.55
Ответ 1.7296047E7
по другим координатам, близко но не точно
77.1539/120.398 77.1804/129.55
Ответ 239902.0
Подскажите, пожалуйста где напортачил?
[code lang=»php»]
double _latA = 77.1539;
double _longA = -139.398;
double _latB = -77.1804;
double _longB = -139.55;
// перевести координаты в радианты
double lat1 =(_latA * Math.PI) / 180.; //φA
double lat2 = (_latB * Math.PI )/ 180.; //φB
double long1 = (_longA * Math.PI) / 180.; //λA
double long2 = (_longB * Math.PI) / 180.; //λB
// косинусы и синусы широт и разницы долгот
double cosLat1 = Math.cos(lat1);
double cosLat2 = Math.cos(lat2);
double sinLat1 = Math.sin(lat1);
double sinLat2 = Math.sin(lat2);
double delta = long1 — long2;
double cosDelta = Math.cos(delta);
double sinDelta = Math.sin(delta);
//вычисления длины большого круга
double y = Math.sqrt(Math.pow(cosLat1 * sinDelta, 2) Math.pow(cosLat1 * sinLat2 — sinLat1 * cosLat2 * cosDelta, 2));
double x = sinLat1 * sinLat2 cosLat1 * cosLat2 * sinDelta;
double ad = Math.atan2(y,x);
double dist = Math.ceil(ad * EARTH_RADIUS);
System.out.println(«The distance between this places is: » dist » meters»);
[code]
На первый взгляд, все нормально, я в java не силен, вы по строкам отладку сделайте, мне даже проверить ваш код негде
Добрый день!
А есть пример для расчета координат на сфере по азимуту и расстоянию от реперной точки?
На плоскости очень уж неточно..
Добрый, к сожалению, нет. Попробуйте задать вопрос автору статьи!