terrain-urban-diffusion v5
Five conditional denoising diffusion "experts" that generate street-level urban growth proposals (roads, continuous built-up density, and proposed amenity locations) for real settlements, conditioned on terrain and the existing footprint. Each expert covers one contemporary growth regime, and a hard router selects the expert for a given map window from interpretable conditioning statistics.
Companion to the paper From Growth Model to Planning Assistant: Terrain-Conditioned Diffusion with Auditable Language Operations and Jurisdictional Rule Packs. A preprint is available on SSRN (abstract 7089538, posted July 2026); the same manuscript is under review at Environment and Planning B: Urban Analytics and City Science (manuscript ID EPB-2026-0743). The paper PDF is also included in this repo as paper.pdf.
- Preprint (SSRN): https://papers.ssrn.com/abstract=7089538
- Code, full planning-task layer, and browser demo: https://github.com/eshankiyer/terrain-urban-diffusion
- Live demo: https://eshankiyer.github.io/terrain-urban-diffusion
The five experts and the router
There is one expert per growth regime:
| Expert file | Regime |
|---|---|
model_village.onnx |
Village |
model_town.onnx |
Hilly town |
model_urban.onnx |
Planned fringe |
model_informal.onnx |
Informal peri-urban frontier |
model_megacity.onnx |
Megacity edge |
A hard router picks the expert for each window from four interpretable conditioning statistics: slope, built fraction, road fraction, and the roads-per-built ratio. The routing rule and its fallback chains live in src/moe.py in the code repository, so expert selection is auditable rather than learned end-to-end.
Repository contents
| File | What it is |
|---|---|
model_village.onnx, model_town.onnx, model_urban.onnx, model_informal.onnx, model_megacity.onnx |
The five diffusion experts, ~23 MB each |
zone_clf.json |
Gradient-boosted zoning classifier, exported as plain JSON trees for in-browser evaluation |
bike_clf.json |
Logistic bike-infrastructure classifier (intercept + 4 coefficients) |
paper.pdf |
The accompanying paper |
Model architecture
Each expert is an ONNX export of a conditional U-Net with roughly 13M parameters, operating on 128x128 rasters at 15 m/px. The five conditioning channels are:
- Elevation z-score
- Slope / 30
- Built density
- Roads
- Water
Sampling uses DDIM with 50 steps.
Usage
The experts are standard ONNX graphs, so any ONNX Runtime binding works. Because the exact input and output node names depend on the export, inspect them at load time rather than hardcoding:
import numpy as np
import onnxruntime as ort
sess = ort.InferenceSession("model_village.onnx", providers=["CPUExecutionProvider"])
# Inspect the signature so you feed the right tensors
for i in sess.get_inputs():
print("input:", i.name, i.shape, i.type)
for o in sess.get_outputs():
print("output:", o.name, o.shape, o.type)
# A conditional diffusion U-Net expects a noisy latent, a timestep, and the
# 5-channel conditioning stack (elevation z-score, slope/30, built, roads, water),
# all as 128x128 rasters. Map the names printed above to these tensors, then run
# the DDIM loop (50 steps) yourself. The reference sampler is in the code repo.
For the full pipeline (routing across experts, DDIM sampling, and the planning-task layer described below) use the code repository rather than calling a single expert in isolation.
Choosing an expert
If you only need one window, route manually: compute slope, built fraction, road fraction, and roads-per-built ratio for the window and follow the rule in src/moe.py. If you are processing a whole region, let the router in the code repo assign experts per tile.
Training data and procedure
Training targets are observed 1980-2020 change, assembled automatically with no manual annotation from:
- The multi-epoch GHS-BUILT-S built-up surface (change over time)
- OpenStreetMap (roads and amenities)
- Open elevation tiles (terrain and slope)
Each expert was trained for 300 epochs on a single T4 GPU. Final noise-prediction losses:
| Expert | Loss |
|---|---|
| Village | 0.024 |
| Town | 0.028 |
| Urban | 0.032 |
| Informal | 0.038 |
| Megacity | 0.042 |
Evaluation
The zoning classifier (zone_clf.json) reaches leave-one-town-out macro-F1 of 0.257 across five morphology families and is set to abstain rather than guess, so its output should be read as advisory typing, not ground truth.
Planning-task layer
Beyond raw generation, the code repository wraps the experts in an auditable planning workflow: zoning annotation, demand forecasting, compliance checks against rule packs extracted from planning documents, public-comment synthesis, and staff-report drafting. Those "auditable language operations and jurisdictional rule packs" are the subject of the paper.
Intended use
Decision support and exploration. Outputs are candidate growth proposals meant to help planners and researchers reason about where and how a settlement might grow. They are not plans and not legal determinations.
Limitations and biases
- Historical patterns are baked in. The experts learn from observed 1980-2020 growth, so they reproduce the development patterns of that period, including sprawl and inequitable or informal growth. Generated proposals are descriptions of likely growth under past dynamics, not normative recommendations.
- The road channel is weaker. It does not reach the spatial coherence of the density channel and is hidden in the demo. Do not rely on generated road geometry.
- The zoning classifier is advisory. Macro-F1 of 0.257 is far from reliable typing; it abstains when unsure and should be treated as a hint.
- Geographic coverage is uneven. Training depends on where GHS-BUILT-S, OSM, and open elevation tiles have good coverage, so quality varies by region.
- Read the limitations section of the paper before relying on any output.
Citation
Available as an SSRN preprint (abstract 7089538); the same manuscript is under review at Environment and Planning B. Update with the published reference once available.
@misc{iyer2026terrainurban,
title = {From Growth Model to Planning Assistant: Terrain-Conditioned Diffusion
with Auditable Language Operations and Jurisdictional Rule Packs},
author = {Iyer, Eshan},
year = {2026},
howpublished = {SSRN preprint},
url = {https://papers.ssrn.com/abstract=7089538},
note = {SSRN abstract 7089538; manuscript under review at Environment and
Planning B: Urban Analytics and City Science (EPB-2026-0743)}
}
License
MIT.