8.0 KiB
Город сверху — генератор карты по OpenStreetMap (MVP)
Выделяете на карте небольшой город или район → по данным OSM строится подробная карта с видом строго сверху: дороги реальной ширины с тротуарами и разметкой, парковки с машинами, деревья, и у каждого здания — этажи, комнаты, двери, окна, лестницы и мебель, нарисованные простыми геометрическими фигурами, как на плане квартиры.
Всё работает в браузере, без сервера: данные берутся из Overpass API, генерация идёт в Web Worker'ах, готовый мир сохраняется в IndexedDB.
Запуск
Нужен Node.js 18+.
npm install
npm run dev # http://localhost:5173/ (пересборка на лету)
npm run build # сборка в dist/ — можно положить на любой статический хостинг
npm run typecheck
Для автоматических проверок сетевого клиента нужен Node.js 22+: npm test.
Тесты проверяют таймауты, переключение серверов и отмену без обращения к сети.
Данные сначала запрашиваются у maps.mail.ru, затем у overpass-api.de и
overpass.private.coffee. На каждый запрос отводится 45 секунд, включая загрузку
ответа; после ошибки или таймаута используется следующий сервер. Лимит обработки
запроса на стороне Overpass — 30 секунд. Кнопка «Отмена» прерывает запрос и ожидание
перед повтором.
Без интернета можно проверить на образце: «Другие способы» → «Сгенерировать из выгрузки
Overpass» → samples/balzers-2013.json (Бальцерс, Лихтенштейн, данные OSM 2013 года).
Генерация из файла без браузера (для отладки генератора):
npm run cli -- samples/balzers-2013.json 47.058 9.492 47.074 9.518 world.json
Управление
- перетаскивание — сдвиг, колесо / щипок — масштаб, двойной клик — приблизить;
- справа — этаж для всей карты (⌂ — крыши),
PgUp/PgDnили[]; - клик по зданию — карточка: вид, этажность (из OSM или оценка), квартиры, спальные места, свой переключатель этажей только для этого здания;
- «Экспорт мира» — весь мир одним файлом
.json.gz(будущий формат для игры).
Как устроена генерация
Overpass JSON ─► city.ts ──────────────► зоны, дороги, контуры зданий, деревья, парковки
│ classify.ts вид здания (по тегам, POI внутри, landuse, площади) и этажность
▼
interior.ts (в воркерах) ─► этажи: сетка 0.5 м в осях здания
│ схема: секции с подъездами | коридор | простая раскладка
│ деление на комнаты по программе (м²), несколько попыток с оценкой
│ двери = остовное дерево по графу смежности, санузлы и спальни — тупики
│ вход с фасада к дороге, окна с шагом по типу здания
▼
furnish.ts + catalog.ts ──► мебель по правилам для каждого типа комнаты
▼
finalize.ts ──────────────► общие модели предметов, округление до 1 см
- Сид здания = OSM-id ⊕ сид мира — один и тот же город всегда генерируется одинаково.
- Многоквартирные дома — секционные: подъезд с лестницей (и лифтом от 5 этажей), площадка, 1–4 квартиры вокруг неё; на первом этаже — проход к входу, у домов с магазинами вместо квартир магазины со своими входами с улицы.
- Офисы, школы, больницы, гостиницы — коридорная схема.
- Дома, магазины, кафе, цеха, склады, храмы, гаражи — простая раскладка (у гаражных рядов — отдельные боксы с воротами).
Модель данных мира (src/types.ts)
Заложено под будущую симуляцию:
| Что | Зачем потом |
|---|---|
Door.rooms = [комната, комната | 'outside'] |
рёбра графа навигации внутри здания |
Stairs (одно место на всех этажах, up/down), лифты |
переходы между этажами |
Unit — квартира / магазин / офис с roomIds и beds |
домохозяйства и рабочие места для жителей |
Prop.blocksMove, Prop.blocksSight, tags (sleep:2, sit:4, work, cook, storage…) |
коллизии, линия обзора, что агент может сделать с предметом |
Wall с разрывами под двери и окна, Window |
коллизии и видимость (окна прозрачны для взгляда) |
Road с шириной, тротуарами, oneway, слоями |
граф улиц для перемещения по городу |
все объекты с id |
хранение состояния: открытая дверь, взятый предмет |
Координаты — метры в локальной проекции вокруг центра области (x — восток, y — юг).
Ограничения MVP
- Область до 6 км². Публичные серверы Overpass рассчитаны на умеренную нагрузку; для публичной игры понадобится своё зеркало или заранее нарезанные данные (например, экстракт Geofabrik → статические файлы).
- Подвалы, мансарды, балконы, береговая линия морей пока не генерируются.
- Нестандартные контуры (сильно изломанные) дают менее аккуратные планировки.
Данные и лицензии
Данные карты © участники OpenStreetMap, лицензия ODbL. Если вы распространяете сгенерированные миры, укажите «© OpenStreetMap contributors». Тайлы на экране выбора области — стандартные тайлы OSM по их правилам использования; поиск — Nominatim (не чаще раза в секунду).
Идеи частично подсказаны проектом KnoxMap; код написан с нуля.