Время для прочтения: 1 мин. 22 сек.

Расчет расстояний между городами по их координатам

Расчет расстояний между точками по их координатам на плоскости элементарен, на поверхности Земли — немного посложнее: мы рассмотрим измерение расстояния и начального азимута между точками без проекционных преобразований. Для начала разберемся в терминологии.

Введение

Длина дуги большого круга – кратчайшее расстояние между любыми двумя точками находящимися на поверхности сферы, измеренное вдоль линии соединяющей эти две точки (такая линия носит название ортодромии) и проходящей по поверхности сферы или другой поверхности вращения. Сферическая геометрия отличается от обычной Эвклидовой и уравнения расстояния также принимают другую форму. В Эвклидовой геометрии, кратчайшее расстояние между двумя точками – прямая линия. На сфере, прямых линий не бывает. Эти линии на сфере являются частью больших кругов – окружностей, центры которых совпадают с центром сферы.

Начальный азимут — азимут, взяв который при начале движения из точки А, следуя по большому кругу на кратчайшее расстояние до точки 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 Автор: Максим Дубинин

Ссылки

Пошерить
Плюсануть
Отправить
Вотсап

WordPress Digest Мой канал в Телеграм, посвящённый WordPress
Александр

Добрый день!
А есть пример для расчета координат на сфере по азимуту и расстоянию от реперной точки?
На плоскости очень уж неточно..

Кобзарёв Михаил

Добрый, к сожалению, нет. Попробуйте задать вопрос автору статьи!

Anton Kondakov

Всем, привет. Переписал на 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 не силен, вы по строкам отладку сделайте, мне даже проверить ваш код негде

Александр Аваков

Спасибо за метод

Всегда пожалуйста!

Добрый день!
Спасибо — очень пригодилось!
Может вы сможете помочь мне с еще одной проблемой (которую я давно не могу решить, обгуглил уже все вдоль и поперек)
Задача следующая: необходимо получить координаты вершин многоугольника имя координаты (lat,lng) центра и радиус (в км или м — не важно)
Натолкните на мысль….

Может квадрата, раз радиус есть? Получается надо найти вершины квадрата, в который вписана окружность с известным радиусом и центром?

Большое спасибо, за подбор формул, очень помогли!

Кобзарёв Михаил

Не за что 🙂

syntax error, unexpected ‘$’, expecting ‘&’ or variable

Кобзарёв Михаил

Вы о чем?

А тут долгота с широтой не перепутаны случайно? А то у меня с гуглом совпало, только после того, как поменял их местами.

Чувак! ТЫ реально прав! ЛЮДИ МЕНЯЙТЕ ИХ МЕСТАМИ тут есть ОШИБКА. Над Поменять координаты местами

Кобзарёв Михаил

Ошибка в моей реализации на РНР?

помогите как можно расчитать расстояние между несколькими точками есть масив данных выводится через WHILE в PHP, грубо говоря есть х точек (трек) нужно расчитать его длину.

Кобзарёв Михаил

Так в чем проблема? Примените функцию calculateTheDistance в цикле.

Существует Vincenty формула, которая позволяет со значительной точностью рассчитываеть расстояние между пунками на Земле. Формула базируется на представлении Земли в виде эллипсоида. Причем можно использовать варианты WGS-84, на котором базируется современная геодезия, либо альтернативы. Для WGS-84 a=6378137m, b=6356752.314245m. Саму формулу легко найти на страницах. Точность около 0.115 mm

спасибо, кому надо адаптировал для javascript

function calculateDistance(latA, longA, latB, longB) {
    var EARTH_RADIUS = 6372795;

    lat1 = latA * Math.PI / 180;
    lat2 = latB * Math.PI / 180;
    long1 = longA * Math.PI / 180;
    long2 = longB * Math.PI / 180;
 
    cl1 = Math.cos(lat1);
    cl2 = Math.cos(lat2);
    sl1 = Math.sin(lat1);
    sl2 = Math.sin(lat2);
    delta = long2 - long1;
    cdelta = Math.cos(delta);
    sdelta = Math.sin(delta);
 
    y = Math.sqrt(Math.pow(cl2 * sdelta, 2) + Math.pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2));
    x = sl1 * sl2 + cl1 * cl2 * cdelta;
 
    ad = Math.atan2(y, x);
    dist = Math.ceil(ad * EARTH_RADIUS);
 
    return dist;
}

Добрый день! Дополните статью примером вызова Вашей функции. Как правильно передать в функцию координаты точек? Спасибо!

Кобзарёв Михаил

Дополнил статью примером вызова функции расчета расстояния.

У меня проблема. Я считал аналогичным способом опираясь на координаты с карт гугл. Потом пересчитал по Вашим формулам. Результат один и тот же. Но он не совпадает в полтора раза с данными померяными линейкой в том же гугл earth.
как получить результат приближенный к картам?

Кобзарёв Михаил

Кривизну учитывали?

А как её нужно учесть?
Просьба привести примеры методов дающих хорошую точность вычислений.

А дистанция в каких единицах выражается???

Кобзарёв Михаил

> единицы конечного расстояния будут равны единицам,
> в которых выражен радиус
> (в данном случае – метры).

Да нет, в метрах

Кобзарёв Михаил

Спасибо, уже исправил. (Сам провожу вычисления в километрах)

Легко разобраться в большом разнообразии гис, если знать цели применения

суперский

Кобзарёв Михаил

Максим, приношу извинения. Пометил ваше авторство более заметным способом. Спасибо за понимание.

Мы не против когда используют материалы нашего сайта, но их использование должно сопровождаться _четким_ указанием источника.

Согласитесь, взять 1 в 1 авторский текст и иллюстрации и дать источник в разделе ссылки среди других никак не определяет кто же написал этот текст и создал эти иллюстрации.

Надеюсь на понимание и исправление этого мелкого недоразумения. Автор статьи.

Добавить комментарий

Такой e-mail уже зарегистрирован. Воспользуйтесь формой входа или введите другой.

Вы ввели некорректные логин или пароль

Извините, для комментирования необходимо войти.

1. Нажимая на кнопку "Отправить", я даю согласие на обработку персональных данных.

2. Для вставки кода используйте специальные теги [code lang="php"]ваш код[/code]