Shared contours layer — fold is_haedarlinur in (#151) #198

Merged
art-bot merged 2 commits from issue-151-shared-contours into main 2026-08-20 21:23:02 +00:00
Owner

Closes #151


Shared contours layer — fold is_haedarlinur in (se #101 / pl #104 / fi #107 land into it)

What changed

Made contours a shared layer (issue #151), folding Iceland's per-country
ismap_contours_<z> tables into the partitioned map_contours_<z> parent, exactly
the mechanism airports/buildings used. The style's three contour layers now read
the shared map source instead of is.

  • conf/shared/contracts/18-contours.yaml (new) — the contours contract:
    stop_z: 10, maxz: 14, simplify_line, attrs [geom, elevation, interval_class]
    — Iceland's exact values, so the fold is a clean partition move. Carries the
    cross-country acceptance tests (R119 no-empty-partition over the catalogue, R120
    no-NULL/valid elevation/interval_class).
  • conf/is/07-contours.yaml — now extends: contours; the scaffold (zoom range,
    strategy, attrs) is inherited from the contract. The zoom_filters cascade — the
    per-source thinning — stays here, because it is the source cadence. The old R119/R120
    moved to the contract; the one genuinely Iceland-specific claim (the coarse-zoom
    500 m elevation ladder at z10) is a new R31 acceptance test here.
  • conf/world.yaml — contours added to the map source's layer list, so the
    shared zxy_map function concatenates it (this is what regenerates the tile source
    the style now points at).
  • html/style.yaml — the three layers contours, contours_index,
    contour_labels switch source: is → source: map. source-layer: contours is
    unchanged (the shared layer keeps its name). The is source block is left in
    place
    — peaks still reads it; issue #152 removes it entirely once peaks goes
    shared too (noted in a comment).
  • docs — R13, the layer-inventory table, schema.md, style.md,
    country-iceland.md updated to record contours as shared; peaks is now the only
    Iceland-only layer.

Design decision — the attribute set

Kept interval_class (rather than renaming to a binary contour_index) as the
contract attribute. Reasoning, recorded in the contract comment:

  • The style's only need from a source is which lines are the index/major lines.
    The contract pins the one convention the whole map can agree on: interval_class = 1 is the index line for every source. The style's == 1 filters and labels
    key on that unchanged.
  • Iceland's cascade genuinely needs a three-rung ladder (1 = 100 m index, 4 =
    20 m, 5 = 10 m fine) — the z12 filter drops only the fine rung below z13. A binary
    index/non-index flag would collapse that and silently over-thin or over-draw the
    map.
  • So the contract carries a multi-valued integer ladder, source-agnostic by
    convention: the index line is 1, the values above are each source's intermediates.
    Sweden #101 (5 m hojdlinje, stodkurva half-interval) and Poland #104
    (poziomica) map their index markers into 1 when they land; a country that never
    draws a fine rung simply never emits it. This is the airports airport_class
    model — one shared ladder, each source maps into it.

Verification (live DB)

Reimported the layer (importer/importer import --layer contours conf/is), then
make import-world to regenerate zxy_map with contours.

  • Row counts per zoom (map_contours_<z>_is): z14 139 690, z13 139 690, z12
    138 111 (drops the 10 m fine rung), z11 24 873 (index only), z10 4 064 (500 m
    lines only) — matches the cascade and the old per-country counts exactly.
  • NULLs: 0 NULL elevation / 0 NULL interval_class at every zoom.
  • Partitions: all five map_contours_10..14_is present.
  • Decoded tile: tiles --check decodes zxy_map_contours at z10 and z14 with
    exactly the declared keys [elevation interval_class country]; the shared
    zxy_map now includes the contours blob.

make acceptance (conf/is — the config this change touches)

acceptance: layer contours (is) / R31: the z10 floor holds only 500 m index lines (Iceland's coarse cadence) — PASS (lines=4064, not_500=0)
acceptance: shared layer contours / R119: no contours partition is empty at any zoom z10–z14 — PASS (partitions=5, empty_partitions=<nil>)
acceptance: shared layer contours / R120: every country's contours carry a valid elevation and a positive interval_class — PASS (countries=1, offenders=<nil>)
acceptance: 40 test(s): 40 passed, 0 failed, 0 skipped, 0 not run

The three new tests (R31, R119, R120) fail if the data is wrong and passed here.
Full make acceptance across all configs reports 47 passed / 1 failed / 1 not run;
the single failure — layer buildings (pl) / R120 ... context deadline exceeded — is a
pre-existing, unrelated slow Poland-buildings query: reproduced identically on
main (ebdaa34) via a clean worktree, and touches nothing in this change.

Left undone / notes

  • peaks stays Iceland-only and still served by zxy_is; issue #152 retires the
    is source entirely once peaks goes shared. The is source block and the old
    ismap_contours_* tables remain (the latter are #12's orphan-cleanup work).
  • #101 / #104 / #107 land Sweden, Poland and Finland partitions into this contract
    when their data arrives; the contract comment records the mapping each will fill.
Closes #151 --- # Shared contours layer — fold is_haedarlinur in (se #101 / pl #104 / fi #107 land into it) ## What changed Made `contours` a **shared layer** (issue #151), folding Iceland's per-country `ismap_contours_<z>` tables into the partitioned `map_contours_<z>` parent, exactly the mechanism `airports`/`buildings` used. The style's three contour layers now read the shared `map` source instead of `is`. - **`conf/shared/contracts/18-contours.yaml`** (new) — the `contours` contract: `stop_z: 10`, `maxz: 14`, `simplify_line`, attrs `[geom, elevation, interval_class]` — Iceland's exact values, so the fold is a clean partition move. Carries the cross-country acceptance tests (R119 no-empty-partition over the catalogue, R120 no-NULL/valid `elevation`/`interval_class`). - **`conf/is/07-contours.yaml`** — now `extends: contours`; the scaffold (zoom range, strategy, attrs) is inherited from the contract. The `zoom_filters` cascade — the per-source thinning — stays here, because it is the source cadence. The old R119/R120 moved to the contract; the one genuinely Iceland-specific claim (the coarse-zoom **500 m elevation ladder** at z10) is a new R31 acceptance test here. - **`conf/world.yaml`** — `contours` added to the `map` source's layer list, so the shared `zxy_map` function concatenates it (this is what regenerates the tile source the style now points at). - **`html/style.yaml`** — the three layers `contours`, `contours_index`, `contour_labels` switch `source: is` → `source: map`. `source-layer: contours` is unchanged (the shared layer keeps its name). The `is` source block is **left in place** — `peaks` still reads it; issue #152 removes it entirely once peaks goes shared too (noted in a comment). - **docs** — R13, the layer-inventory table, `schema.md`, `style.md`, `country-iceland.md` updated to record contours as shared; `peaks` is now the only Iceland-only layer. ### Design decision — the attribute set Kept `interval_class` (rather than renaming to a binary `contour_index`) as the contract attribute. Reasoning, recorded in the contract comment: - The style's only need from a source is **which lines are the index/major lines**. The contract pins the one convention the whole map can agree on: **`interval_class = 1` is the index line for every source**. The style's `== 1` filters and labels key on that unchanged. - Iceland's cascade genuinely needs a **three-rung ladder** (1 = 100 m index, 4 = 20 m, 5 = 10 m fine) — the z12 filter drops only the fine rung below z13. A binary index/non-index flag would collapse that and silently over-thin or over-draw the map. - So the contract carries a multi-valued integer ladder, source-agnostic by convention: the index line is `1`, the values above are each source's intermediates. Sweden #101 (5 m `hojdlinje`, `stodkurva` half-interval) and Poland #104 (`poziomica`) map their index markers into `1` when they land; a country that never draws a fine rung simply never emits it. This is the airports `airport_class` model — one shared ladder, each source maps into it. ## Verification (live DB) Reimported the layer (`importer/importer import --layer contours conf/is`), then `make import-world` to regenerate `zxy_map` with contours. - **Row counts per zoom** (`map_contours_<z>_is`): z14 139 690, z13 139 690, z12 138 111 (drops the 10 m fine rung), z11 24 873 (index only), z10 4 064 (500 m lines only) — matches the cascade and the old per-country counts exactly. - **NULLs**: 0 NULL `elevation` / 0 NULL `interval_class` at every zoom. - **Partitions**: all five `map_contours_10..14_is` present. - **Decoded tile**: `tiles --check` decodes `zxy_map_contours` at z10 and z14 with exactly the declared keys `[elevation interval_class country]`; the shared `zxy_map` now includes the contours blob. ### `make acceptance` (conf/is — the config this change touches) ``` acceptance: layer contours (is) / R31: the z10 floor holds only 500 m index lines (Iceland's coarse cadence) — PASS (lines=4064, not_500=0) acceptance: shared layer contours / R119: no contours partition is empty at any zoom z10–z14 — PASS (partitions=5, empty_partitions=<nil>) acceptance: shared layer contours / R120: every country's contours carry a valid elevation and a positive interval_class — PASS (countries=1, offenders=<nil>) acceptance: 40 test(s): 40 passed, 0 failed, 0 skipped, 0 not run ``` The three new tests (R31, R119, R120) fail if the data is wrong and passed here. Full `make acceptance` across all configs reports **47 passed / 1 failed / 1 not run**; the single failure — `layer buildings (pl) / R120 ... context deadline exceeded` — is a **pre-existing, unrelated** slow Poland-buildings query: reproduced identically on main (`ebdaa34`) via a clean worktree, and touches nothing in this change. ## Left undone / notes - `peaks` stays Iceland-only and still served by `zxy_is`; issue #152 retires the `is` source entirely once peaks goes shared. The `is` source block and the old `ismap_contours_*` tables remain (the latter are #12's orphan-cleanup work). - #101 / #104 / #107 land Sweden, Poland and Finland partitions into this contract when their data arrives; the contract comment records the mapping each will fill.
Iceland's contours were the last terrain layer still per-country: conf/is/07-contours.yaml
built ismap_contours_<z> and the style read them via the `is` source. This lands the
shared-contours contract and folds Iceland into it, the same mechanism airports (#149) and
buildings (#150) used.

- conf/shared/contracts/18-contours.yaml (new): the `contours` contract — stop_z 10,
  maxz 14, simplify_line, attrs [geom, elevation, interval_class] — with the
  cross-country acceptance tests (R119 no-empty-partition over the catalogue, R120
  valid elevation / positive interval_class). The attribute set stays source-agnostic
  by convention rather than rename: `interval_class = 1` is the index/major line for
  every source (what the style's `== 1` filters and labels key on), the values above
  are each source's intermediates. A binary index flag would collapse Iceland's
  three-rung cascade (the z12 filter drops only the fine 10 m rung below z13), so the
  contract carries a multi-valued ladder. #101/#104/#107 map their index markers into
  1 when they land.
- conf/is/07-contours.yaml: extends: contours; scaffold inherited, zoom_filters stay
  (the per-source thinning). R119/R120 moved to the contract; a new R31 test holds
  Iceland's 500 m elevation ladder at z10.
- conf/world.yaml: contours added to the `map` source layer list so zxy_map serves it.
- html/style.yaml: the three contour layers switch source is -> map; `is` survives for
  peaks (#152 removes it entirely).
- docs updated (R13, layer inventory, schema, style, country-iceland): peaks is now the
  only Iceland-only layer.

Verified live: reimported the layer and regenerated zxy_map. Row counts per zoom match
the cascade exactly (139690/139690/138111/24873/4064), zero NULL elevation or
interval_class, all five partitions present, tiles --check decodes zxy_map_contours
with keys [elevation interval_class country]. conf/is acceptance: 40/40 passed
including the new R31/R119/R120. (The pl buildings R120 10s-timeout failure is
pre-existing on main and unrelated.)
The fold left `contours` in conf/is/downloads.yaml's `is` source layer list. A
shared layer resolves to the one zxy_map_contours (importer/source.go layerFunc),
so zxy_is would have concatenated a second, unread copy of contours into every
Iceland tile — the style reads them from `map` now. Every earlier fold took the
layer off this list for exactly that reason (cover, roads, settlements, airports,
buildings); contours does too, and the comment records it with the rest.

Verified on the live DB: zxy_is regenerated to `SELECT zxy_ismap_peaks(...)`, and
at 12/1831/1079 over Iceland zxy_map is 3125 B of which zxy_map_contours is 1903,
while zxy_is is down to 127 B of peaks. `tiles --check` decodes contours from
zxy_map_contours at z10 and z14 with keys [elevation interval_class country].
`importer acceptance conf/is` is 40/40, including the three new tests (R31 z10
floor 4064 lines / not_500=0; contract R119 partitions=5; R120 countries=1).

Docs and comments that named contours as Iceland-only: geo-primer's two-sources
passage (the interleaving example was contours-on-`is`), unification.md's "is …
holding contours and peaks", naming.md's per-country table example, mapsrv.yaml
and shared/acceptance.yaml's layer lists, and the peaks R119 comment that pointed
at contours for the pattern. Two typos in the new contract ("KEpt", "countour's").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2QYwuohkM9vWJs6uzsK58
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
art/ismap!198
No description provided.