GeoJSON и TopoJSON: форматы и отличия

GeoJSON представляет собой текстовый формат на основе JSON, предназначенный для описания географических объектов и их свойств. Основная идея заключается в том, чтобы хранить геометрию и атрибутивные данные в единой структуре, пригодной для передачи по сети и последующей визуализации.

Структура GeoJSON строится вокруг объекта FeatureCollection, внутри которого содержатся отдельные Feature. Каждая Feature включает геометрию и свойства.

Типичная структура:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [30.5, 50.45]
      },
      "properties": {
        "name": "Объект"
      }
    }
  ]
}

Геометрия может принимать несколько форм:

  • Point — точка
  • LineString — линия
  • Polygon — полигон
  • MultiPoint, MultiLineString, MultiPolygon — наборы соответствующих геометрий
  • GeometryCollection — смешанные геометрии

Координаты в GeoJSON всегда задаются в порядке [долгота, широта], что часто становится источником ошибок при интеграции с картографическими библиотеками.

При использовании D3.js GeoJSON напрямую применяется как входной формат для географических проекций. Основной инструмент визуализации — d3.geoPath, который преобразует географические координаты в экранные.

const path = d3.geoPath(projection);

svg.selectAll("path")
  .data(geojson.features)
  .enter()
  .append("path")
  .attr("d", path);

Проекция определяет, как сферические координаты Земли отображаются на плоскости. Например:

const projection = d3.geoMercator()
  .scale(150)
  .translate([width / 2, height / 2]);

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

TopoJSON решает эту проблему через введение топологической структуры. В отличие от GeoJSON, где каждый объект хранит собственные координаты, TopoJSON выделяет общие линии (arcs) и переиспользует их между объектами.

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

Структура TopoJSON:

{
  "type": "Topology",
  "objects": {
    "regions": {
      "type": "GeometryCollection",
      "geometries": [
        {
          "type": "Polygon",
          "arcs": [[0, 1]]
        }
      ]
    }
  },
  "arcs": [
    [[0,0],[10,0],[10,10],[0,10],[0,0]]
  ]
}

Ключевой элемент — массив arcs. Каждый arc представляет собой последовательность координатных дельт, а не абсолютных значений. Это дополнительно уменьшает размер данных за счёт дельта-кодирования.

В D3.js работа с TopoJSON требует дополнительной библиотеки topojson-client. Она предоставляет функции преобразования:

  • topojson.feature — преобразует TopoJSON в GeoJSON
  • topojson.mesh — извлекает общие границы
  • topojson.merge — объединяет геометрии

Пример использования:

d3.json("data.topojson").then(data => {
  const geoData = topojson.feature(data, data.objects.regions);

  svg.selectAll("path")
    .data(geoData.features)
    .enter()
    .append("path")
    .attr("d", path);
});

Функция feature выполняет декодирование топологии и возвращает стандартный GeoJSON, который затем может использоваться с d3.geoPath.

Функция mesh особенно полезна для отображения границ между регионами без дублирования линий:

const borders = topojson.mesh(data, data.objects.regions, (a, b) => a !== b);

svg.append("path")
  .attr("d", path(borders))
  .attr("fill", "none")
  .attr("stroke", "black");

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

GeoJSON:

  • Простая и интуитивная структура
  • Независимые объекты
  • Удобство ручного редактирования
  • Более крупный размер файлов при сложных картах
  • Отсутствие топологических связей

TopoJSON:

  • Топологическая модель данных
  • Общие границы не дублируются
  • Существенное уменьшение размера файлов
  • Поддержка операций над геометриями (объединение, границы)
  • Требует дополнительного преобразования перед использованием

При визуализации в D3.js GeoJSON используется напрямую, тогда как TopoJSON почти всегда предварительно преобразуется в GeoJSON или mesh-структуры.

Процесс рендеринга географических данных в D3 строится по следующей цепочке:

  1. Загрузка данных (d3.json)
  2. При необходимости преобразование TopoJSON → GeoJSON
  3. Создание проекции (d3.geoProjection)
  4. Создание генератора пути (d3.geoPath)
  5. Привязка данных к SVG-элементам

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

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

В GeoJSON такие артефакты возникают из-за независимого хранения координат. Даже минимальные расхождения в данных приводят к появлению щелей между полигонами при отрисовке.

Декодирование TopoJSON включает этап восстановления абсолютных координат из дельт. Алгоритм проходит по массиву arcs, последовательно суммируя значения:

x[i] = x[i-1] + delta[i]
y[i] = y[i-1] + delta[i]

После восстановления координат применяется масштабирование и трансформация в зависимости от заданной проекции D3.

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

В контексте D3.js это особенно важно при рендеринге интерактивных карт, где производительность зависит от количества SVG-путей и их сложности. GeoJSON в таких сценариях может перегружать DOM, тогда как TopoJSON снижает нагрузку за счёт компактного хранения.

Сравнение форматов в контексте визуализации:

  • GeoJSON обеспечивает прямую работу с данными без промежуточных шагов
  • TopoJSON требует декодирования, но снижает объём передаваемых данных
  • GeoJSON проще для генерации на стороне клиента
  • TopoJSON эффективнее для серверной раздачи картографических слоёв

D3.js не ограничивает выбор формата, но архитектура библиотек для работы с геоданными формирует типичный паттерн: TopoJSON используется как исходный формат хранения, GeoJSON — как формат рендеринга.

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