feat(geo): cross-check block heights against Mapbox building data #25

Merged
zwitschi merged 1 commits from mapbox-buildings-0.1.2 into main 2026-11-08 16:31:39 +01:00
Owner

Summary

Adds a second building-height source: Mapbox building data, cross-checked against our OSM-derived heights.

New tool — Geo/tools/mapbox_buildings.py

  • Tilequeries mapbox-streets-v8 / layer building at every building centroid in the OSM extract and merges the returned height / min_height / type with our height and its source (tag > levels > guess, reusing block_height_report.classify_height).
  • Verdicts: match (±0.5 m), close (±2 m), disagree (>2 m), oursonly, mapboxonly, non-building; sorted worst-first; optional --only-diffs and --json.
  • Stdlib urllib only; one request per building with --delay and HTTP 429/5xx back-off; responses cached so re-runs are free and deterministic.

What the first run found (72 buildings: 58 match, 5 close, 3 disagree, 6 non-building)

  • Corroborates the 0.1.2 finding: Mapbox independently classifies our roof/canopy/shelter volumes as roof, canopy or shelter.
  • 3 disagreements: rear building=yes/apartments structures rendering at our 2-level guess (6.4 m) vs Mapbox's 3.0 m.
  • Every levels × 3.2 m building is ~0.6 m taller per 6 levels than Mapbox implies → Mapbox suggests 3.1 m per level. Recorded in TODO.md/MEMORY.md, deliberately not applied — a storey height change should come from the photographs.

Also: classify_height() now treats building=canopy as a non-building volume (found by this cross-check).

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 (from the ignored .env) is never written to cache, report or JSON.

Tests and docs

  • 17 new tests (29 total) covering compare, nearest_building, centroid_lat_lon, render_markdown (incl. "never contains a token"), token loading, and the canopy rule.
  • Geo/README.md inventory row; Docs/Architecture/05 + architecture.md tools table updated (per the new architecture-upkeep rule).

Verification: python3 -m unittest discover -s Tools/tests -t Tools -p 'test_*.py' → 29 tests OK; prettier --check clean; git check-ignore confirms the cache and report are untracked.

## Summary Adds a second building-height source: **Mapbox** building data, cross-checked against our OSM-derived heights. ### New tool — `Geo/tools/mapbox_buildings.py` - Tilequeries `mapbox-streets-v8` / layer `building` at **every building centroid** in the OSM extract and merges the returned `height` / `min_height` / `type` with our height **and its source** (tag > levels > guess, reusing `block_height_report.classify_height`). - Verdicts: `match` (±0.5 m), `close` (±2 m), `disagree` (>2 m), `oursonly`, `mapboxonly`, `non-building`; sorted worst-first; optional `--only-diffs` and `--json`. - Stdlib `urllib` only; one request per building with `--delay` and HTTP 429/5xx back-off; responses cached so re-runs are free and deterministic. ### What the first run found (72 buildings: 58 match, 5 close, 3 disagree, 6 non-building) - **Corroborates the `0.1.2` finding**: Mapbox independently classifies our roof/canopy/shelter volumes as `roof`, `canopy` or `shelter`. - **3 disagreements**: rear `building=yes`/`apartments` structures rendering at our 2-level guess (6.4 m) vs Mapbox's 3.0 m. - **Every `levels × 3.2 m` building is ~0.6 m taller per 6 levels than Mapbox implies** → Mapbox suggests **3.1 m per level**. Recorded in `TODO.md`/`MEMORY.md`, deliberately **not** applied — a storey height change should come from the photographs. Also: `classify_height()` now treats `building=canopy` as a non-building volume (found by this cross-check). ### 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 (from the ignored `.env`) is never written to cache, report or JSON. ### Tests and docs - **17 new tests (29 total)** covering `compare`, `nearest_building`, `centroid_lat_lon`, `render_markdown` (incl. "never contains a token"), token loading, and the canopy rule. - `Geo/README.md` inventory row; `Docs/Architecture/05` + `architecture.md` tools table updated (per the new architecture-upkeep rule). Verification: `python3 -m unittest discover -s Tools/tests -t Tools -p 'test_*.py'` → 29 tests OK; `prettier --check` clean; `git check-ignore` confirms the cache and report are untracked.
zwitschi added 1 commit 2026-11-08 16:31:35 +01:00
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.
zwitschi merged commit 81f7cd3991 into main 2026-11-08 16:31:39 +01:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zwitschi/gig-line#25