Преобразование форматов

GeoJSON как основной формат обмена данными

В экосистеме веб-картографии GeoJSON выступает универсальным форматом описания геометрии и атрибутов объектов. В Leaflet он является базовым стандартом для импорта и экспорта пространственных данных.

Структура GeoJSON опирается на несколько ключевых типов:

  • Feature — объект с геометрией и свойствами
  • FeatureCollection — набор объектов
  • Geometry — геометрические примитивы (Point, LineString, Polygon и др.)

Leaflet интерпретирует GeoJSON напрямую через L.geoJSON, преобразуя данные в соответствующие слои карты.

Особенность взаимодействия заключается в автоматическом маппинге типов:

  • Point → Marker
  • LineString → Polyline
  • Polygon → Polygon
  • Multi* → группы соответствующих слоёв

Дополнительно поддерживаются обработчики onEachFeature, pointToLayer, filter, позволяющие модифицировать процесс конвертации без изменения исходного формата.


Преобразование слоёв Leaflet в GeoJSON

Внутренние объекты Leaflet могут быть сериализованы обратно в GeoJSON. Основной механизм реализован через метод toGeoJSON().

Поддерживаемые сущности:

  • L.Marker
  • L.Polyline
  • L.Polygon
  • L.LayerGroup
  • L.FeatureGroup

Принцип преобразования основан на обходе вложенной структуры слоёв и сборе геометрии в стандартизированное представление.

const geojson = layer.toGeoJSON();

При использовании FeatureGroup происходит рекурсивная агрегация всех дочерних слоёв:

const group = L.featureGroup([marker, polyline, polygon]);
const data = group.toGeoJSON();

В результате формируется единый FeatureCollection.

Дополнительные свойства можно внедрять через опцию properties внутри слоя:

const marker = L.marker([51.5, 0.1], {
  title: 'Object A'
});
marker.feature = {
  type: 'Feature',
  properties: {
    name: 'Object A',
    category: 'point'
  }
};

Загрузка GeoJSON и трансформация данных

Загрузка GeoJSON в Leaflet реализуется через L.geoJSON, который выполняет преобразование геометрии в слои карты.

L.geoJSON(data, {
  style: function (feature) {
    return { color: 'blue' };
  },
  onEachFeature: function (feature, layer) {
    layer.bindPopup(feature.properties.name);
  }
}).addTo(map);

Механизм трансформации включает:

  • интерпретацию координат
  • создание соответствующих объектов Leaflet
  • привязку атрибутов
  • применение стилей

Фильтрация объектов выполняется на этапе загрузки:

filter: function (feature) {
  return feature.properties.visible === true;
}

Координатные системы и порядок координат

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

  • LatLng: [latitude, longitude]

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

  • [longitude, latitude]

Несоответствие компенсируется автоматически при использовании L.geoJSON, однако при ручной обработке требуется строгий контроль порядка координат.

Пример некорректной интерпретации:

// Ошибка: перепутан порядок
L.marker([lng, lat]);

Корректная форма:

L.marker([lat, lng]);

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


CRS и преобразование проекций

Leaflet оперирует системой координат через CRS (Coordinate Reference System). Наиболее распространённые:

  • EPSG:3857 (Web Mercator) — стандарт для тайловых карт
  • EPSG:4326 (WGS84) — географические координаты

При работе с GeoJSON предполагается EPSG:4326, однако отображение на карте почти всегда выполняется в EPSG:3857.

Инициализация карты с альтернативной CRS:

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

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

Leaflet предоставляет методы:

  • project(latlng) — перевод в пиксельные координаты
  • unproject(point) — обратное преобразование

Конвертация KML и GPX

Помимо GeoJSON часто используются форматы KML и GPX. Leaflet не поддерживает их нативно, но применяются специализированные плагины.

Одним из распространённых решений является leaflet-omnivore, обеспечивающий парсинг различных форматов:

omnivore.kml('data.kml').addTo(map);
omnivore.gpx('track.gpx').addTo(map);

Процесс преобразования включает:

  • парсинг XML-структуры
  • извлечение координат
  • конвертацию в GeoJSON-подобные структуры
  • генерацию Leaflet-слоёв

TopoJSON и оптимизация геометрии

TopoJSON представляет собой расширение GeoJSON, в котором геометрия хранится в виде топологических связей. Это уменьшает размер данных за счёт устранения дублирования координат.

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

const geojson = topojson.feature(topology, topology.objects.layer);
L.geoJSON(geojson).addTo(map);

Преобразование выполняется через библиотеку topojson-client.


WKT и альтернативные текстовые форматы

WKT (Well-Known Text) используется в ряде GIS-систем для текстового описания геометрии:

POINT (30 10)
LINESTRING (30 10, 10 30, 40 40)

Leaflet не поддерживает WKT напрямую, поэтому требуется промежуточное преобразование:

  • WKT → GeoJSON
  • GeoJSON → Leaflet layers

Конвертация обычно выполняется через вспомогательные библиотеки, после чего результат передаётся в L.geoJSON.


Сериализация и десериализация слоёв

Leaflet-слои могут быть сериализованы для хранения состояния карты.

Основной механизм:

  • toGeoJSON() — экспорт
  • восстановление через L.geoJSON

Дополнительно сериализуются:

  • стили
  • popup-данные
  • идентификаторы объектов
  • пользовательские свойства

Пример полного цикла:

const saved = layer.toGeoJSON();

const restored = L.geoJSON(saved, {
  onEachFeature: function (feature, layer) {
    layer.bindPopup(feature.properties.name);
  }
});

Преобразование маркеров и векторных объектов

Маркерные объекты преобразуются в GeoJSON как Point, при этом координаты извлекаются из внутреннего LatLng.

Полилинии и полигоны преобразуются через последовательность узлов:

  • Polyline → LineString
  • Polygon → LinearRing + Polygon

Многосоставные объекты сохраняют структуру:

  • MultiPolygon → массив полигонов
  • MultiLineString → массив линий

При экспортировании учитывается замыкание контуров полигона, если оно было задано при создании слоя.


Кастомные форматы и интеграция с API

Во многих архитектурах используется промежуточный формат между Leaflet и сервером. GeoJSON выступает транспортным слоем, однако нередко вводятся расширения:

  • дополнительные свойства объектов
  • идентификаторы версий
  • временные метки
  • состояния объектов

Пример расширенного объекта:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [30.5, 50.5]
  },
  "properties": {
    "id": 123,
    "status": "active",
    "updated": 1710000000
  }
}

При обмене с API происходит нормализация:

  • удаление UI-специфичных свойств
  • приведение координат к WGS84
  • упаковка атрибутов в properties

Серверная трансформация данных

В системах с высокой нагрузкой преобразование форматов часто переносится на серверную сторону. Причины:

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

Типичный pipeline:

  • Shapefile / PostGIS → GeoJSON
  • GeoJSON → упрощённый GeoJSON (simplification)
  • GeoJSON → тайлы (vector tiles)

Leaflet в таком случае получает уже готовые данные и выполняет только визуализацию.


Производительность при преобразовании данных

При работе с большими наборами геометрии преобразование форматов становится критическим фактором.

Основные оптимизации:

  • использование simplify для уменьшения количества вершин
  • кластеризация маркеров через MarkerCluster
  • ленивое добавление слоёв через LayerGroup
  • разбиение GeoJSON на чанки

Дополнительный эффект оказывает уменьшение глубины вложенности FeatureCollection, так как обход структуры влияет на время парсинга и отрисовки.

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