Planning

Central to a Surveyor's toolbox, and the most dramatic way a player can change the city — literally building it.

Design-Time Engine & Tooling Transport Buildings

Overview

The city is a continuous 3D world — no tile-based simulation grid underneath. Grids are a UI aid, drawn only in contexts where people reason spatially in units: building plots, city blocks, and the design-time surveying/road-sketching mode. They disappear in normal play.

Design-Time Surveying

Plots & Blocks

Road-bundle frontage edges are defined in Arc-Spline Transport.

Parcel Subdivision

Subdivision co-generates parcels with the road graph so every buildable lot has street access and neighboring lots do not claim the same ground. The pipeline follows Chen, Song & Ortner's co-generation idea adapted to our stack: never emit overlapping candidates and repair them afterward — if two parcels would share an interior point, the generator that produced both is wrong.

Closed blocks

When frontage edges form a closed loop, the network yields a block. The block interior subdivides along frontage (extractBlockssubdivideBlock). Each child inherits or receives a frontage edge; landlocked children are not emitted.

Open networks & junctions

Roads that do not enclose a loop subdivide road-facing: each side of a centerline gets a strip of parcels along its offset frontage (subdivideRoadFrontage). Where two or more open roads share a centerline endpoint, independently subdivided strips would leave a gap or overlap at the corner. Before ordinary frontage subdivision runs, junction closure builds that corner by construction:

  1. For each interior corner between angularly adjacent offset arms, emit a wedge parcel whose outline is the two frontage offsets plus the corner that joins them (subdivisionMode: "junction").
  2. Trim each road's ordinary frontage by the arc-length those wedges already cover (trimStart / trimEnd), so the first road-facing parcel meets the wedge at the miter rather than overlapping it.

Wedge reach is capped at the ray-intersection (miter) distance between the two frontage lines (and further by half a typical frontage width at the call site). A fixed reach past the miter produces a self-intersecting bowtie.

Mid-span crossings (a stem meeting a through road's interior, or two through centerlines crossing away from shared endpoints) are the same algorithm with a different junction detector. Until that detector exists, pairs that are not closed by construction use a conservative drop-both safety net based on real polygon intersection — not a centroid-in-polygon heuristic, which misses long thin road-facing overlaps whose centroids lie outside each other.

Invariants

Data Model

Entity Fields
Block boundary polyline, frontage edges[]
Parcel polygon, basePolygon (immutable raw lot boundary), blockId, frontageEdgeId, zoneType, density, frontSetback, sideSetback, rearSetback, maxLotCoverage, parkingMinimum, subdivisionMode ("road-facing" | "block-based" | "junction")
Plat id, status, roadIds, blocks, parcels, zoneIntent, gridCell (world-space alignment, default 10m), footprintGridCell (model-space construction snapping, default 50cm)

Every parcel must have street frontage to be buildable and valuable. Landlocked parcels (no street access) are legally and economically unusable. Therefore, frontageEdgeId must never be null or undefined.

Parcel Constraints & Construction Grid

The dedicated Parcels surveyor tool allows players to inspect and customize individual platted lots without affecting the surrounding road network or triggering zoning actions.

Saved Plans

A plan is a named, saved set of sketched transport networks — a snapshot the player can restore into the current sketch rather than a submitted plat. Distinct from a plat (the block/parcel/zoning document a Surveyor session submits): a plan only holds the transport-line sketches used to refit those curves later.

Entity Fields
Plan id, name, createdAt, transportNetworks (map of transport type → TransportNetwork[])
TransportNetwork id, polyline (raw sketched centerline), roadClass, speedLimit, evenLanes, oddLanes, grades (terrain-aware evaluation), terrainSnapshot (baseline heightmap state)
Transport Type road, rail

Terrain Integration

Survey mode integrates with the terrain system to provide visual and cost-based feedback:

Undo/Redo in Survey Mode

Full undo/redo stack using Memento pattern (immutable snapshots + caretaker history):

Future Work