Карты: OSM vs Яндекс vs 2GIS — что реально вкрутить в этот репозиторий¶
Дата исследования: 2026-09-17. Ветка: fix4/maps-research (от release/m1).
Это не обзор «какой ГИС лучше», а выбор подложки под уже написанный MapCanvas и два стенда.
Brief (EN)¶
Recommend: self-hosted OSM vector tiles (Planetiler → PMTiles) + Copernicus DEM GLO-30 as terrain-RGB. This is the only option that keeps MapLibre + deck.gl, satisfies the isolated simulator stand (SIM-BIZ-09: no internet, no tile keys), and gives the planner a real DEM for terrain-following / AGL — already designed as MAP-08.
Fallback: Yandex Maps Tiles API as a MapLibre raster source, internet stands only
(https://aerozveno.ff). Since 2025-06-03 Tiles API is a separate product that explicitly allows
Leaflet / OpenLayers-class renderers. It does not replace DEM, has no satellite, and is
illegal to archive for the isolated sim (cache ≤ 30 days). Do not scrape JS API v3 tiles
into MapLibre — commercial JS API terms require display “solely by means of the Software”.
Kill: 2GIS MapGL as primary. Vector tiles may be consumed only through MapGL JS API; that replaces MapLibre and breaks the existing deck.gl overlay. On-Prem MVT export is an enterprise cycle, not a 15-day hackathon.
OpenFreeMap public CDN (https://tiles.openfreemap.org/styles/liberty) is phase 0 of the
recommended path (same style format, one URL swap), not a third vendor. Acceptable for a
hackathon demo on aerozveno (browsers have internet). Not acceptable as the sim-stand basemap.
1. Ограничения этого проекта (проверено в репо)¶
Каждый пункт — факт из кода или доки, не из общих знаний.
| Факт | Где |
|---|---|
Карта уже есть: MapLibre GL JS 5 + deck.gl 9, MapboxOverlay |
src/frontend/apps/planner/package.json:13-22, src/frontend/README.md:3 |
Стиль сейчас — пустой фон, ноль sources / glyphs / sprite |
MapCanvas.tsx:20-24 (OFFLINE_STYLE) |
Overlay в режиме interleaved: false; на terrain-RGB надо вернуть true |
MapCanvas.tsx:75-80; критерий — docs/task5/92-code/03-map-and-3d.md:61-71 |
attributionControl: false — при живой подложке это нарушение OSM/Яндекс |
MapCanvas.tsx:70 |
Подписи — TextLayer deck.gl, не symbol MapLibre: symbol требует glyphs-сервер |
MapCanvas.tsx:16-18, src/frontend/README.md:149-151 |
Рельеф — синтетика terrainAt(), диапазон 112…288 м MSL, район [37.6488, 55.7712] |
packages/domain/src/terrain.ts:15-36 |
| Модель полёта — огибание рельефа (terrain following), иначе GSD плывёт | terrain.ts:69-72, src/frontend/README.md:142-144 |
Целевой прод: DEM → terrain-RGB + maplibre-contour; подложка — OSM в PMTiles |
src/frontend/README.md:99-100; docs/task5/50-stack/04-frontend-3d.md:133-146 |
Задача MAP-08 уже расписана: протокол pmtiles://, raster-dem, тест MAP-R-13 |
docs/task5/92-code/03-map-and-3d.md:560,604 |
Бесполётные зоны и разрешённое ВП рисует deck.gl (nfz, allowed), не тайлы провайдера |
apps/planner/src/map/layers.ts:64-106 |
Стенд продукта: https://aerozveno.ff, кластер n1, ns aerozveno |
docs/task5/95-deploy/frontend-on-aerozveno.md:3,14; docs/task5/99-release/00-release-notes.md:140-142 |
Статику отдаёт nginx из MinIO (aerozveno-frontend) через mc mirror |
k3s/aerozveno/45-deployment-frontend.yaml:1-22,60 |
| Симулятор обязан подняться без интернета и без ключей тайл-сервисов | simulate/docs/90-final/02-requirements-registry.md:414 (SIM-BIZ-09, MUST) |
| Заказчик: третий вход — «карта высотных препятствий» (Q-09) | docs/task5/00-brief/06-customer-qa-2026-09-16.md:102-109 |
| Geoscan Planner по умолчанию берёт карту высот GEM и кеширует её офлайн | docs/task5/20-analogs/01-geoscan-planner.md:39-41 |
| Своя топосъёмка заказчика (GeoTIFF) имеет приоритет над любой глобальной ЦМР | simulate/docs/10-world/01-geodata-sources.md:84-85,109 |
| Браузеры пользователей aerozveno имеют интернет; стенд — tailnet-only | CLAUDE.md (домен .ff); факт задачи |
| Диск n1 ≈ 800 ГБ свободно (данное задания; аэрозвено уже живёт на n1) | не в репо — принимаем как ограничение стенда |
Следствие, от которого крутится вся матрица: подложка — это style у уже существующего
MapLibre, а не новый виджет. Слои галсов / БПЗ / полос захвата трогать не надо
(layers.ts не знает про тайлы). Сломать это ради «привычной» Яндекс/2GIS-картинки —
переписать MapCanvas и, для 2GIS-вектора, выкинуть MapLibre.
2. Три убийственных вопроса¶
2.1. Можно ли кормить тайлы Яндекса / 2GIS в MapLibre?¶
Яндекс JS API v3 — нет. Коммерческие «Условия использования» JS API (не путать с Tiles API):
- п. 1.1.2: доводить полученное изображение до сведения только при помощи ПО (то есть JavaScript API Яндекс Карт);
- п. 2.2.1: «Лицензиат имеет право обрабатывать получаемые данные исключительно для отображения их посредством ПО».
Источник: yandex.ru/dev/tariffs/doc/kk/jsapi/terms/ и EN yandex.com/dev/tariffs/doc/en/jsapi/terms/, прочитано 2026-09-17. Это как раз тот исторический запрет «не свой рендерер».
Кастомные слои / Deck внутри ymaps3 — да, документация это показывает
(Custom layer implementations,
прочитано 2026-09-17). Это замена MapLibre на Яндекс как движок вида, а не «тайлы в MapLibre».
Яндекс Tiles API — да, растром. Это отдельный сервис с 03.06.2025 бесплатный для коммерции
и некоммерции. Продуктовая страница прямо пишет: тайлы «подходят для работы в популярных
библиотеках для веб-картографии: Leaflet, OpenLayers и других»
(yandex.ru/maps-api/products/tiles-api,
2026-09-17). Юридически п. 6.5.1 соглашения
(yandex.ru/legal/maps_api, публикация 15.06.2026):
пользователь вправе получать тайлы «как для коммерческого, так и для некоммерческого использования,
в открытых и закрытых системах» и класть свои данные поверх. MapLibre в этом списке не назван
по имени; класс «и других» / Leaflet-совместимый XYZ — достаточное основание, чтобы считать
растровый source допустимым. Это не разрешение выдрать тайлы из JS API.
Ограничения Tiles API, проверенные по доке (Общие сведения, 2026-09-17):
- только тип «схема»; спутник и гибрид недоступны;
- 30 RPS на бесплатном тарифе;
- логотип Яндекса нужно повесить самим;
- проекция:
projection=web_mercatorобязательна, иначе сетка разъедется с deck.gl (формат запроса).
Общие запреты того же соглашения (дата публикации 15.06.2026):
- п. 5.1.5 — хранить данные дольше 30 дней нельзя (кроме временного кеша). Офлайн-архив для симулятора этим пунктом закрыт;
- п. 5.1.3 — системы мониторинга ТС / диспетчеризации в реальном времени — только на коммерческом тарифе. Планировщик (не live-трекинг) ближе к п. 6.5.1, но если на карте появятся «борт сейчас» с живым каналом — риск вырастет. Не замалчиваем.
2GIS вектор — нет. Официальный FAQ (docs.2gis.com/en/maps/overview, 2026-09-17):
Vector tiles: to access the Map Tiles API, you can use only the MapGL JS API library.
И там же: «Direct integration of vector tiles without using a library or SDK 2GIS is not supported»
(Map Tiles API). Обход — On-Premise
API Platform и экспорт MVT mapbox (6–14 ГБ, не хакатонный цикл)
(Exporting vector tiles).
2GIS растр — серая зона. Тот же FAQ: сторонние библиотеки «можно», но «compatibility with 2GIS raster maps is not guaranteed and may be disrupted at any time without notice». Для демо-стенда с чужим ToS это не опора.
Текст «Services Use Agreement» на law.2gis.ae/rules/ (прочитано
2026-09-17) — общее пользовательское соглашение платформы 2GIS, не специфика Map Tiles.
Российский law.2gis.ru в этой сессии не верифицирован дословно (см. §8). Опираемся на
документацию API, не на догадку по .ae.
2.2. OSM: что стоит self-host по РФ и можно ли OpenFreeMap на демо?¶
Данные OSM — ODbL 1.0, атрибуция «© OpenStreetMap contributors» обязательна (Attribution Guidelines). Публичные рендеры OSMF — не «данные свободны ⇒ сервер свободен»:
tile.openstreetmap.org: офлайн и bulk запрещены явно, §4 (Tile Usage Policy, 2026-09-17);vector.openstreetmap.org: то же — scraping / offline archive запрещены (Vector Tile Usage Policy).
Для этого репозитория tile.openstreetmap.org как прод-подложка неприемлема: MAP-R-13
запрещает внешние URL в стиле (92-code/03-map-and-3d.md:560), SIM-BIZ-09 запрещает ключи
и сеть на симуляторе, а OSMF ещё и офлайн-пакет со своих серверов запрещает.
Self-host векторных тайлов по РФ — реалистичен на n1. Инструмент: Planetiler (OpenMapTiles-схема, выход PMTiles), Java 21+, без PostGIS (README Planetiler, 2026-09-17):
| Экстракт | PBF (Geofabrik, снимок ~2026-09-11) | RAM Planetiler | Диск temp (5–10× PBF) | Оценка PMTiles |
|---|---|---|---|---|
| Демо-bbox s04 (~14×14 км вокруг 37.65°E 55.77°N) | вырезать osmium extract из ЦФО |
< 2 ГБ | < 2 ГБ | десятки МБ |
| Центральный ФО | 835 МБ | ~1–4 ГБ | ~5–8 ГБ | ~0,5–2 ГБ |
| РФ целиком | 3,9 ГБ (russia-latest.osm.pbf) |
~2–8 ГБ (-Xmx ≈ 0,5× PBF) |
~20–40 ГБ | ~3–8 ГБ |
Источник размеров: download.geofabrik.de/russia.html,
2026-09-17. Полный planet не нужен: сценарии крутятся вокруг московского ORIGIN
(terrain.ts:15). n1 с ~800 ГБ свободными перекрывает даже полный РФ; рекомендуемый бюджет —
ЦФО + DEM демо-района, ≤ 15 ГБ вместе с temp.
Альтернатива Planetiler — tilemaker (меньше RAM, медленнее) или готовый weekly planet OpenFreeMap (Btrfs / MBTiles). Полный planet OpenFreeMap на хакатон не качаем.
OpenFreeMap public CDN — для хакатон-демо на aerozveno да, для симулятора нет.
- Код — MIT; данные — OSM / OpenMapTiles (LICENSE.md).
- Сайт: public instance бесплатен, без ключей, без лимитов, коммерция разрешена, SLA нет (openfreemap.org, 2026-09-17).
- ToS public instance: as-is, last updated 2025-02-26, венгерское право (openfreemap.org/tos).
- Стиль MapLibre из коробки:
https://tiles.openfreemap.org/styles/liberty(Quick Start, 2026-09-17). - Автор подтвердил отсутствие usage restrictions на public instance (issue #126).
Это легальный bootstrap на стенде, где у браузера есть интернет. На изолированном симуляторе
URL tiles.openfreemap.org мёртв. Self-host того же стека = тот же Planetiler/PMTiles, что и
рекомендация.
2.3. Откуда DEM? (терренный полёт — не «красивые холмы»)¶
Планировщику рельеф нужен как число, не как картинка:
- постоянный GSD только при постоянной истинной высоте (
terrain.ts:69-72); - G2-04 «запас над рельефом» на бэкенде сейчас без модели высот
(
docs/task5/95-manual/03-limitations.md:93); - заказчик принёс «карту высотных препятствий» (Q-09);
- эталон отрасли — GEM в Geoscan Planner с офлайн-кешем
(
20-analogs/01-geoscan-planner.md:39-41). - исходный Q-33 «какой моделью рельефа пользуетесь (SRTM, своя съёмка)?»
(
00-brief/05-questions-to-customer.md:212-215) в протоколе 16.09 не отвечен: слот Q-33 занят другой репликой (06-customer-qa-2026-09-16.md:300).
Ни Яндекс Tiles API, ни 2GIS Map Tiles не отдают terrain-RGB / quantized-mesh. Рельеф в любом случае свой.
| Источник | Покрытие РФ | Лицензия | MapLibre | Офлайн | Вердикт для этого репо |
|---|---|---|---|---|---|
| Copernicus DEM GLO-30 | полное (AM/AZ/MD открыты с 2023_1) | Free & Open; при публикации: «© DLR e.V. 2010-2014 and © Airbus Defence and Space GmbH 2014-2018 provided under COPERNICUS by the European Union and ESA; all rights reserved» | rio-rgbify → terrain-RGB → raster-dem |
да, COG с AWS copernicus-dem-30m (--no-sign-request) |
основа, уже выбрана в simulate/docs/10-world/01-geodata-sources.md:59 и 50-stack/04-frontend-3d.md:139 |
| GLO-90 | полное | та же | то же | да | резерв дыр |
| SRTM GL1 | обрезан на 60° с.ш. — севернее СПб/Вологды нет | public domain | да | да | не основа |
| AWS Terrain Tiles (бывш. Mapzen, terrarium) | глобально | открытые, без SLA | да | после зеркала | быстрый старт, источник неоднородный |
| Mapbox Terrain-RGB | глобально | коммерция, токен; офлайн-кеш в ToS неясен | да | нет | убивает SIM-BIZ-09 / R-DOC-3 |
| MapTiler on-prem | глобально | от 2 500 $/год | да | Custom | не влезает в хакатон |
| Яндекс / 2GIS | — | — | нет продукта | нет | не источник DEM |
| Свой GeoTIFF заказчика | по факту работ | заказчика | тот же пайплайн | да | приоритет над GLO-30 |
Декод terrain-RGB уже зафиксирован в коде-спеке:
h = −10000 + (R·65536 + G·256 + B) · 0,1 (92-code/03-map-and-3d.md:332-335).
Район работ 14×14 км на z12 — единицы тайлов (там же:337-341).
Спутник (желателен, не обязателен):
- Яндекс Tiles API — нет;
- Яндекс JS API — есть, но только в их рендерере;
- 2GIS — спутникового слоя в публичной доке Map/Raster Tiles не нашли (2026-09-17);
- Esri World Imagery — коммерческое использование по общим Esri ToS платное / ограниченное (esri.com/en-us/legal/terms/web-site-service, 2026-09-17); в офлайн-пакет не кладётся;
- Sentinel-2 (Copernicus) — открытые данные, мозаика демо-bbox в PMTiles за вечер;
- ортофото заказчика из Metashape — уже в пирамиде симулятора
(
01-geodata-sources.md:163-166).
На защите достаточно гипсометрии + hillshade из того же DEM. Спутник — опциональный слой
satellite из Sentinel-2 по bbox s04, не Esri и не Яндекс.
3. Разбор вариантов¶
3.1. OSM¶
| Ось | Растр OSMF | Вектор OSMF | OpenFreeMap public | Self-host Planetiler + PMTiles |
|---|---|---|---|---|
| Лицензия / ToS | данные ODbL; сервер — Tile Usage Policy, офлайн запрещён | то же для vector.openstreetmap.org | MIT + ODbL; ToS as-is 2025-02-26; коммерция да | ODbL на данные, свой рантайм |
| РФ | да | да | да | да, экстракт Geofabrik |
| Ключ / цена | нет / 0 ₽ | нет / 0 ₽ | нет / 0 ₽ | 0 ₽ + CPU n1 |
| MapLibre | raster XYZ | MVT, свой стиль | нативный style URL | нативный pmtiles:// |
| Офлайн | запрещён политикой | запрещён | нет (нужен интернет) | да |
| DEM | нет | нет | нет (кладу свой) | свой Copernicus |
| Спутник | нет | нет | нет | Sentinel-2 / орто заказчика |
| Лимиты | throttle / бан | throttle | нет заявленных, нет SLA | диск / nginx |
Вывод по OSM: публичные CDN OSMF отпадают по политике и по MAP-R-13. OpenFreeMap — легальный онлайн-bootstrap. Self-host — единственный путь, который закрывает симулятор.
3.2. Яндекс Карты¶
| Ось | JS API v3 | Tiles API | Static API |
|---|---|---|---|
| Лицензия / ToS | отображение только «посредством ПО»; п. 5.1.3 (диспетчеризация) | п. 6.5.1 явно про Leaflet/OL-класс и закрытые системы; кеш ≤ 30 дней | 1000 req/сут (п. 6.3.1); не движок карты |
| РФ | да, в реестре ПО РФ | да | да |
| Ключ / цена | ключ ЛК; без ключа нельзя (п. 3.1.1) | ключ; бесплатно с 03.06.2025 при соблюдении условий | ключ; 1000/сут |
| MapLibre | нет — свой рендерер | растр XYZ, web_mercator |
одна картинка, не карта |
| Офлайн | нет | нет (5.1.5) | нет |
| DEM | нет | нет | нет |
| Спутник | да, внутри JS API | нет | схема / ограниченно |
| Лимиты | зависят от тарифа; панорамы 100/сут | 30 RPS | 1000/сут |
JS API v3 на этом фронте = выкинуть maplibregl.Map и писать мост deck.gl → ymaps3.
15 дней хакатона и MAP-08 это не переживут. Static API — превью в отчёте, не планировщик.
Tiles API — честный запасной путь только для aerozveno, где браузер ходит в интернет.
3.3. 2GIS¶
| Ось | MapGL JS API + Map Tiles | Raster Tiles / RasterJS | On-Prem MVT |
|---|---|---|---|
| Лицензия / ToS | вектор только через MapGL | сторонние библиотеки «можно», совместимость не гарантирована | договор On-Premise |
| РФ | да | да | да |
| Ключ / цена | demo 1 месяц; затем Map Tiles от 8 000 ₽ / 100k тайлов | Raster от 3 500 ₽ / 500k | enterprise |
| MapLibre | нет | растр, риск сломаться «в любой момент» | MVT да, но цикл продаж |
| Офлайн | нет | нет | да, после внедрения |
| DEM | нет | нет | нет |
| Спутник | в публичной доке не подтверждён | не подтверждён | — |
| Лимиты | 3000 единиц/мин; demo урезан | то же | по договору |
Источник цен: Pricing and billing, 2026-09-17, рубли. MapGL «бесплатен» только как библиотека — тайлы платные.
2GIS как подложка «как у заказчика в городе» красивее OSM по зданиям/POI. Цена этого —
второй WebGL-движок рядом с MapLibre и сломанный MapboxOverlay. Для хакатона — нет.
4. Матрица: веса из этого проекта, не «вообще»¶
Почему такие веса:
| Критерий | Вес | Почему здесь, а не в абстрактном сравнении карт |
|---|---|---|
| Offline fit | 0.25 | SIM-BIZ-09 MUST; R-DOC-3 / MAP-R-13; защита может быть без интернета (TODO.md:106-107) |
| License fit | 0.20 | заказчик Геоскан / ЛЦТ, РФ; ToS-бан на защите = ноль продукта |
| MapLibre fit | 0.20 | MapCanvas уже написан; второй рендерер = выкинуть неделю фронта |
| Terrain | 0.15 | терренный полёт, GSD, G2-04, Q-09, GEM у Planner |
| Effort | 0.10 | окно 15–29.09; MAP-08 оценена в 2 захода |
| Cost | 0.05 | хакатон, закупки 2GIS/MapTiler не успеть |
| Satellite | 0.05 | в брифе «желательны», не вход ТЗ |
Шкала 1–5. Итог = Σ(оценка × вес).
| Вариант | Lic 0.20 | Off 0.25 | ML 0.20 | Ter 0.15 | Sat 0.05 | ₽ 0.05 | Eff 0.10 | Итог |
|---|---|---|---|---|---|---|---|---|
| OSM self-host PMTiles + GLO-30 | 5 | 5 | 5 | 5 | 3 | 5 | 3 | 4.70 |
| OpenFreeMap public (фаза 0 OSM) | 4 | 2 | 5 | 2 | 2 | 5 | 5 | 3.45 |
| Яндекс Tiles API → MapLibre raster | 3 | 1 | 4 | 1 | 1 | 5 | 3 | 2.40 |
OSMF raster tile.openstreetmap.org |
2 | 1 | 4 | 1 | 1 | 5 | 5 | 2.40 |
| 2GIS Raster → MapLibre | 3 | 1 | 3 | 1 | 1 | 2 | 3 | 2.05 |
| Яндекс JS API v3 (свой рендерер) | 2 | 1 | 1 | 1 | 4 | 4 | 1 | 1.50 |
| 2GIS MapGL (свой рендерер) | 2 | 1 | 1 | 1 | 1 | 2 | 1 | 1.25 |
| Яндекс Static API | 2 | 1 | 1 | 1 | 2 | 3 | 2 | 1.40 |
OSM self-host выигрывает не «потому что open source», а потому что три самых тяжёлых веса (offline / license / MapLibre) у него пятёрки, а DEM уже спроектирован в MAP-07/08. Яндекс Tiles — лучший не-OSM вариант, который не ломает MapLibre. 2GIS MapGL — худший по сумме именно из-за принудительной смены рендерера.
quadrantChart
title Подложка × этот репозиторий (офлайн vs MapLibre)
x-axis "Чужой рендерер" --> "Нативный MapLibre"
y-axis "Только онлайн" --> "Живёт офлайн"
quadrant-1 "Берём"
quadrant-2 "Дорого / не успеть"
quadrant-3 "Не берём"
quadrant-4 "Стенд aerozveno only"
OSM self-host PMTiles: [0.88, 0.92]
OpenFreeMap public: [0.90, 0.38]
Yandex Tiles API: [0.72, 0.22]
OSMF raster: [0.70, 0.12]
2GIS Raster: [0.55, 0.18]
Yandex JS API v3: [0.12, 0.10]
2GIS MapGL: [0.08, 0.10]
5. Вердикт¶
Рекомендация: OSM-вектор self-host (Planetiler → PMTiles) + Copernicus DEM GLO-30
(terrain-RGB в том же PMTiles-контуре). Это прямое исполнение уже принятых MAP-08 и
50-stack/04, а не новая идея.
Запасной путь: Яндекс Tiles API как raster source в том же MapLibre, только на
https://aerozveno.ff (браузер с интернетом). DEM всё равно свой. На симулятор этот путь
не переносится.
Фаза 0 рекомендации (не отдельный вендор): пока Planetiler крутится на n1, aerozveno
может открыть https://tiles.openfreemap.org/styles/dark / liberty — одна строка в
style. На симулятор этот URL не попадает.
flowchart TD
start[Нужна подложка в MapCanvas] --> q1{Симулятор / docker compose<br/>без интернета?}
q1 -->|да| osmSelf[OSM PMTiles + GLO-30 на томе]
q1 -->|нет, aerozveno| q2{PMTiles уже лежат в MinIO?}
q2 -->|да| osmSelf
q2 -->|нет, сегодня| ofm[OpenFreeMap style URL<br/>фаза 0]
ofm --> later[Заменить URL на pmtiles://]
later --> osmSelf
osmSelf --> dem[raster-dem + interleaved true]
start --> q3{Заказчик требует<br/>привычную Яндекс-схему?}
q3 -->|да, и есть интернет| ya[Yandex Tiles API raster<br/>web_mercator + логотип]
ya --> demOwn[DEM всё равно GLO-30]
q3 -->|нет| q1
start --> kill1[2GIS MapGL]
kill1 --> no1[Ломает MapLibre / deck.gl]
start --> kill2[Яндекс JS API тайлы в MapLibre]
kill2 --> no2[ToS: только посредством ПО]
start --> kill3[tile.openstreetmap.org]
kill3 --> no3[Tile Usage Policy: офлайн запрещён]
6. Как вкрутить в ЭТОТ код¶
6.1. Рекомендация — проводка OSM + DEM¶
Точка врезки одна: src/frontend/apps/planner/src/map/MapCanvas.tsx.
layers.ts не меняется. terrain.ts меняется по уже описанному контракту TerrainSource
(92-code/03-map-and-3d.md:313-335).
Что меняется во фронте
- Зависимости
@geoscan/planner:pmtiles, позжеmaplibre-contour(MAP-09). - В
MapCanvasдоnew maplibregl.Map:
import { Protocol } from 'pmtiles';
const protocol = new Protocol();
maplibregl.addProtocol('pmtiles', protocol.tile);
- Заменить
OFFLINE_STYLE(MapCanvas.tsx:20-24) на стиль без внешних хостов (тест MAP-R-13):
const BASEMAP_STYLE: StyleSpecification = {
version: 8,
glyphs: '/tiles/glyphs/{fontstack}/{range}.pbf',
sprite: '/tiles/sprite',
sources: {
osm: {
type: 'vector',
url: 'pmtiles:///tiles/basemap.pmtiles',
attribution: '© OpenStreetMap contributors',
},
terrain: {
type: 'raster-dem',
url: 'pmtiles:///tiles/terrain.pmtiles',
tileSize: 256,
encoding: 'mapbox',
attribution:
'produced using Copernicus WorldDEM-30 © DLR e.V. 2010-2014 and © Airbus Defence and Space GmbH 2014-2018 provided under COPERNICUS by the European Union and ESA; all rights reserved',
},
},
layers: [
{ id: 'background', type: 'background', paint: { 'background-color': '#0D1117' } },
// слои OpenMapTiles/Protomaps, обрезанные под тёмную тему токенов
// symbol-слои либо вендорим glyphs, либо НЕ кладём — подписи сценария
// остаются TextLayer (MapCanvas.tsx:16-18)
],
terrain: { source: 'terrain', exaggeration: 1 },
};
attributionControl: true(сейчасfalse, строка 70) — иначе ODbL/Copernicus нарушены.- Когда в стиле есть
raster-dem:interleaved: trueиmap.once('load', …)доaddControl(overlay)— как написано в92-code/03-map-and-3d.md:64-71. - Runtime-переключатель, не зашивать URL. Расширить
AppRuntimeConfig(packages/state/src/runtime-config.ts:3-11):
mapBasemap?: 'pmtiles' | 'openfreemap' | 'yandex-tiles';
Читать из /config.json шелла (тот же файл, что уже не кешируется nginx,
45-deployment-frontend.yaml:38-40). На симуляторе значение только pmtiles.
- Glyphs. Это главная ловушка текущего кода: пустой стиль специально без
glyphs, чтобы демо открывалось без сети. Векторная подложка с подписями улиц требует PBF-глифов (~несколько МБ). Два допустимых пути: - вендорить glyphs OpenMapTiles в
/tiles/glyphs/(офлайн-честно); -
оставить style без symbol-слоёв, подписи сценария как сейчас через
TextLayer. Второй путь быстрее и не ломает «карта не ходит в сеть» (README.md:149-151). Для защиты достаточно гидрографии / дорог / землепользования без OSM-лейблов. -
DemTerrain.preload(bbox)приloadScenario— район 14×14 км, z12, единицы тайлов.SyntheticTerrainостаётся для тестов и сценариев без файла.
Что self-host и куда
Стенд продукта уже на n1 (kubectl --context n1, ns aerozveno). Диск ~800 ГБ.
| Артефакт | Где собрать | Куда положить | Бюджет |
|---|---|---|---|
basemap.pmtiles |
n1, разово: osmium extract bbox s04 или Planetiler --area=central |
бакет MinIO aerozveno-frontend/tiles/ → nginx /tiles/ |
демо-bbox: < 100 МБ; ЦФО: ~1 ГБ + 8 ГБ temp |
terrain.pmtiles |
n1: AWS copernicus-dem-30m → clip bbox → rio-rgbify → PMTiles |
тот же /tiles/ |
демо 14×14 км: < 20 МБ |
glyphs/ + sprite |
вендор из OpenMapTiles / Protomaps, если нужны OSM-лейблы | /tiles/glyphs, /tiles/sprite |
< 20 МБ |
| Sentinel-2 мозаика (опц.) | GDAL warp bbox s04, z8–z15 | /tiles/satellite.pmtiles |
< 200 МБ на демо |
Не класть PMTiles в git. Не класть в emptyDir как единственную копию: под пересоздаётся.
Источник правды — MinIO, как у бандла (45-deployment-frontend.yaml:1-10). Nginx уже
умеет try_files $uri — файл /tiles/basemap.pmtiles отдастся, SPA-fallback не
перехватит существующий путь.
Сборку не держать в hot path деплоя. Скрипт scripts/build-map-tiles.sh (ещё нет) +
ручной mc cp в бакет. Полный РФ не собираем, пока жюри не попросит «покрутить всю страну».
Симулятор, изолированная сеть
SIM-BIZ-09: docker compose up без интернета и без ключей, «фронт открывается, рельеф
отображается». Те же два PMTiles копируются в образ / volume симулятора (сейчас офлайн-стиль
simulate — public/style/offline.json, simulate/docs/92-api/02-user-guide.md:80-82).
mapBasemap зашит в pmtiles. Ни OpenFreeMap, ни Яндекс, ни OSMF. Исходящих URL в стиле нет —
это тот же барьер MAP-R-13.
flowchart LR
subgraph n1["n1 / ns aerozveno"]
minio["MinIO aerozveno-frontend"]
fe["geoscan-frontend nginx"]
minio -->|mc mirror /tiles/*.pmtiles| fe
end
subgraph build["разовая сборка на n1"]
pbf["Geofabrik ЦФО или osmium bbox"]
planetiler["Planetiler → basemap.pmtiles"]
glo["Copernicus GLO-30 COG"]
rgbify["rio-rgbify → terrain.pmtiles"]
pbf --> planetiler
glo --> rgbify
planetiler --> minio
rgbify --> minio
end
subgraph browser["браузер оператора"]
ml["MapLibre style pmtiles://"]
deck["deck.gl layers.ts без изменений"]
dem["TerrainSource.elevationAt"]
ml --> deck
ml --> dem
end
fe -->|HTTPS aerozveno.ff Range| ml
subgraph sim["симулятор, air-gap"]
vol["те же PMTiles в volume"]
vol --> ml2["MapLibre, mapBasemap=pmtiles"]
end
Фаза 0 на aerozveno (пока нет файла)
style: 'https://tiles.openfreemap.org/styles/dark' // или liberty
Атрибуция: OpenFreeMap / OpenMapTiles / OSM (MapLibre добавит сам, если не выключать
attributionControl). Это нарушает MAP-R-13 — допустимо только как временный
mapBasemap: 'openfreemap' на интернет-стенде, с тестом-исключением. На симулятор не тащить.
6.2. Fallback — Яндекс Tiles API в том же MapLibre¶
Только если к защите PMTiles не готовы и жюри/заказчик хочет «карту как в Яндексе», и стенд — aerozveno (интернет в браузере).
- Ключ Tiles API завести в ЛК Яндекса, сразу в creds-store
project/geoscan/YANDEX_TILES_API_KEY(не в git, не вconfig.jsonпубличным текстом без ограничения referrer). - Проксировать тайлы через gateway
/api/tiles/yandex/{z}/{x}/{y}или ограничить ключ HTTP Refererhttps://aerozveno.ff/*. Прямой ключ в бандле на tailnet терпим на 2 недели, на любой публичный контур — нет. - Источник в стиле (не JS API):
https://tiles.api-maps.yandex.ru/v1/tiles/
?x={x}&y={y}&z={z}&lang=ru_RU&l=map
&projection=web_mercator&apikey=…
projection=web_mercator обязателен: дефолт Яндекса — эллиптический меркатор,
deck.gl живёт в Web Mercator.
4. Свой HTML-оверлей с логотипом-ссылкой на https://yandex.ru/maps — требование доки
Tiles API, MapLibre сам его не нарисует.
5. raster-dem остаётся нашим PMTiles. Яндекс рельеф не подменяет.
6. Кеш браузера ≤ 30 дней, не собирать mbtiles из этих PNG — п. 5.1.5.
7. На симуляторе этот mapBasemap отсутствует. Ветка yandex-tiles в config.json
симулятора — ошибка конфигурации, ловить тестом.
Не делать: подменять maplibregl.Map на ymaps3.YMap; не брать спутник из JS API
«тихо»; не класть геокодер Яндекса на OSM-подложку (п. 6.6.1 — геокодер только вместе
с JS API и только на их карте).
7. Что сознательно не берём¶
- 2GIS MapGL как движок вида — ломает
MapboxOverlayи MAP-08. - Яндекс JS API тайлы в MapLibre — ToS 1.1.2 / 2.2.1.
tile.openstreetmap.org— Tile Usage Policy §4 + MAP-R-13.- Mapbox / Cesium ion / Google Photorealistic 3D — токены и запрет офлайн-кеша;
уже отведены в
simulate/docs/10-world/01-geodata-sources.md:73-78. - Esri World Imagery как бесплатный спутник — коммерческие ToS Esri.
- FABDEM — CC BY-NC-SA, несовместим с коммерческим продуктом
(
01-geodata-sources.md:67).
8. Что не удалось проверить¶
| Вопрос | Почему | Как не гадаем |
|---|---|---|
Полный текст российского law.2gis.ru (не .ae) на Map Tiles |
страница .ae открылась; .ru в этой сессии не сняли дословно | опираемся на docs.2gis.com FAQ про third-party libraries — этого достаточно, чтобы отвести вектор |
| Платный офер Яндекса целиком (не публичные «Условия конкретных сервисов») | часть тарифов за ЛК | для Tiles API хватает публичного 6.5.* и продуктовой страницы от 03.06.2025 |
| Актуальный SLA / аптайм OpenFreeMap | ToS as-is, «may discontinue at any time» | не ставим public instance в критерий приёмки симулятора |
| Точная точность GEM Геоскана | ОВ-2 в simulate/docs/10-world/01-geodata-sources.md:336 |
объявляем GLO-30 в манифесте мира, не притворяемся GEM |
| Покрытие спутникового слоя 2GIS | в overview / Map Tiles / Raster Tiles не описан | считаем «нет», пока не покажут иначе |
| Свободное место n1 прямо сейчас | в репо цифры нет | бюджет ≤ 15 ГБ; если диск меньше — только bbox s04 |
9. Источники (дата обращения везде 2026-09-17, если не указано)¶
Юридика и доки провайдеров
- Яндекс, Terms of Use for Yandex Maps Specific Services, публикация 15.06.2026: https://yandex.ru/legal/maps_api/?lang=en
- Яндекс, Условия использования JS API (коммерческие, «только посредством ПО»): https://yandex.ru/dev/tariffs/doc/kk/jsapi/terms/
- Яндекс Tiles API, продукт (Leaflet/OpenLayers, бесплатно с 03.06.2025): https://yandex.ru/maps-api/products/tiles-api
- Яндекс Tiles API, ограничения (схема, не спутник, 30 RPS, логотип): https://yandex.ru/maps-api/docs/tiles-api/index.html
- Яндекс Tiles API,
projection=web_mercator: https://yandex.kz/maps-api/docs/tiles-api/request.html - 2GIS, Overview / third-party libraries: https://docs.2gis.com/en/maps/overview
- 2GIS Map Tiles API: https://docs.2gis.com/en/maps/others/maptiles/overview
- 2GIS On-Prem MVT export: https://docs.2gis.com/en/on-premise-api-platform/user-guide/vector-tiles
- 2GIS Pricing (₽): https://docs.2gis.com/en/platform-manager/subscription/pricing
- OSMF Tile Usage Policy: https://operations.osmfoundation.org/policies/tiles/
- OSMF Vector Tile Usage Policy: https://operations.osmfoundation.org/policies/vector/
- OpenFreeMap, коммерция / атрибуция: https://openfreemap.org/
- OpenFreeMap ToS, last updated 2025-02-26: https://openfreemap.org/tos/
- OpenFreeMap Quick Start (
styles/liberty): https://openfreemap.org/quick_start/ - OpenFreeMap LICENSE: https://github.com/hyperknot/openfreemap/blob/main/LICENSE.md
- Planetiler RAM/диск: https://github.com/onthegomap/planetiler
- Geofabrik РФ / ЦФО размеры: https://download.geofabrik.de/russia.html
- Copernicus DEM GLO-30 licence / citation: https://dataspace.copernicus.eu/explore-data/data-collections/copernicus-contributing-missions/collections-description/COP-DEM
- Esri Web Site and Service Terms: https://www.esri.com/en-us/legal/terms/web-site-service
Этот репозиторий — цитаты в §1 и по тексту.