Files
citygen/README.md
T

110 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Город сверху — генератор карты по OpenStreetMap (MVP)
Выделяете на карте небольшой город или район → по данным OSM строится подробная карта
с видом строго сверху: дороги реальной ширины с тротуарами и разметкой, парковки
с машинами, деревья, и **у каждого здания — этажи, комнаты, двери, окна, лестницы
и мебель**, нарисованные простыми геометрическими фигурами, как на плане квартиры.
Всё работает в браузере, без сервера: данные берутся из Overpass API, генерация
идёт в Web Worker'ах, готовый мир сохраняется в IndexedDB.
Машины появляются только на парковках и в гаражах; вдоль улиц они не генерируются.
## Запуск
Нужен Node.js 18+.
```bash
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 года).
Генерация из файла без браузера (для отладки генератора):
```bash
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
- Область до 25 км²; предупреждение о времени генерации — свыше 10 км².
Скорость и расход памяти зависят от плотности застройки и этажности.
Публичные серверы Overpass рассчитаны на умеренную нагрузку; для
публичной игры понадобится своё зеркало или заранее нарезанные данные (например, экстракт
Geofabrik → статические файлы).
- Подвалы, мансарды, балконы, береговая линия морей пока не генерируются.
- Нестандартные контуры (сильно изломанные) дают менее аккуратные планировки.
## Данные и лицензии
Данные карты © участники OpenStreetMap, лицензия ODbL. Если вы распространяете
сгенерированные миры, укажите «© OpenStreetMap contributors». Тайлы на экране выбора
области — стандартные тайлы OSM по их [правилам использования](https://operations.osmfoundation.org/policies/tiles/);
поиск — Nominatim (не чаще раза в секунду).
Идеи частично подсказаны проектом [KnoxMap](https://github.com/spytheeuclidean-a11y/knoxmap);
код написан с нуля.