Skip to content

feat(tiles): serve facade_scan and the incident layers from Martin - #73

Merged
yorickdewid merged 1 commit into
mainfrom
feat/incident-facade-tiles-martin
Aug 6, 2026
Merged

feat(tiles): serve facade_scan and the incident layers from Martin#73
yorickdewid merged 1 commit into
mainfrom
feat/incident-facade-tiles-martin

Conversation

@yorickdewid

Copy link
Copy Markdown
Contributor

Moves the last five tilesets off tippecanoe and onto the Martin tileserver.

Why

Tileset Features Nightly tile build Spaces objects
incident_district 1,016 26.5 min 155,335
incident_neighborhood 1,530 11.5 min 67,346
incident 2,728 2.0 min 7,373
facade_scan 3,202 1.0 min 1,090
incident_municipality 298 0.5 min 497

~40 of the ~50 minutes process_mapset spends every night, and 231,641 Spaces objects, to render 8,774 features. incident_district alone spends 26.5 minutes uploading 155k tile files for 1,016 polygons — the upload dominates, not the tiling. Nightly flow should go from ~101 min to ~60 min.

What

Two SQL files following the create_building_cluster_tiles.sql pattern: flat table in 3857 + GiST index, refresh_* procedure (TRUNCATE + INSERT), (z,x,y) function source Martin auto-publishes from maplayer, TileJSON COMMENT (with the mandatory fields map), and grants.

MVT layer names match the retired tileset names, so no layer config changes anywhere — every WebFront config already uses source == source-layer == tileset name, and the Report incident chapter is the same.

Zoom ranges come from maplayer.bundle: incident 12–16, district/neighborhood 10–16, municipality 7–11.

The views are not dropped

maplayer.facade_scan and the four incident views still feed the nightly GPKG export to s3://fundermaps-data/mapset/, which is the permanent static-model history. The refresh procedures repeat the views' joins rather than selecting from them, so the archived GPKG schema cannot drift as the tile attribute set evolves.

Geofence — please read

The four incident sources now emit neighborhood_id / district_id / municipality_id, which the static tiles never carried.

WebFront's geofence builds any(match(<id>, fence), !has(<id>)) — a feature missing the id is shown. Schiedam publiek is a public mapset fenced to GM0606 client-side (store/mapsets.ts) that includes the incident layer, so today it renders all 2,728 Dutch incidents instead of Schiedam's 216. Emitting the ids makes the existing fence actually bite.

Same failure mode as the z12–13 slimming fixed in #52. This is the one behaviour change in the PR — if you'd rather keep exact parity for now, drop the three id columns from the ST_AsMVT select in maplayer.incident() and nothing else changes.

Notes

  • Aggregation polygons are detailed (860k vertices over 1,016 districts) and are drawn at zooms where that detail is sub-pixel, so they carry a geom_simple variant for z<12 — with separate query branches, because a CASE over two geometry columns in WHERE is not indexable.
  • facade_scan and incident get no simplified variant on purpose: the whole of each is smaller than a single dense building_tiles z12 tile.
  • Enum columns stored as text (ST_AsMVT emits the label either way, and it keeps these tables independent of enum DDL).
  • Windmill: new f/fundermaps/data/refresh_layer_tiles script created, to be wired as step v after u in refresh_data_model.

Cutover order

  1. Apply both SQL files to prod, restart Martin, verify the catalog + tile parity.
  2. Wire the Windmill step.
  3. Merge + deploy the WebFront and Report PRs.
  4. Only then set generate_tileset=false on the five bundle rows — enabled stays true and upload_dataset stays true, so the nightly GPKG exports keep feeding the archive.
  5. Purge the Spaces prefixes last, once the frontends are confirmed live.

🤖 Generated with Claude Code

Adds flat tile tables + (z,x,y) function sources for the last five
tilesets still built by tippecanoe every night:

  incident_district      1,016 features   26.5 min/night   155,335 objects
  incident_neighborhood  1,530 features   11.5 min/night    67,346 objects
  incident               2,728 features    2.0 min/night     7,373 objects
  facade_scan            3,202 features    1.0 min/night     1,090 objects
  incident_municipality    298 features    0.5 min/night       497 objects

That is ~40 of the ~50 minutes process_mapset spends nightly, and 231,641
Spaces objects, to render 8,774 features. incident_district alone spent
26.5 minutes uploading 155k tile files for 1,016 polygons.

MVT layer names match the retired tileset names, so every WebFront layer
config (source == source-layer == tileset name) and the Report incident
chapter keep working with no config change.

The maplayer.* views stay: they feed the nightly GPKG export to
s3://fundermaps-data/mapset/, which is the permanent static-model history.
The refresh procedures repeat the views' joins instead of selecting from
them so the archived GPKG schema does not drift.

Emits the CBS ids (neighborhood/district/municipality) on all four
incident sources. WebFront's geofence is any(match(id, fence), !has(id)),
so a feature missing the id is SHOWN — and 'Schiedam publiek' is a public
mapset fenced to GM0606 that includes the incident layer, so it currently
renders all 2,728 Dutch incidents instead of Schiedam's 216. Same failure
mode as the z12-13 slimming fixed in #52.

Aggregation layers carry a simplified geometry variant for z<12 (860k
vertices over 1,016 districts, drawn where that detail is sub-pixel), with
separate indexable query branches rather than a CASE in WHERE.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants