Координаты в GeoJSON

В GeoJSON координаты описываются строго по спецификации RFC 7946 и всегда опираются на систему географических координат WGS84 (EPSG:4326). В отличие от многих библиотек визуализации, где порядок координат может варьироваться, GeoJSON фиксирует единый стандарт: сначала долгота, затем широта.

Ключевой принцип:

[долгота, широта] → [longitude, latitude]

Этот порядок критически важен при интеграции с Leaflet, поскольку библиотека использует обратное представление координат.


Структура координат в GeoJSON

Координаты в GeoJSON всегда представлены массивами чисел с плавающей точкой. Они могут описывать:

  • точку
  • линию
  • многоугольник
  • сложные геометрии (MultiPoint, MultiLineString, MultiPolygon)

Базовый формат:

{
  "type": "Point",
  "coordinates": [30.5, 50.45]
}

Здесь:

  • 30.5 — долгота
  • 50.45 — широта

Точки (Point)

Точка является простейшей геометрией. Она состоит из одного массива координат.

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [37.6173, 55.7558]
  },
  "properties": {
    "name": "Москва"
  }
}

В Leaflet такие данные часто используются через L.geoJSON, где библиотека автоматически преобразует их в LatLng.


Линии (LineString)

Линия представляет собой упорядоченный набор координатных точек.

{
  "type": "LineString",
  "coordinates": [
    [30.31, 59.93],
    [30.33, 59.94],
    [30.35, 59.95]
  ]
}

Каждый элемент массива — отдельная точка маршрута.

В Leaflet линия интерпретируется как полилиния.

L.geoJSON(lineStringData).addTo(map);

Многоугольники (Polygon)

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

{
  "type": "Polygon",
  "coordinates": [
    [
      [30.0, 60.0],
      [31.0, 60.0],
      [31.0, 61.0],
      [30.0, 61.0],
      [30.0, 60.0]
    ]
  ]
}

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

  • первый и последний элемент должны совпадать, образуя замкнутый контур

Многоугольники с отверстиями:

{
  "type": "Polygon",
  "coordinates": [
    [
      [30.0, 60.0],
      [32.0, 60.0],
      [32.0, 62.0],
      [30.0, 62.0],
      [30.0, 60.0]
    ],
    [
      [30.5, 60.5],
      [31.5, 60.5],
      [31.5, 61.5],
      [30.5, 61.5],
      [30.5, 60.5]
    ]
  ]
}

Вложенные структуры координат

GeoJSON поддерживает многокомпонентные геометрии:

  • MultiPoint
  • MultiLineString
  • MultiPolygon

Пример MultiPoint:

{
  "type": "MultiPoint",
  "coordinates": [
    [30.1, 59.9],
    [30.2, 60.0],
    [30.3, 60.1]
  ]
}

Пример MultiPolygon:

{
  "type": "MultiPolygon",
  "coordinates": [
    [
      [
        [30.0, 60.0],
        [31.0, 60.0],
        [31.0, 61.0],
        [30.0, 61.0],
        [30.0, 60.0]
      ]
    ],
    [
      [
        [32.0, 60.0],
        [33.0, 60.0],
        [33.0, 61.0],
        [32.0, 61.0],
        [32.0, 60.0]
      ]
    ]
  ]
}

Различие Leaflet LatLng и GeoJSON координат

Leaflet использует собственный формат координат:

L.latLng(lat, lng)

или массив:

[lat, lng]

GeoJSON использует противоположный порядок:

[longitude, latitude]

Это ключевая точка несоответствия.

Сравнение:

Формат Порядок
Leaflet [lat, lng]
GeoJSON [lng, lat]

При ручной обработке данных это различие становится источником системных ошибок отображения.


Частые ошибки при работе с координатами

Основные проблемы возникают из-за нарушения порядка координат:

  1. Перепутаны широта и долгота → точка отображается в другом регионе мира

  2. Использование Leaflet-формата в GeoJSON → некорректная геометрия

  3. Отсутствие замыкания полигона → визуальные разрывы или некорректная заливка

  4. Неправильная вложенность массивов → MultiPolygon становится невалидным

  5. Использование локальных систем координат вместо WGS84 → смещение на карте


Преобразование координат между Leaflet и GeoJSON

Преобразование из Leaflet в GeoJSON требует перестановки значений:

function latLngToGeoJSON(latlng) {
  return [latlng.lng, latlng.lat];
}

Обратное преобразование:

function geoJSONToLatLng(coords) {
  return L.latLng(coords[1], coords[0]);
}

Для массивов:

function convertArray(arr) {
  return arr.map(([lat, lng]) => [lng, lat]);
}

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

Leaflet предоставляет встроенный механизм работы с GeoJSON через L.geoJSON.

const geojsonData = {
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [37.62, 55.75]
  },
  "properties": {
    "title": "Объект"
  }
};

L.geoJSON(geojsonData, {
  onEachFeature: function (feature, layer) {
    if (feature.properties && feature.properties.title) {
      layer.bindPopup(feature.properties.title);
    }
  }
}).addTo(map);

Внутри Leaflet происходит автоматическое преобразование GeoJSON координат в LatLng.


CRS и система координат

GeoJSON по стандарту использует только WGS84:

  • EPSG:4326
  • географические координаты в градусах

Leaflet по умолчанию также работает в EPSG:3857 (Web Mercator) для отображения тайлов, но входные координаты принимает в географическом формате.

Это означает:

  • вход: GeoJSON (WGS84)
  • отображение: проекция Web Mercator
  • преобразование выполняется автоматически

Особенности вложенности координат в сложных геометриях

Чем сложнее тип геометрии, тем глубже уровень вложенности:

  • Point → [lng, lat]
  • LineString → [[lng, lat], ...]
  • Polygon → [[[lng, lat], ...]]
  • MultiPolygon → [[[[lng, lat], ...]], ...]

Ошибки часто возникают при неправильном увеличении или уменьшении уровня вложенности.


Геометрическая согласованность данных

Корректные координаты должны:

  • быть числовыми значениями

  • соблюдать порядок [lng, lat]

  • соответствовать допустимым диапазонам:

    • долгота: -180 до 180
    • широта: -90 до 90

Нарушение диапазонов приводит к невозможности корректного отображения на карте или к «переносу» объекта в другую область мира.


Работа с FeatureCollection

GeoJSON обычно используется в виде коллекций объектов:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [30.3, 59.9]
      },
      "properties": {}
    }
  ]
}

Leaflet обрабатывает такие структуры напрямую:

L.geoJSON(featureCollection).addTo(map);

Все координаты внутри структуры интерпретируются рекурсивно, независимо от глубины вложенности.


Поведение при рендеринге в Leaflet

При передаче GeoJSON в Leaflet выполняется следующий процесс:

  1. чтение типа геометрии

  2. извлечение массива координат

  3. преобразование [lng, lat] → LatLng

  4. построение соответствующего слоя:

    • Marker для Point
    • Polyline для LineString
    • Polygon для Polygon

Финальный результат всегда зависит от корректности исходной структуры координат, поскольку Leaflet не исправляет ошибки порядка, а лишь интерпретирует входные данные.