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.
47 lines
3.0 KiB
Markdown
47 lines
3.0 KiB
Markdown
# 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**.
|