Проекции

Проекции в картографических библиотеках определяют способ преобразования географических координат (широта и долгота) в плоские координаты, используемые для отображения карты на экране. В Leaflet вся геометрия карты строится вокруг понятия CRS (Coordinate Reference System) — системы координат, которая объединяет проекцию, единицы измерения и правила преобразования между координатами мира и пикселями.

В основе архитектуры лежит интерфейс L.CRS, через который задаётся поведение карты при масштабировании, панорамировании и наложении слоёв.

Основные CRS в Leaflet

EPSG:3857 (Web Mercator)

Стандартная система координат в Leaflet — Web Mercator.

Leaflet использует её по умолчанию через L.CRS.EPSG3857.

Ключевые особенности:

  • координаты хранятся в метрах (псевдометрах);
  • широты ограничены диапазоном около ±85.0511°;
  • подходит для тайловых карт (OpenStreetMap, Mapbox-подобные системы);
  • обеспечивает удобную квадратную плиточную структуру мира.

Преобразование базируется на меркаторной проекции:

  • долгота → линейная шкала по X;
  • широта → логарифмическое преобразование по Y.

Это позволяет сохранить углы (конформность), но искажает площади ближе к полюсам.

EPSG:4326 (WGS84)

Вторая базовая система — географическая:

  • координаты представлены в градусах;
  • отсутствует проекция в классическом смысле (широта/долгота как есть);
  • используется в GPS и геодезии.

В Leaflet доступна через L.CRS.EPSG4326.

Особенности:

  • ось X — долгота;
  • ось Y — широта;
  • масштабирование линейное;
  • плохо подходит для тайловых карт без дополнительной трансформации.

Simple CRS

L.CRS.Simple — плоская декартова система координат:

  • отсутствует географическая привязка;
  • координаты трактуются как пиксели или произвольные единицы;
  • используется для изображений, схем, игровых карт.

Применение:

  • схемы помещений;
  • карты внутри игр;
  • изображения высокого разрешения.

Архитектура CRS в Leaflet

Каждая CRS в Leaflet определяется набором функций:

  • latLngToPoint(latlng, zoom) — перевод географических координат в пиксели;
  • pointToLatLng(point, zoom) — обратное преобразование;
  • project(latlng) — проекция в плоское пространство;
  • unproject(point) — обратная операция;
  • scale(zoom) — масштабный коэффициент.

Пример структуры:

const CRS = {
  project: function (latlng) {},
  unproject: function (point) {},
  scale: function (zoom) {},
  distance: function (latlng1, latlng2) {}
};

Эта абстракция позволяет подменять систему координат без изменения логики слоёв и тайлов.

Преобразование координат

Проекция широты и долготы

В Web Mercator используется следующая логика:

  • долгота масштабируется линейно;
  • широта преобразуется через логарифмическую функцию.

Внутренне Leaflet использует вспомогательные классы:

  • L.Projection.Mercator
  • L.Projection.SphericalMercator

Принцип:

  1. координаты переводятся в радианы;
  2. применяется масштабирование Земли как сферы;
  3. результат нормализуется в единый мир размером 256 × 256 на нулевом зуме.

Мир в пикселях

При zoom = 0:

  • карта представляет собой один тайл 256×256;
  • вся Земля умещается в один квадрат.

При увеличении зума:

  • каждый уровень удваивает разрешение;
  • формируется сетка тайлов 2ⁿ × 2ⁿ.

Формула масштабирования:

  • scale = 2^zoom

Это значение используется для перевода координат в пиксельное пространство.

Тайлы и связь с проекциями

Tile layer в Leaflet полностью зависит от CRS. Каждый тайл имеет координаты:

  • x — колонка;
  • y — строка;
  • z — уровень масштабирования.

Пример URL тайлов:

/{z}/{x}/{y}.png

При использовании EPSG:3857:

  • x/y вычисляются в проецированном пространстве;
  • границы мира фиксированы;
  • тайлы равномерно покрывают поверхность.

Если CRS отличается, система тайлов должна соответствовать новой сетке.

L.CRS.EPSG3857 внутри Leaflet

Внутренняя реализация включает:

  • сферическую модель Земли;
  • радиус R = 6378137 м;
  • преобразование в Web Mercator координаты.

