Векторные тайлы
> Кратко. Карта рисует сеть векторными тайлами (MVT) из трёх источников: функций PostGIS через martin (участки, узлы, здания), GeoServer (остальные слои рабочей области) и архивы PMTiles через API (здания). У встраиваемой карты — свои тайлы API. Ниже — какой тайл откуда, как он кешируется и как его запросить самому.
Источники
| Источник | Что отдаёт | Адрес | Вход |
|---|---|---|---|
| martin | участки, узлы, здания — функции tgid_mvt_<слой>(z, x, y, query_params) в базе города |
<MARTIN_TILES_URL>/<префикс города><слой>/{z}/{x}/{y}?viewparams=… (за nginx — /geoserver/tiles/…) |
cookie tgid_gs |
| GeoServer | слои рабочей области города (WMS-MVT, кеш GWC) | …/geoserver/… |
cookie tgid_gs |
| PMTiles через API | статичные слои: здания zdaniya_2, zdaniya_tu |
/api/v1/static-tiles/{слой}/{z}/{x}/{y}.mvt?v=<версия> |
токен входа |
| тайлы встраивания | слои ключа встраивания | /api/v1/embed/tiles/{слой}/{z}/{x}/{y}?key= |
ключ |
Какие слои идут из martin, задают переменные веба MARTIN_TILES_URL, MARTIN_SOURCE_PREFIX, MARTIN_LAYERS
(по умолчанию heatpipesections,uzel,zdaniya_2,zdaniya_tu), MARTIN_WORKSPACE. В собранном вебе их задают
с префиксом NUXT_ (NUXT_MARTIN_TILES_URL …): nuxt.config уже вычислен при сборке. Без MARTIN_TILES_URL
всё берётся из GeoServer.
martin
- Функции генерирует
scripts/martin/build_martin_functions.pyиз SQL-представлений GeoServer рабочей области города (featuretype.xml): тот же SQL, те же атрибуты и имя слоя в тайле, поэтому стили MapLibre одни и те же.scripts/martin/build_martin_config.pyпишетconfig.yamlс источником<город>_<слой>. - Параметры — строка
viewparamsкак у GeoServer:fragments:74;RAS:on;rev:26;. Функция разбирает её сама. - Ниже минимального зума стиля функция отдаёт пустой тайл. Если стиль делит объекты по полю (узлы — по
code, участки — по фильтрам MBStyle), в тайл идут только объекты, которые стиль рисует на этом зуме. - Атрибуты, которые веб не читает (
TILE_UNUSED_COLUMNS), в тайл не идут. - После переконвертации базы API возвращает функции сам — пункт
city_schema«функции тайлов martin» изMARTIN_SQL_FILE(API одного города) илиMARTIN_SQL_DIR/<город>.sql(общий API). - Доступ: nginx публикует martin под
/geoserver/tiles/с той же проверкой cookie, что GeoServer (/auth/check); город проверяется по префиксу источника.
Кеш и версия данных
Тайл сети зависит от данных, поэтому веб добавляет в viewparams версию rev:<N> (utils/mvtTileUrl.ts,
withTileRevision). Версия — GET /api/v1/map/data-version (сумма счётчиков изменений таблиц; на копии Алматы
сейчас {"version":"26"}). После расчёта или правки сети версия растёт, адреса тайлов меняются, и ни кеш GWC,
ни кеш martin (cache_size_mb, по умолчанию 512 МБ в памяти; ключ — точная строка запроса), ни браузер старый тайл не отдают. Сбрасывать кеши
вручную не нужно; прогреть кеш заранее нельзя — ключ меняется после каждой правки.
PMTiles (статичные слои)
Здания меняются редко, а их тайлы дороже всего строить в базе. Поэтому администратор запекает их в архив
PMTiles v3 (окно Статичные слои (PMTiles)); веб подменяет адрес тайлов слоя на API
(utils/staticTiles.ts).
| Адрес | Что | Право |
|---|---|---|
GET /api/v1/static-tiles |
архивы города: зумы, охват, число тайлов, размер, version; администратору — слои, которые можно запечь |
вход |
POST /api/v1/static-tiles/{слой}/build {maxzoom, minzoom?} |
запечь (Celery; ход — GET /api/v1/task/{id}) |
администратор |
DELETE /api/v1/static-tiles/{слой} |
удалить архив — слой снова из martin или GeoServer | администратор |
GET /api/v1/static-tiles/{слой}/{z}/{x}/{y} (.mvt, .pbf — можно) |
тайл; нет тайла — 204 | вход |
GET /api/v1/static-tiles/{слой}.pmtiles |
архив целиком, с Range — для клиентов PMTiles и офлайна |
вход |
Запекаются только слои, у функции которых нет параметров (здания). Тайл отдаётся как лежит в архиве — gzip с
Content-Encoding: gzip, Cache-Control: private, max-age=604800 (7 дней); версия архива в адресе (?v=)
обходит кеш после пересборки. Архив — <STATIC_TILES_DIR>/<город>/<слой>.pmtiles (по умолчанию
files/static_tiles в каталоге API).
Пример на копии Алматы: архив zdaniya_2 — z14–16, 3120 тайлов, 22 МБ; тайл центра города:
curl -s -D - -o tile.mvt "$API/api/v1/static-tiles/zdaniya_2/14/11693/6004.mvt?v=1793287350" -H "Authorization: Bearer $TOKEN"
# 200, content-type: application/vnd.mapbox-vector-tile, content-encoding: gzip, 73 423 байта, 0,28 с
Тайл вне охвата (…/14/11693/6062.mvt) — 204 без тела.
Тайлы встраиваемой карты
/api/v1/embed/tiles/{слой}/{z}/{x}/{y}?key= строятся из тех же запросов, что OGC API
(database/ogc_features.py), но только с полями без персональных данных и с прореживанием участков на обзорных
зумах (до z12 — Ду от 500, на z12 — от 300). id признака MVT — номер объекта в базе. Тайлы обзорных зумов
API держит в памяти 10 минут, ответ — Cache-Control: public, max-age=300. Подробно — Встраивание.
Как проверить тайл
MVT — двоичный формат protobuf. Посмотреть содержимое можно GDAL (драйвер MVT читает и тайл в gzip; номер тайла нужен, чтобы получить координаты Web Mercator):
ogrinfo -ro -so -oo Z=14 -oo X=11693 -oo Y=6004 tile.mvt zdaniya_2
# Feature Count: 1299 / mvt_id: Integer64, objectid: Real, number_1: String, txt: String, floor: String, …
В браузере — map.querySourceFeatures(источник) в консоли страницы карты.
В Node fs.readFileSync маленького файла может вернуть срез общего буфера — копируйте в new Uint8Array(buf)
перед разбором.
Для разработчика
- API:
scripts/martin/(генератор функций и конфигурации,install-martin.ps1),database/pmtiles.py(формат PMTiles без сторонних пакетов),database/static_tiles.py,routers/static_tiles.py, задачаbake_static_tilesвworker.py,database/embed.py. Описания —docs/martin.md,docs/static-tiles.md. - Веб:
server/api/geoserver-layers.ts(каталог слоёв и адреса martin),utils/mvtTileUrl.ts,utils/staticTiles.ts,stores/mapStore.ts(transformRequestдобавляет токен к адресам API). - Тесты: API —
tests/test_martin_scripts.py,tests/test_static_tiles.py,tests/test_embed.py; веб —tests/utils/staticTiles.spec.ts.
