strahler: node-less bridging polygons are dropped from the adjacency, breaking pass-through chains #70

Open
opened 2026-08-06 19:27:27 +00:00 by art-bot · 0 comments
Collaborator

Split out of the #67 review. #67 fixes the type half of the polygon-adjacency predicate (ST_Dimension >= 1); this is the other half, kept separate because it is a much larger graph change and needs a verified import per country.

What

_ww_padj in importer/strahler.go stitches adjacent bridging polygons, but only when both carry a stream node:

AND a.pid IN (SELECT pid FROM _ww_node WHERE pid > 0)
AND b.pid IN (SELECT pid FROM _ww_node WHERE pid > 0);

The comment justifies it as "a polygon with none cannot be a super-node, so stitching it is meaningless." That is the right test for a polygon at the end of a chain and the wrong one for a polygon in the middle.

In A — B — C where B carries no stream node, the rule drops both A—B and B—C, so the chain breaks and A's drainage never reaches C. Including B would work: computeStrahlerOrders materializes P<pid> super-nodes from the padj adjacency itself, not only from superOf, so a node-less polygon becomes a valid pass-through link. It cannot originate drainage — nothing roots there — but it conducts.

This is the same failure mode #62 was filed for: a chain of touching river polygons that roots nowhere.

Measurements

Adjacent polygon pairs, replicated against the live map_water_bodies_14 / map_waterways_14 (endpoint-within-30 m as the "used" test, matching the default bridge_meters; the old-rule column lands within 3% of the numbers #67 reported, which is the check that the replication is faithful):

old rule with ST_Dimension (#67) + pass-through pairs gained by pass-through
IS 434 436 657 +221
FI 7 032 7 037 20 420 +13 383
SE 22 783 22 869 49 097 +26 228

Iceland breakdown of the 657 linear adjacencies by which side carries a node:

a_used b_used pairs
t t 435
t f 130
f t 51
f f 41

The f/f pairs matter too: in A(used) — B — C — D(used) with B and C both node-less, all three links are needed.

Connectivity effect on Iceland — union-find over the two edge sets, counting only polygons that carry a node:

both-used only (current)     edges= 435  used-polys in a chain= 566  chains=135  largest=34
all linear adjacencies       edges= 657  used-polys in a chain= 603  chains=137  largest=37

37 more polygons join a chain and the longest chain grows from 34 to 37.

Why it is filed rather than folded into #67

Lifting the filter grows the adjacency by half again on Iceland and nearly triples it on Finland. That is a structural change to the drainage graph of every country that runs the stage, on top of the order-5 shifts #67 already produces (FI 479 → 3 673 by #67's own replication). It wants a real import and a rendered check per country, not a model.

That is the blocker: only Iceland's source data is present on the dev box. data/se_topo10/hydro_sverige.gpkg is absent (only kommunikation_sverige.gpkg is local) and data/fi/ is empty, so -layer waterways on conf/semap.yaml triggers a full ~11 GB Geotorget delivery and Finland needs its MTK files fetched. Whoever picks this up should run it where the data already lives, or budget the fetch.

Done when

  • The two pid IN (SELECT pid FROM _ww_node …) clauses are gone from _ww_padj.
  • IS, SE and FI are each reimported (-layer waterways) against real source data, with the per-order histogram, NULL count and per-zoom cascade recorded, and a rendered check at a chain that previously rooted nowhere.
  • docs/schema.md's "Adjacent water polygons" bullet drops the pointer to this issue.
Split out of the #67 review. #67 fixes the *type* half of the polygon-adjacency predicate (`ST_Dimension >= 1`); this is the other half, kept separate because it is a much larger graph change and needs a verified import per country. ## What `_ww_padj` in `importer/strahler.go` stitches adjacent bridging polygons, but only when **both** carry a stream node: ```sql AND a.pid IN (SELECT pid FROM _ww_node WHERE pid > 0) AND b.pid IN (SELECT pid FROM _ww_node WHERE pid > 0); ``` The comment justifies it as "a polygon with none cannot be a super-node, so stitching it is meaningless." That is the right test for a polygon at the *end* of a chain and the wrong one for a polygon in the *middle*. In A — B — C where B carries no stream node, the rule drops both A—B and B—C, so the chain breaks and A's drainage never reaches C. Including B would work: `computeStrahlerOrders` materializes `P<pid>` super-nodes from the padj adjacency itself, not only from `superOf`, so a node-less polygon becomes a valid pass-through link. It cannot originate drainage — nothing roots there — but it conducts. This is the same failure mode #62 was filed for: a chain of touching river polygons that roots nowhere. ## Measurements Adjacent polygon pairs, replicated against the live `map_water_bodies_14` / `map_waterways_14` (endpoint-within-30 m as the "used" test, matching the default `bridge_meters`; the old-rule column lands within 3% of the numbers #67 reported, which is the check that the replication is faithful): | | old rule | with `ST_Dimension` (#67) | + pass-through | pairs gained by pass-through | |---|---|---|---|---| | IS | 434 | 436 | **657** | +221 | | FI | 7 032 | 7 037 | **20 420** | +13 383 | | SE | 22 783 | 22 869 | **49 097** | +26 228 | Iceland breakdown of the 657 linear adjacencies by which side carries a node: | a_used | b_used | pairs | |---|---|---| | t | t | 435 | | t | f | 130 | | f | t | 51 | | f | f | 41 | The `f/f` pairs matter too: in A(used) — B — C — D(used) with B and C both node-less, all three links are needed. Connectivity effect on Iceland — union-find over the two edge sets, counting only polygons that carry a node: ``` both-used only (current) edges= 435 used-polys in a chain= 566 chains=135 largest=34 all linear adjacencies edges= 657 used-polys in a chain= 603 chains=137 largest=37 ``` 37 more polygons join a chain and the longest chain grows from 34 to 37. ## Why it is filed rather than folded into #67 Lifting the filter grows the adjacency by half again on Iceland and nearly triples it on Finland. That is a structural change to the drainage graph of every country that runs the stage, on top of the order-5 shifts #67 already produces (FI 479 → 3 673 by #67's own replication). It wants a real import and a rendered check per country, not a model. **That is the blocker: only Iceland's source data is present on the dev box.** `data/se_topo10/hydro_sverige.gpkg` is absent (only `kommunikation_sverige.gpkg` is local) and `data/fi/` is empty, so `-layer waterways` on `conf/semap.yaml` triggers a full ~11 GB Geotorget delivery and Finland needs its MTK files fetched. Whoever picks this up should run it where the data already lives, or budget the fetch. ## Done when - The two `pid IN (SELECT pid FROM _ww_node …)` clauses are gone from `_ww_padj`. - IS, SE and FI are each reimported (`-layer waterways`) against real source data, with the per-order histogram, NULL count and per-zoom cascade recorded, and a rendered check at a chain that previously rooted nowhere. - `docs/schema.md`'s "Adjacent water polygons" bullet drops the pointer to this issue.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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#70
No description provided.