Размер офлайн-пакета: вектор OSM + рельеф + покров (замер на Словении)
Замер к плану offline_world_data.md (этапы 0 и 1). 30.09.2026. Код игры не менялся. Код, числа,
картинки и команды — tools/research/osm_pack/ (README там же).
Коротко. Вся Словения в нашем формате занимает ≈ 80 МБ: вектор OSM 63 МБ, рельеф 30 м 14 МБ, покров 25 м 2,4 МБ. 81 % вектора — землепользование. В Словении это импорт, очень плотная разметка, так что оценка верхняя. Для Альп пакет выйдет порядка 150–300 МБ на страну. Россия одним пакетом — ~14 ГБ (оценка), почти всё — рельеф и покров, а не OSM. Раздавать её нужно по субъектам (Республика Алтай — порядка 90 МБ, оценка) или ячейками по запросу. Рисовать подложку из вектора дёшево: квадрат 10×10 км при 1 м/пикс рисуется на CPU в один поток за 1–2 с.
1. Что замерили
- Источник. Geofabrik
europe/slovenia-latest.osm.pbf, выгрузка от 28.09.2026 20:23Z. Фильтр слоёв —osmium tags-filter(filter.txt). Заборы (barrier) и дома (building) не брали. - Формат (
osmpack.py). Ячейка 0,25°×0,25° (≈ 19×28 км). В ячейке объекты разложены по потокам: дороги, track/path, ж/д, водотоки, водоёмы, покров, обрывы, place, «объекты для пилота», имена. На объект пишется класс (varint) и байт флагов (ширина, высота/ele, имя, тоннель, мост). Координаты — целые метры в локальной сетке ячейки: дельты по цепочке, zigzag, varint. Мультиполигоны собраны в кольца с дырами (pyosmium). Геометрия режется по границам ячеек и упрощается Дугласом–Пейкером с допуском 1 м. Каждая ячейка сжимается отдельно: brotli q11 и zstd 19. - Рельеф и покров (
slovenia_rasters.py). Взяты два пробных квадрата 0,5°: «горы» (Юлийские Альпы: Триглав, Бохинь, Соча) и «холмы» (к югу от Любляны). В каждом по 4 ячейки. Результат пересчитан на площадь страны. Рельеф — Copernicus GLO-30 в родной сетке (1″ ≈ 31×21 м). Высоты квантованы (int с шагом 1 м или 0,1 м от минимума ячейки), затем плоский предсказатель a+b−c, zigzag и разнос по байтовым плоскостям. Покров — классы ESA WorldCover (uint8) на 10 м и на 25 м (ближайший сосед). Скачано ≈ 83 МБ. - Итог по OSM считали по 65 ячейкам, которые пересекают границу Словении (площадь 20,4 тыс. км²).
2. Словения: таблица размеров
| Что | Сырое | brotli | zstd | байт/км² (brotli) |
|---|---|---|---|---|
| Исходный PBF Geofabrik (весь OSM) | 313,3 МБ | — | — | 15 460 |
| PBF после фильтра слоёв (с метаданными / без) | 252,9 / 235,7 МБ | — | — | — |
(для сравнения: только building=*) | 47,8 МБ | — | — | — |
| Наш вектор, всё | 85,4 МБ | 63,2 МБ | 64,0 МБ | 3 100 |
| Наш вектор без track/path | 80,1 МБ | 59,0 МБ | 59,7 МБ | 2 890 |
| — землепользование + natural (+обрывы) | 70,6 | 51,5 | 52,0 | 2 520 |
| — дороги (без track/path) | 6,6 | 5,3 | 5,3 | 260 |
| — track/path | 5,3 | 4,2 | 4,3 | 210 |
| — вода (линии 1,0 + площади 0,25) | 1,5 | 1,2 | 1,2 | 60 |
| — объекты для пилота (ЛЭП, канатки, аэродромы, старты, мачты, вершины) | 0,56 | 0,40 | 0,43 | 19 |
| — place (узлы и полигоны) | 0,55 | 0,42 | 0,44 | 21 |
| — ж/д | 0,11 | 0,09 | 0,09 | 4 |
| — имена (place, вершины, аэродромы, старты) | 0,23 | 0,12 | 0,13 | 6 |
| Рельеф 30 м, шаг 1 м, с предсказателем | — | 13,6 МБ | 14,1 МБ | 670 (горы 709, холмы 633) |
| рельеф 30 м, шаг 0,1 м, с предсказателем | — | 26,0 МБ | — | 1 280 |
| рельеф 30 м, шаг 1 м, без предсказателя | — | 24,4 МБ | — | 1 200 |
рельеф 30 м, float32 + brotli (как data/terrain сейчас) | — | 91,8 МБ | — | 4 530 |
| дальний рельеф ~90 м / ~210 м (средние 3×3 / 7×7), шаг 1 м | — | 2,2 / 0,5 МБ | — | 109 / 25 |
| Покров WorldCover 25 м | — | 2,4 МБ | 2,5 МБ | 117 |
| покров WorldCover 10 м | — | 7,5 МБ | 8,5 МБ | 371 |
| Пакет Словении целиком (вектор + рельеф 30 м/1 м + покров 25 м + дальний 210 м) | — | ≈ 80 МБ | — | ≈ 3 900 |
Разбивка по слоям — сумма потоков, каждый сжат отдельно в своей ячейке, поэтому она на ~1 % больше «всего». Ячейка brotli: медиана 1,0 МБ, максимум 2,4 МБ. Рельеф и покров — пересчёт двух квадратов (8 ячеек) на 20 271 км², то есть оценка по замеру.
Время (один поток Python, 20 ядер не использованы):
- фильтр
osmium tags-filter— 9 с; - разбор, сборка мультиполигонов, нарезка и упрощение (pyosmium + shapely) — 865 с;
- сжатие — 907 с. Это с тройной работой (весь блоб, вариант без track/path, каждый поток отдельно; brotli q11). В сборщике хватит одного прохода.
Объекты для пилота в Словении (число объектов OSM; в скобках — сколько из них с
height/ele):
| Тип | Сколько |
|---|---|
Старты и посадки дельта/пара (sport=free_flying, free_flying:*) | 63: старт 31 точка + 8 полигонов (20 с ele), «старт;верхняя посадка» 1, верхняя посадка 1, посадка 8 + 2, «площадка» без уточнения 8 + 4 |
| Аэродромы / взлётные полосы / вертолётные площадки | 40 (10) / 3 полосы-airstrip + 53 runway / 55 (3) |
| ЛЭП | линий 749, малых линий 3 615, опор 13 540 (4), столбов 44 104 (149) |
| Канатки | линий ≈ 250 (кресельные 56, бугельные 45+31+35, грузовые 24, тросовые спуски 23 и др.), опор 742 |
| Ветряки | 20 (0) |
| Мачты / башни / трубы / телебашни | 682 (80) / 2 317 (171) / 71 (11) / 5 (1) |
| Вершины / седловины с именем | 11 128 (11 107) / 364 (357) |
Высота у мачт и башен указана редко (6–12 %). Под man_made=tower попадают и колокольни, и
смотровые вышки. Заданной высоты у препятствий почти нет: её придётся брать по типу или из DSM.
3. Растеризация 10×10 км при 1 м/пикс (CPU)
Использовали skia-python: один поток, сглаживание, 10000×10000 пикс. Цвет задан по классу, тоннели и точки не рисовали. Декодировали целые ячейки (2 шт., ≈ 970 км², хотя нужно 100 км²) на чистом Python.
| Квадрат | Объектов | Декодирование | Сборка путей | Рисование |
|---|---|---|---|---|
| Бохинь (46,29° с. ш., 13,88° в. д.) | 49 119 | 1,5 с | 1,2 с | 1,7 с |
| Триглав / Трента (46,39; 13,78) | 36 314 | 1,4 с | 1,0 с | 1,1 с |
Пересчёт на плитку 2×2 км при 1 м выходит < 0,1 с на CPU (оценка), так что на GPU запас большой.
Картинки (уменьшенная копия 10×10 км и фрагмент 2×2 км в масштабе 1:1):
tools/research/osm_pack/results/bohinj_full_small.jpg,bohinj_crop_1m.jpgtools/research/osm_pack/results/triglav_full_small.jpg,triglav_crop_1m.jpg

