Формат векторных тайлов

Общая структура векторных тайлов

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

Наиболее распространённым стандартом является Mapbox Vector Tile (MVT), основанный на Protocol Buffers (Protobuf). MapLibre GL JS полностью поддерживает этот формат и использует его как основной способ доставки геоданных.


Бинарная основа MVT

Формат MVT использует сериализацию Protobuf, что обеспечивает:

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

Каждый тайл представляет собой отдельный бинарный пакет, содержащий:

  • набор слоёв (layers);
  • внутри слоёв — набор объектов (features);
  • геометрии в виде закодированных команд;
  • атрибуты в формате key-value.

Система координат тайла

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

Основные характеристики:

  • координатная сетка фиксированного размера (обычно 4096 × 4096 единиц);
  • начало координат — верхний левый угол тайла;
  • ось X направлена вправо, ось Y — вниз;
  • геометрия нормализуется в пределах тайла.

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


Слои внутри тайла

Каждый векторный тайл содержит набор логических слоёв. Слой — это группировка объектов одного типа или тематической категории (например, дороги, здания, водоёмы).

Структура слоя включает:

  • имя слоя (string);
  • список ключей атрибутов (keys);
  • список значений (values);
  • набор геометрических объектов (features).

Ключевая особенность: словари ключей и значений хранятся централизованно на уровне слоя, что снижает дублирование данных.


Геометрии и их кодирование

Векторные тайлы поддерживают три базовых типа геометрий:

  • Point (точка)
  • LineString (линия)
  • Polygon (полигон)

Геометрия кодируется через последовательность команд:

  • MoveTo — перемещение без рисования;
  • LineTo — построение линии;
  • ClosePath — замыкание полигона.

Все координаты кодируются как дельты (delta encoding), что уменьшает размер данных за счёт хранения разниц между точками, а не абсолютных значений.

Дополнительно используется varint encoding, позволяющий эффективно упаковывать целые числа переменной длины.


Атрибуты объектов

Каждый геометрический объект может содержать набор атрибутов (properties), например:

  • название объекта;
  • тип дороги;
  • этажность здания;
  • скорость движения;
  • административная принадлежность.

Атрибуты хранятся в виде ссылок на ключи и значения слоя, а не как повторяющиеся строки, что снижает объём данных.


Проекция и географическая привязка

Векторные тайлы обычно генерируются в проекции Web Mercator (EPSG:3857), которая обеспечивает:

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

На этапе рендеринга MapLibre GL JS преобразует локальные координаты тайла в экранные координаты с учётом текущего масштаба и центра карты.


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

Векторные тайлы организованы в пирамиду уровней зума:

  • z — уровень детализации;
  • x, y — индексы тайла на данном уровне.

Формат URL обычно выглядит так:

/tiles/{z}/{x}/{y}.pbf

На каждом уровне зума:

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

Роль в рендеринг-пайплайне MapLibre

В MapLibre GL JS векторные тайлы проходят несколько этапов обработки:

  1. Загрузка тайлов

    • HTTP-запрос к tile server;
    • получение бинарного MVT-файла.
  2. Парсинг Protobuf

    • декодирование слоёв;
    • восстановление геометрий;
    • разбор атрибутов.
  3. Тесселяция

    • преобразование полигонов в треугольники;
    • подготовка к WebGL рендерингу.
  4. Буферизация

    • создание vertex buffers;
    • загрузка в GPU.
  5. Отрисовка

    • применение стилей;
    • компоновка слоёв;
    • рендер через WebGL.

Отличие векторных и растровых тайлов

Векторные тайлы:

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

Растровые тайлы:

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

Сжатие и оптимизация

Для уменьшения размера векторных тайлов применяются:

  • gzip или brotli-сжатие;
  • уплотнение геометрии (simplification);
  • удаление мелких или незначимых объектов на низких зумах;
  • атрибутивная агрегация;
  • общие словари ключей/значений.

Дополнительно генераторы тайлов, такие как Tippecanoe, используют пороговые фильтры и агрессивную генерализацию для оптимизации производительности.


Ограничения формата

Несмотря на эффективность, формат имеет ограничения:

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

Использование слоёв стиля MapLibre

Векторные тайлы напрямую связаны со стилями:

  • source-layer определяет слой внутри тайла;
  • paint управляет визуальными параметрами;
  • layout задаёт поведение отображения.

Пример логики связывания:

  • слой тайла roads → стиль линии дорог;
  • слой buildings → заливка и экструзия;
  • слой water → заливка водных объектов.

MapLibre GL JS динамически комбинирует данные тайлов и стиль, формируя итоговую сцену на GPU.


Геометрическая точность и extent

Стандартный extent (размер внутренней координатной сетки) чаще всего равен 4096, но может варьироваться (например, 256 или 8192).

Высокий extent:

  • повышает точность;
  • увеличивает размер данных.

Низкий extent:

  • уменьшает точность;
  • ускоряет обработку.

Баланс выбирается в зависимости от характера данных и требований к производительности.