Skip to content

feat(layers): HotSpot layer for the Risico mapset (#919) - #279

Merged
yorickdewid merged 1 commit into
mainfrom
feat/hotspot-layer
Jul 26, 2026
Merged

feat(layers): HotSpot layer for the Risico mapset (#919)#279
yorickdewid merged 1 commit into
mainfrom
feat/hotspot-layer

Conversation

@yorickdewid

Copy link
Copy Markdown
Contributor

Closes Laixer/FunderMaps#919 (frontend half).

What

A HotSpot layer in the Risico mapset: buildings whose highest risk class across the two groundwater-driven models is D or E.

MAX(drystand_risk, dewatering_depth_risk) >= 'd'

Classes order a < b < c < d < e, so "the maximum" is just the worse of the two; A/B/C are excluded. It is a fast visual answer to where do we look first, not a new model.

Note

The issue body is truncated — it cuts off mid-code-fence right after the rule (775 bytes, no comments, opened 2024-11-01). The functional spec that is there is complete enough to build against, but see the open questions below.

Why it is only a JSON file

No data work is needed. maplayer.building_tiles already carries both drystand_risk and dewatering_depth_risk, and maplayer.buildings(z,x,y) emits both at every zoom — including the slimmed z12–13 attribute subset. So the whole layer is a MapLibre filter + paint expression over the existing buildings Martin source: no new column, no tile rebuild, no change to the nightly refresh.

address_count != 0 matches the guard the other risk layers already use.

Styling

Colored by the worst of the two classes, reusing the exact D and E swatches from the existing drystand-risk / dewatering-depth-risk legends, so HotSpot reads as a summary of those two rather than as a separate scale.

worst class color
D #ffac33
E #ff5533

Verification

  • Validates clean against @maplibre/maplibre-gl-style-spec v26.
  • Compiled the filter and the color expression and evaluated all 108 combinations of (drystand, dewatering) × {null,a,b,c,d,e} × address_count {0,1,4} against the spec table — all match. The absent-attribute cases carry real weight here: 3.6M buildings have no drystand_risk at all, and MVT drops null attributes entirely rather than encoding them.

Scope today: 165,286 of 6,449,590 buildings (2.6%) qualify — 8,817 class E, 156,469 class D. Top municipalities: Rotterdam 34,746 (21%), Haarlem 12,465, Dordrecht 7,658, Leeuwarden 5,752, Deventer 5,654, Schiedam 5,550. The peat-and-pole belt, as expected.

Deploy order

Important

This PR ships first. The matching legend row is FunderMapsWorker#66 (sql/migrate/add_hotspot_layer.sql) — applying that first would put a layer id in layerSet that this repo cannot resolve, giving a dead legend entry and a console error.

Open questions for @DonZandbergen

  1. One color or two? This paints D orange and E red. The issue's table only says include/exclude, so a single flat "hotspot" color is an equally valid read — one-line change.
  2. Reliability gate? 106,683 of the 165,286 hotspots (65%) are indicative on both models; only 49,831 are established. The issue is silent on it. Painting 100k indicative buildings bright orange as "direct aandacht gewenst" is a fairly loud claim — worth deciding whether to exclude indicative or split the legend.

🤖 Generated with Claude Code

Closes #919. A HotSpot is a building whose highest risk class across the
two groundwater-driven models is D or E:

    MAX(drystand_risk, dewatering_depth_risk) >= 'd'

The classes order a < b < c < d < e, so "the maximum" is the worse of the
two; A/B/C are excluded. It answers "where do we look first" at a glance,
it is not a new model.

No data work: maplayer.building_tiles already carries both columns and
maplayer.buildings(z,x,y) emits both at every zoom (z12-13 included), so
the layer is purely a filter + paint expression over the existing
'buildings' source. address_count != 0 matches the other risk layers.

Colored by the worst of the two classes, reusing the exact D and E
swatches of the drystand-risk / dewatering-depth-risk legends so HotSpot
reads as a summary of those two rather than a separate scale.

Verified against @maplibre/maplibre-gl-style-spec, and by compiling the
filter and color expressions and evaluating all 108 combinations of
(drystand, dewatering) x {null,a..e} x address_count {0,1,4} against the
spec table. The absent-attribute cases matter: 3.6M buildings have no
drystand_risk, and MVT drops null attributes entirely.

The matching legend row lives in FunderMapsWorker
sql/migrate/add_hotspot_layer.sql and must be applied AFTER this ships -
the other order leaves a layer id in layerSet that has no config here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@yorickdewid
yorickdewid merged commit 73e4190 into main Jul 26, 2026
4 checks passed
@yorickdewid
yorickdewid deleted the feat/hotspot-layer branch July 26, 2026 21:23
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.

HotSpot kaart

1 participant