Расстояние между точками

В Leaflet работа с расстояниями основана на географических координатах широты и долготы, представленных в формате WGS84. Любая точка на карте описывается объектом координат, а вычисление расстояния между ними опирается на сферическую модель Земли.

Ключевая особенность заключается в том, что расстояние не вычисляется в пикселях карты или в координатах проекции, а всегда переводится в метры на поверхности Земли.


Объект координат L.LatLng

Базовая сущность для работы с географическими точками — объект координат.

const pointA = L.latLng(55.751244, 37.618423);
const pointB = L.latLng(59.931058, 30.360909);

Каждый объект содержит:

  • широту (lat)
  • долготу (lng)
  • дополнительные методы для преобразований

Leaflet использует эти объекты во всех операциях, связанных с геометрией.


Вычисление расстояния методом map.distance

Основной встроенный инструмент для получения расстояния между двумя точками — метод карты distance.

const map = L.map('map');

const a = L.latLng(55.751244, 37.618423);
const b = L.latLng(59.931058, 30.360909);

const meters = map.distance(a, b);
console.log(meters);

Метод возвращает расстояние в метрах.

Внутренне используется сферическая модель Земли с радиусом, приближённым к 6371 км. Алгоритм основан на вычислении геодезического расстояния, что позволяет учитывать кривизну поверхности планеты.


Геодезическое расстояние и особенности расчёта

Прямое евклидово расстояние в координатах широты/долготы не соответствует реальности. Поэтому используется сферическая геометрия.

Расстояние между двумя точками на сфере вычисляется через угловую дистанцию:

  • координаты переводятся в радианы
  • вычисляется центральный угол между точками
  • результат умножается на радиус Земли

Такой подход обеспечивает корректность при работе на глобальных масштабах.


Альтернативное вычисление через формулу Хаверсина

В Leaflet аналогичная логика может быть реализована вручную:

function haversineDistance(a, b) {
    const R = 6371000; // радиус Земли в метрах

    const toRad = deg => deg * Math.PI / 180;

    const dLat = toRad(b.lat - a.lat);
    const dLng = toRad(b.lng - a.lng);

    const lat1 = toRad(a.lat);
    const lat2 = toRad(b.lat);

    const sinDLat = Math.sin(dLat / 2);
    const sinDLng = Math.sin(dLng / 2);

    const h =
        sinDLat * sinDLat +
        Math.cos(lat1) * Math.cos(lat2) *
        sinDLng * sinDLng;

    const c = 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));

    return R * c;
}

Такой подход эквивалентен встроенному механизму Leaflet при вычислении расстояний.


Расстояние между несколькими точками (ломаная линия)

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

const latlngs = [
    L.latLng(55.751244, 37.618423),
    L.latLng(56.326944, 44.007500),
    L.latLng(59.931058, 30.360909)
];

let total = 0;

for (let i = 0; i < latlngs.length - 1; i++) {
    total += map.distance(latlngs[i], latlngs[i + 1]);
}

console.log(total);

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


Использование полилиний для измерения длины

Leaflet позволяет работать с объектами Polyline, которые хранят набор точек.

const polyline = L.polyline(latlngs).addTo(map);

const points = polyline.getLatLngs();

let length = 0;

for (let i = 0; i < points.length - 1; i++) {
    length += map.distance(points[i], points[i + 1]);
}

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


Работа с геометрией через CRS.Earth

Leaflet использует систему координат EPSG:3857 для отображения карты, однако расчёт расстояний выполняется независимо от пиксельной проекции.

В контексте геометрии используется модель:

map.options.crs = L.CRS.Earth;

Эта система обеспечивает корректную интерпретацию координат как точек на сфере, а не на плоскости.


Точность вычислений и источники погрешностей

Несмотря на использование сферической модели, присутствуют ограничения:

  • Земля не является идеальной сферой (используется приближение)
  • расстояния могут не учитывать эллипсоидальную модель WGS84
  • на больших дистанциях погрешность возрастает
  • локальные измерения (до нескольких километров) обладают высокой точностью

Оптимизация вычислений при большом количестве точек

При работе с массивами координат важна производительность:

  • предварительное кэширование результатов
  • уменьшение числа вычислений через упрощение геометрии
  • использование линейной проходки без вложенных циклов

Пример оптимизированного расчёта:

function calculateLength(map, points) {
    let result = 0;
    const len = points.length;

    for (let i = 1; i < len; i++) {
        result += map.distance(points[i - 1], points[i]);
    }

    return result;
}

Сравнение расстояний и фильтрация точек

Расстояния часто используются для отбора объектов в радиусе:

const center = L.latLng(55.751244, 37.618423);

const filtered = points.filter(p =>
    map.distance(center, p) < 1000
);

Такой подход применяется в задачах поиска объектов поблизости, кластеризации и анализа плотности данных.


Работа с интерактивными измерениями на карте

При обработке пользовательских действий расстояния вычисляются динамически:

let lastPoint = null;

map.on('click', function(e) {
    const current = e.latlng;

    if (lastPoint) {
        const dist = map.distance(lastPoint, current);
        console.log(dist);
    }

    lastPoint = current;
});

Каждое новое нажатие формирует сегмент, длина которого вычисляется в реальном времени.


Использование геометрических утилит

В экосистеме Leaflet существуют дополнительные расширения, такие как leaflet-geometryutil, позволяющие работать с длинами линий, площадями и проекциями.

В базовой версии Leaflet основная логика расстояний ограничивается методом map.distance, тогда как расширения добавляют высокоуровневые операции над геометрией.