Что видно. Лес, луга, поля, посёлки, реки с шириной и дороги ложатся чисто, швов по
границам ячеек не видно. Выше леса в районе Триглава OSM почти пуст. bare_rock/scree
размечены пятнами, и большие площади остаются цвета «нет данных». Значит, WorldCover (класс 60 —
голый грунт, 70 — снег) нужен как подложка под вектором, а не вместо него.
4. Землепользование — куда уходит объём
Проверка на трёх ячейках (lc_check.py: две у Бохиня и одна у Любляны):
- Общие вершины. Уникальных вершин 61–70 % от всех: соседние полигоны импорта хранят общую границу дважды. Топологическое кодирование (общие рёбра один раз) даст порядка −25…35 % слоя (оценка по вершинам, не проверено).
- Заранее растеризованный покров (uint8-классы без сглаживания): на 5 м это 0,55–0,85 объёма вектора, на 2 м — 1,8–2,4. Вектор с точностью 1 м компактнее растра той же чёткости. Растр 5 м меньше, но при подложке 0,5–1 м края полей будут ступенями по 5 м.
- Выкинуть track/path — это −7 % (4,2 МБ). Мало, а тропы и грунтовки видны с воздуха.
5. Экстраполяция (оценка)
Логика расчёта:
- OSM «по доле PBF». Наш пакет = 20,2 % исходного PBF Словении; эту долю переносим на размеры PBF других регионов (Content-Length на 30.09.2026). В Словении дома — всего 15 % PBF, а там, где их больше (города, Россия, мир), доля нужных слоёв ниже. Поэтому это оценка сверху.
- OSM «по плотности». 3,1 КБ/км² Словении × площадь. Годится только для так же плотно размеченных стран.
- Рельеф + покров. 790 байт/км² (рельеф 30 м с шагом 1 м — 670, покров 25 м — 117) × площадь. Словения холмистая и гористая, равнины сжимаются лучше, так что и это оценка сверху.
| Регион | PBF | OSM (доля PBF) | OSM (плотность Словении) | Рельеф 30 м + покров 25 м | Итого (оценка) |
|---|---|---|---|---|---|
| Словения (замер) | 313 МБ | 63 МБ | 63 МБ | 16 МБ | ≈ 80 МБ |
| Швейцария | 547 МБ | 110 МБ | 129 МБ | 33 МБ | ≈ 150 МБ |
| Австрия | 811 МБ | 164 МБ | 262 МБ | 66 МБ | ≈ 230–330 МБ |
| Россия | 4,17 ГБ | ≤ 0,84 ГБ | (53 ГБ — неприменимо) | 13,5 ГБ | ≈ 14 ГБ |
| Мир (planet, суша без Антарктиды) | 95 ГБ | ≤ 19 ГБ | — | 106 ГБ | ≈ 110–125 ГБ |
Покров 10 м вместо 25 м добавляет примерно +25 % к растрам: Россия +4,3 ГБ, мир +34 ГБ.
Разброс плотности OSM (замер фильтра до отмены расширения на Алтай). Республика Алтай
(92,9 тыс. км², вырез из siberian-fed-district по границе, complete_ways): PBF 63,3 МБ,
то есть 680 байт/км² против 15 460 у Словении — в 23 раза реже. Нужные слои составляют там
91 % PBF: домов мало, а покров размечен полигонами. Пакет Республики Алтай ≈ 0,2 × 63 ≈ 13 МБ
OSM + 93 тыс. км² × 790 байт ≈ 73 МБ растров ≈ 90 МБ (оценка; пакет не собирали). В
редко размеченных регионах основной объём занимают рельеф и покров.
6. Выводы
- Смысл есть на уровне страны или субъекта, а не всей России. Словения — 80 МБ, альпийская страна — 150–300 МБ, субъект РФ — десятки–сотни МБ (оценка). Россия целиком — ~14 ГБ, мир — ~110+ ГБ. Это уже не «положить рядом с игрой»: нужны пакеты по регионам или ячейки 0,25° по запросу (медиана 1 МБ на ячейку OSM плюс ~0,4 МБ растров).
- Рельеф хранить как int16 с шагом 1 м и плоским предсказателем, brotli. Это в 6,7 раза меньше, чем float32 + brotli сейчас: 670 против 4 530 байт/км². Шаг 0,1 м удваивает размер, а при шуме GLO-30 в метры смысла не имеет. Дальний слой (~210 м) почти бесплатный: 25 байт/км².
- Покров WorldCover 25 м (117 байт/км²) — как фон под вектором. Там, где OSM пуст (высокогорье Триглава), без него никак. 10 м — втрое дороже, и при векторе нужен мало.
- OSM. Формат «ячейка 0,25° + потоки по слоям + zigzag-varint + brotli» работает. brotli и zstd близки (zstd больше на 1–4 % у OSM и рельефа, на 13 % у покрова 10 м; распаковывается быстрее). Главный резерв — топология покрова (−25…35 %, оценка). track/path оставить. Заборы не берём (решение пользователя).
- Точности хватает. Квантование 1 м + Дуглас–Пейкер 1 м дают подложку 1 м/пикс без видимых изъянов (см. фрагменты 1:1).
Риски
- Лицензия ODbL. Пакет — производная база данных. Раздавать его можно с атрибуцией «© OpenStreetMap contributors» и на условиях ODbL (share-alike для базы, не для игры).
- Скорость сборки. Однопоточный pyosmium — 15 мин на Словению. На Россию (PBF в 13 раз больше) это часы. Нужен параллельный разбор по регионам или ячейкам либо сборщик на C++ (libosmium).
- Неоднородность OSM. Импорт покрова есть не везде. Высоты препятствий размечены редко.
Под
man_made=towerпопадают колокольни. - Сдвиг покрова. Классы покрова в OSM и в WorldCover размечены по-разному: на стыке будет видна граница «вектор/растр».
7. Что не проверено
- Реальные пакеты Швейцарии, Австрии и Республики Алтай (там только оценка; сборка Алтая отменена).
- Топологическое кодирование покрова и уровни детализации для дали.
- Сетка 0,5 м и другие допуски упрощения.
- Растеризация на GPU и декодер не на Python.
- Рельеф и покров по всей Словении (замер по 8 ячейкам 0,25° из 65).
- Равнинные регионы (там рельеф сжимается лучше).