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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Adds a second building-height source: Mapbox building data, cross-checked against our OSM-derived heights.
New tool —
Geo/tools/mapbox_buildings.pymapbox-streets-v8/ layerbuildingat every building centroid in the OSM extract and merges the returnedheight/min_height/typewith our height and its source (tag > levels > guess, reusingblock_height_report.classify_height).match(±0.5 m),close(±2 m),disagree(>2 m),oursonly,mapboxonly,non-building; sorted worst-first; optional--only-diffsand--json.urllibonly; one request per building with--delayand 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)
0.1.2finding: Mapbox independently classifies our roof/canopy/shelter volumes asroof,canopyorshelter.building=yes/apartmentsstructures rendering at our 2-level guess (6.4 m) vs Mapbox's 3.0 m.levels × 3.2 mbuilding is ~0.6 m taller per 6 levels than Mapbox implies → Mapbox suggests 3.1 m per level. Recorded inTODO.md/MEMORY.md, deliberately not applied — a storey height change should come from the photographs.Also:
classify_height()now treatsbuilding=canopyas a non-building volume (found by this cross-check).Data handling
Mapbox terms restrict persisting/redistributing their data, so
.gitignorecoversGeo/raw/mapbox-cache/andGeo/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
compare,nearest_building,centroid_lat_lon,render_markdown(incl. "never contains a token"), token loading, and the canopy rule.Geo/README.mdinventory row;Docs/Architecture/05+architecture.mdtools 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 --checkclean;git check-ignoreconfirms the cache and report are untracked.