Initial commit: browser OSM city generator
This commit is contained in:
commit
2d4bad0dc7
32 files changed
+5915
No files matched your search
+197
@@ -0,0 +1,197 @@
|
||||
// Модель мира. Все координаты в метрах в локальной проекции мира:
|
||||
// x — на восток, y — на юг (как на экране). Углы в радианах.
|
||||
// Модель с самого начала рассчитана на будущую симуляцию: у всего есть id,
|
||||
// двери и лестницы — это связи между комнатами (граф навигации),
|
||||
// у объектов есть флаги «блокирует проход / блокирует обзор».
|
||||
|
||||
export type Vec = [number, number];
|
||||
export type Ring = Vec[];
|
||||
|
||||
export interface World {
|
||||
version: 1;
|
||||
id: string;
|
||||
name: string;
|
||||
createdAt: string;
|
||||
seed: number;
|
||||
/** Центр проекции и исходная область в градусах [south, west, north, east]. */
|
||||
origin: { lat: number; lon: number };
|
||||
bbox: [number, number, number, number];
|
||||
/** Границы области в метрах. */
|
||||
bounds: { minX: number; minY: number; maxX: number; maxY: number };
|
||||
areas: Area[];
|
||||
roads: Road[];
|
||||
buildings: Building[];
|
||||
/** Уличные объекты: деревья, машины, скамейки, фонари. */
|
||||
props: Prop[];
|
||||
/** Библиотека общих моделей предметов: prop.model → набор фигур. */
|
||||
models: Record<string, Shape[]>;
|
||||
attribution: string;
|
||||
}
|
||||
|
||||
export type AreaKind =
|
||||
| 'residential' | 'commercial' | 'industrial' | 'retail' | 'farmland' | 'farmyard'
|
||||
| 'grass' | 'park' | 'forest' | 'scrub' | 'meadow' | 'orchard' | 'vineyard'
|
||||
| 'water' | 'wetland' | 'beach' | 'sand' | 'parking' | 'pitch' | 'playground'
|
||||
| 'cemetery' | 'construction' | 'railway' | 'school' | 'hospital' | 'pedestrian' | 'garden';
|
||||
|
||||
export interface Area {
|
||||
id: string;
|
||||
kind: AreaKind;
|
||||
/** Первое кольцо — внешнее, остальные — дыры. */
|
||||
rings: Ring[];
|
||||
osmId?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export type RoadKind =
|
||||
| 'motorway' | 'trunk' | 'primary' | 'secondary' | 'tertiary' | 'residential'
|
||||
| 'unclassified' | 'service' | 'living_street' | 'pedestrian' | 'track'
|
||||
| 'footway' | 'cycleway' | 'path' | 'steps' | 'rail' | 'tram' | 'river' | 'stream' | 'canal' | 'ditch';
|
||||
|
||||
export interface Road {
|
||||
id: string;
|
||||
kind: RoadKind;
|
||||
pts: Vec[];
|
||||
/** Ширина проезжей части (или русла) в метрах. */
|
||||
width: number;
|
||||
/** Ширина тротуара с каждой стороны, 0 — нет. */
|
||||
sidewalk: number;
|
||||
lanes: number;
|
||||
oneway: boolean;
|
||||
layer: number;
|
||||
bridge: boolean;
|
||||
tunnel: boolean;
|
||||
name?: string;
|
||||
osmId?: string;
|
||||
}
|
||||
|
||||
export type BuildingKind =
|
||||
| 'house' | 'apartments' | 'mixed' | 'retail' | 'restaurant' | 'office' | 'industrial'
|
||||
| 'warehouse' | 'school' | 'hospital' | 'hotel' | 'church' | 'civic' | 'garage' | 'shed' | 'farm';
|
||||
|
||||
export interface Building {
|
||||
id: string;
|
||||
osmId?: string;
|
||||
kind: BuildingKind;
|
||||
/** Подтип из OSM-тегов/POI: 'supermarket', 'bakery', 'pharmacy'… */
|
||||
use?: string;
|
||||
name?: string;
|
||||
address?: string;
|
||||
footprint: Ring;
|
||||
/** Внутренние дворы (дыры в контуре). */
|
||||
holes: Ring[];
|
||||
/** Площадь контура, м². */
|
||||
area: number;
|
||||
levels: number;
|
||||
/** Откуда взялась этажность: 'osm' | 'height' | 'estimate'. */
|
||||
levelsSource: 'osm' | 'height' | 'estimate';
|
||||
/** Локальная система здания: поворот сетки планировки. */
|
||||
frame: { origin: Vec; angle: number };
|
||||
floors: Floor[];
|
||||
/** Помещения-юниты: квартиры, магазины, офисы — будущие «домохозяйства» и «рабочие места». */
|
||||
units: Unit[];
|
||||
/** Сколько спальных мест (оценка жильцов). */
|
||||
beds: number;
|
||||
seed: number;
|
||||
}
|
||||
|
||||
export interface Unit {
|
||||
id: string;
|
||||
kind: 'home' | 'shop' | 'office' | 'service' | 'common';
|
||||
level: number;
|
||||
roomIds: string[];
|
||||
beds: number;
|
||||
}
|
||||
|
||||
export type RoomKind =
|
||||
| 'hall' | 'landing' | 'living' | 'kitchen' | 'bedroom' | 'bath' | 'wc' | 'storage' | 'corridor'
|
||||
| 'stairs' | 'lift' | 'lobby' | 'sales' | 'backroom' | 'office' | 'openoffice' | 'meeting'
|
||||
| 'dining' | 'prokitchen' | 'workshop' | 'hall_ind' | 'classroom' | 'staff' | 'ward'
|
||||
| 'guestroom' | 'nave' | 'garage' | 'utility' | 'void';
|
||||
|
||||
export interface Room {
|
||||
id: string;
|
||||
kind: RoomKind;
|
||||
/** Контур комнаты (может быть несколько колец; дыры — по чётности). Рисовать с клипом по контуру здания. */
|
||||
rings: Ring[];
|
||||
area: number;
|
||||
labelPos: Vec;
|
||||
unitId?: string;
|
||||
}
|
||||
|
||||
export interface Wall {
|
||||
a: Vec;
|
||||
b: Vec;
|
||||
thickness: number;
|
||||
exterior: boolean;
|
||||
}
|
||||
|
||||
export interface Door {
|
||||
id: string;
|
||||
a: Vec;
|
||||
b: Vec;
|
||||
/** Комнаты по обе стороны; 'outside' — улица. Это ребро графа навигации. */
|
||||
rooms: [string, string];
|
||||
/** 'opening' — проём без полотна (арка, выход на лестницу). */
|
||||
kind: 'interior' | 'entrance' | 'unit' | 'garage' | 'opening';
|
||||
/** Сторона, куда открывается полотно (точка внутри комнаты). */
|
||||
swingTo: Vec;
|
||||
}
|
||||
|
||||
export interface Window {
|
||||
a: Vec;
|
||||
b: Vec;
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
export interface Stairs {
|
||||
id: string;
|
||||
rings: Ring[];
|
||||
/** Ось марша: от низа к верху. */
|
||||
from: Vec;
|
||||
to: Vec;
|
||||
width: number;
|
||||
up: boolean;
|
||||
down: boolean;
|
||||
lift?: boolean;
|
||||
/** id комнаты-лестничной клетки на этом этаже. */
|
||||
roomId: string;
|
||||
}
|
||||
|
||||
export interface Floor {
|
||||
level: number;
|
||||
rooms: Room[];
|
||||
walls: Wall[];
|
||||
doors: Door[];
|
||||
windows: Window[];
|
||||
stairs: Stairs[];
|
||||
props: Prop[];
|
||||
}
|
||||
|
||||
/** Примитив в локальных координатах предмета (центр предмета в 0,0; «спинка» к стене при y<0). */
|
||||
export type Shape =
|
||||
| { t: 'rect'; x: number; y: number; w: number; h: number; r?: number; s?: ShapeStyle }
|
||||
| { t: 'circle'; x: number; y: number; r: number; s?: ShapeStyle }
|
||||
| { t: 'line'; x1: number; y1: number; x2: number; y2: number; s?: ShapeStyle };
|
||||
|
||||
/** Стиль: 'base' — основной предмет, 'soft' — ткань/подушка, 'dark' — техника/акцент, 'green' — растение, 'glass', 'metal'. */
|
||||
export type ShapeStyle = 'base' | 'soft' | 'dark' | 'green' | 'glass' | 'metal' | 'wood' | 'water' | 'line' | 'car' | 'fabric' | 'accent';
|
||||
|
||||
export interface Prop {
|
||||
id: string;
|
||||
kind: string;
|
||||
pos: Vec;
|
||||
rot: number;
|
||||
w: number;
|
||||
d: number;
|
||||
/** Фигуры предмета; после сборки мира обычно вынесены в world.models (см. model). */
|
||||
shapes?: Shape[];
|
||||
model?: string;
|
||||
blocksMove: boolean;
|
||||
blocksSight: boolean;
|
||||
roomId?: string;
|
||||
/** Цвет для машин и т.п. (иначе по стилю). */
|
||||
color?: string;
|
||||
/** Для симуляции: можно сидеть/спать/хранить и т.п. */
|
||||
tags?: string[];
|
||||
}
|
||||
Reference in new issue
Block a user