Files
gig-line/Geo
zwitschi 63aa0adf1c feat(geo): cross-check block heights against Mapbox building data
New Geo/tools/mapbox_buildings.py (stdlib urllib) Tilequeries
mapbox-streets-v8 / layer building at each building centroid and merges
height/min_height/type with our OSM height + source (tag > levels > guess,
reusing block_height_report.classify_height). Reports matches, close calls,
disagreements (sorted worst first), our-only and mapbox-only cases, and writes
optional JSON.

First run over 72 buildings: 58 match, 5 close, 3 disagree, 6 non-building.
- Mapbox independently classifies our roof/canopy/shelter volumes as roof,
  canopy or shelter -> corroborates the 0.1.2 finding.
- The 3 disagreements are rear building=yes/apartments structures rendering at
  our 2-level guess (6.4 m) vs Mapbox's 3.0 m.
- Every levels x 3.2 m building is ~0.6 m per 6 levels taller than Mapbox
  implies, i.e. Mapbox suggests 3.1 m per level. Recorded, not applied.

classify_height() now also treats building=canopy as a non-building volume
(found by this cross-check), with tests.

Data handling: Mapbox terms restrict persisting/redistributing their data, so
.gitignore covers Geo/raw/mapbox-cache/ and Geo/verification/*mapbox*; the tool
refuses to cache a response containing the token, and the token is never written
to the cache, report or JSON. Token comes from the ignored .env.

Also: 17 new tests (29 total) for the compare/nearest/centroid/render helpers
and the canopy rule; Geo/README inventory row; architecture 05 + architecture.md
tools table updated per the new upkeep rule.
2026-11-08 16:31:29 +01:00
..

Geo

Geographic sources, manifests, and the tools that turn them into Blender and Unreal content.

OSM is layout data only. It is not authoritative for façade detail, height, or pavement, and it is never sampled as a texture or panorama source.

Layout

Path Contents
Geo/raw/ Verbatim source responses and downloads, checksummed. Never edited by hand.
Geo/manifests/ One manifest per source: extract, DEM, and the local origin
Geo/verification/ Per-pass notes: address, footprints, bounds, street profile, cross-sections, elevation
Geo/tools/ Every geographic tool (Python, standard library only unless noted)

Tools that build 3D content from these sources live next to their output in Art/blender/*/ (terrain_from_dem.py, street_mesh.py, site_assembly.py, blosm_blockout.py) because they need Blender; their shared geo helpers and the unit conversion come from Geo/tools/osm_common.py.

Tools

Tool Purpose
osm_common.py Shared helpers: parse .osm, stitch and clip a street, project to UTM through PROJ, and the single metres→centimetres conversion (to_unreal_local)
block_report.py Streets, boundary intersections, and the building set for a block, split by side
block_height_report.py Every block building with its height source — tag, levels × 3.2 m, or a placeholder guess
street_profile.py Carriageway width from crossings, sidewalk offsets, per-building setbacks
street_section.py Cross-sections from the DEM: crown, gutters, kerb detection
elevation_probe.py Samples 3DEP for relief and records the baseline for the release checks
dem_stats.py Stdlib reader for the tiled GeoTIFF the 3DEP service returns; GDAL does not run on this host
asset_metadata.py Writes and audits <asset>.geo.json sidecars: position, provenance, conversion
mapbox_buildings.py Cross-checks every building's height against Mapbox mapbox-streets-v8 building data (Tilequery per centroid), merging our OSM height + source with theirs and flagging matches, close, disagreements, non-building volumes. Needs MAPBOX_ACCESS_TOKEN in .env; caches responses under Geo/raw/mapbox-cache/, and both the cache and its report are gitignored (Mapbox terms restrict redistribution)

Unit boundary

There is exactly one conversion in the repository:

WGS84 (lat, lon) → EPSG:26911 (E, N metres) → project-local metres → Unreal centimetres

Geo/tools/osm_common.py::to_unreal_local is the only place that multiplies by 100. Per-asset sidecars record the result, and asset_metadata.py audit checks each saved sidecar against that function, so a file that drifts is caught rather than trusted.

Current state

The extract, both El Capitan footprints, the demo bounds, the building sets, the street profile, cross-sections, and the 3DEP DEM window are recorded in Geo/verification/ and Geo/manifests/. The local CRS and origin are fixed in manifests/local-origin.md.

Open items live in TODO.md under Geographic data.