Упрощённо:

x = R * lonRad;
y = R * ln(tan(π/4 + latRad/2));

Эта формула задаёт основу проекции.

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

Масштабирование и уровни зума

Zoom в Leaflet не является простым увеличением изображения. Он связан с CRS через масштабную функцию:

  • каждый zoom увеличивает детализацию в 2 раза;
  • центр карты остаётся фиксированным в координатах CRS;
  • пересчитываются только пиксельные координаты.

Механизм:

scale = 256 * Math.pow(2, zoom);

Это означает, что на каждом уровне зума карта становится плотнее, а не просто «увеличивается».

Custom CRS

Leaflet позволяет задавать собственные системы координат через L.CRS.extend.

Пример структуры:

const customCRS = L.extend({}, L.CRS, {
  projection: L.Projection.LonLat,
  transformation: new L.Transformation(1, 0, -1, 0)
});

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

  • нестандартных карт;
  • CAD-систем;
  • игровых миров;
  • изображений с фиксированной сеткой.

Ключевой элемент — L.Transformation, задающий линейное преобразование:

  • x’ = ax + b
  • y’ = cy + d

Проекция и события карты

Все взаимодействия карты завязаны на CRS:

  • click → экранные координаты → CRS координаты;
  • drag → пересчёт центра карты;
  • zoom → пересчёт масштаба проекции.

Пример:

map.on('click', function (e) {
  console.log(e.latlng);
});

e.latlng формируется через обратное преобразование:

  • пиксель → point → latlng через CRS.

Ограничения Web Mercator

EPSG:3857 имеет ряд математических искажений:

  • полюса не отображаются;
  • площади увеличиваются к северу и югу;
  • Гренландия визуально сопоставима с Африкой.

Leaflet не компенсирует эти искажения, так как цель — совместимость с тайловыми сервисами.

Использование Proj4Leaflet

Для сложных систем координат применяется плагин Proj4Leaflet, интегрирующий библиотеку Proj4.

Он позволяет:

  • использовать EPSG-коды вне стандартных наборов;
  • подключать локальные проекции;
  • работать с геодезическими системами.

Пример:

const crs = new L.Proj.CRS('EPSG:32636',
  '+proj=utm +zone=36 +datum=WGS84 +units=m +no_defs', {
    resolutions: [8192, 4096, 2048]
});

Это расширяет возможности Leaflet за пределы Web Mercator.

Привязка изображений к CRS.Simple

При использовании L.CRS.Simple изображение интерпретируется как плоскость.

Пример:

const map = L.map('map', {
  crs: L.CRS.Simple
});

const bounds = [[0, 0], [1000, 1000]];
L.imageOverlay('image.png', bounds).addTo(map);

В этом случае:

  • координаты = пиксели изображения;
  • нет географической интерпретации;
  • масштаб определяется только визуально.

Влияние CRS на слои

Разные типы слоёв по-разному реагируют на CRS:

  • TileLayer — требует совпадения схемы тайлов;
  • Marker — пересчитывает latlng → point;
  • Vector layers — проецируют геометрию через CRS;
  • ImageOverlay — зависит от bounds и трансформации.

Векторные объекты всегда хранятся в географических координатах и пересчитываются при каждом рендере.

Геометрические операции внутри CRS

Leaflet использует CRS также для:

  • расчёта расстояний;
  • определения границ видимой области;
  • вычисления масштабов объектов.

Например, расстояние:

  • EPSG:3857 — приближённое в метрах;
  • EPSG:4326 — требует сферической модели;
  • Simple — евклидово.

Каждая CRS может переопределять метод distance().

Взаимодействие CRS и Viewport

Viewport (область отображения) всегда вычисляется через CRS:

  1. берётся центр карты в latlng;
  2. преобразуется в пиксели;
  3. вычисляется bounding box;
  4. выбираются тайлы и объекты.

При изменении zoom пересчёт выполняется полностью, но географическая логика остаётся неизменной.

Роль трансформации

L.Transformation является связующим звеном между проекцией и экраном.

Он задаёт:

  • смещение (offset);
  • масштаб;
  • отражение осей при необходимости.

Без трансформации невозможно корректно совместить координатную систему мира и пиксельный canvas браузера.