Poland's transit will not merge: the tram network is 73% junction nodes #38

Closed
opened 2026-08-02 12:54:22 +00:00 by art-bot · 1 comment
Collaborator

merge_lines was added to transit as part of #27 and effectively did nothing for Poland.
It is applied and working — it is just finding almost nothing to merge.

z14 (source) z13 (first merged level) ratio avg length
Sweden 1 764 862 2.0x 363 m -> 742 m
Poland 8 334 7 280 1.14x 301 m -> 344 m

Poland still measures 2.1 points per feature at z9, which is the over-division signature
merge_lines exists to remove. Nothing further merges below z13 in either country (7 280 at
z13 and at z9), so this is not a "merge earlier" problem.

It is not a precision problem

The first guess — sub-metre gaps between segments, so endpoints do not coincide and
ST_LineMerge refuses — is wrong. Of Poland's 16 668 segment endpoints, 15 804 (94.8%)
exactly share a node
with another endpoint of the same mode. Only 64 have a neighbour
under 1 m away without touching, and 279 are isolated. The data is well connected.

It is node degree

ST_LineMerge chains only through nodes of degree 2. A node where three or more lines
meet ends the chain, and that is what the two networks differ in:

node degree Poland Sweden
1 858 221
2 (chainable) 1 057 (17%) 902 (56%)
3 3 854 431
4 513 47
5+ 16 4

73% of Poland's tram nodes are junctions, against 30% of Sweden's. BDOT10k SKTR models
each track separately and splits it at every crossover and switch, which is how tram track
is actually laid — so the chains break almost everywhere by construction. No amount of
merging tolerance changes that; the graph genuinely has that shape.

Worth fixing

transit is 29 203 B of the 261 622 B z9 tile over Warszawa (11%), and 19 895 B of
134 643 B at z10 (15%). For a layer that draws tram lines in a handful of cities that is a
lot.

The candidate

parallel_merge_pixels, which is what collapsed double track and yard tracks for
railways. Most of those degree-3 nodes are crossovers between the two tracks of one
line
; collapse the parallel pair and the crossovers stop being junctions, which should
convert a large share of degree-3 nodes into degree-2 and let the merge run.

The obstacle is that it requires parallel_priority, a column ranked ascending to decide
which of two parallel chains survives, and transit has only mode (enum.transit_mode,
metro before tram). Using mode is semantically odd — it would mean a metro line survives
over a parallel tram line, which is defensible on a map but is not what the knob is for, and
within-mode pairs would fall through to the longer-then-stable-key tiebreak. Worth checking
whether parallel_priority can simply be made optional, defaulting to longest-wins, since
that is what this layer actually wants.

How to verify

  • -regeneralize makes it cheap: transit is z9-14 and small.
  • The number to watch is the merge ratio and the node-degree histogram, not the runtime.
    The degree-2 share is the thing that has to move.
  • Re-measure the z9 Warszawa tile (zxy_map_transit(9,285,168), 29 203 B today).
  • Check Sweden does not regress: it is at 2.0x and its metro/tram should not lose track it
    needs, and Stockholm's parallel metro tracks are a different case from Warsaw's trams.
  • Both countries render tram/metro in the style's transit layers; confirm visually that no
    line disappears rather than merges.

Measured on the database rebuilt by the full import of 2026-08-02; background in
docs/performance.md, "Water at coarse zoom", final section.

`merge_lines` was added to `transit` as part of #27 and effectively did nothing for Poland. It is applied and working — it is just finding almost nothing to merge. | | z14 (source) | z13 (first merged level) | ratio | avg length | |---|---:|---:|---:|---:| | Sweden | 1 764 | 862 | **2.0x** | 363 m -> 742 m | | Poland | 8 334 | **7 280** | **1.14x** | 301 m -> 344 m | Poland still measures **2.1 points per feature** at z9, which is the over-division signature `merge_lines` exists to remove. Nothing further merges below z13 in either country (7 280 at z13 and at z9), so this is not a "merge earlier" problem. ### It is not a precision problem The first guess — sub-metre gaps between segments, so endpoints do not coincide and `ST_LineMerge` refuses — is wrong. Of Poland's 16 668 segment endpoints, **15 804 (94.8%) exactly share a node** with another endpoint of the same `mode`. Only 64 have a neighbour under 1 m away without touching, and 279 are isolated. The data is well connected. ### It is node degree `ST_LineMerge` chains only through nodes of **degree 2**. A node where three or more lines meet ends the chain, and that is what the two networks differ in: | node degree | Poland | Sweden | |---:|---:|---:| | 1 | 858 | 221 | | 2 (chainable) | **1 057 (17%)** | **902 (56%)** | | 3 | **3 854** | 431 | | 4 | 513 | 47 | | 5+ | 16 | 4 | 73% of Poland's tram nodes are junctions, against 30% of Sweden's. BDOT10k `SKTR` models each track separately and splits it at every crossover and switch, which is how tram track is actually laid — so the chains break almost everywhere by construction. No amount of merging tolerance changes that; the graph genuinely has that shape. ### Worth fixing `transit` is **29 203 B of the 261 622 B z9 tile over Warszawa (11%)**, and 19 895 B of 134 643 B at z10 (15%). For a layer that draws tram lines in a handful of cities that is a lot. ### The candidate **`parallel_merge_pixels`**, which is what collapsed double track and yard tracks for `railways`. Most of those degree-3 nodes are crossovers *between the two tracks of one line*; collapse the parallel pair and the crossovers stop being junctions, which should convert a large share of degree-3 nodes into degree-2 and let the merge run. The obstacle is that it requires `parallel_priority`, a column ranked ascending to decide which of two parallel chains survives, and `transit` has only `mode` (`enum.transit_mode`, metro before tram). Using `mode` is semantically odd — it would mean a metro line survives over a parallel tram line, which is defensible on a map but is not what the knob is for, and within-mode pairs would fall through to the longer-then-stable-key tiebreak. Worth checking whether `parallel_priority` can simply be made optional, defaulting to longest-wins, since that is what this layer actually wants. ### How to verify - `-regeneralize` makes it cheap: `transit` is z9-14 and small. - The number to watch is the **merge ratio and the node-degree histogram**, not the runtime. The degree-2 share is the thing that has to move. - Re-measure the z9 Warszawa tile (`zxy_map_transit(9,285,168)`, 29 203 B today). - Check Sweden does not regress: it is at 2.0x and its metro/tram should not lose track it needs, and Stockholm's parallel metro tracks are a different case from Warsaw's trams. - Both countries render tram/metro in the style's `transit` layers; confirm visually that no line disappears rather than merges. Measured on the database rebuilt by the full import of 2026-08-02; background in `docs/performance.md`, "Water at coarse zoom", final section.
Owner

PR #57#57

PR #57 — https://git.blahonga.org/art/ismap/pulls/57
art closed this issue 2026-08-05 08:06:17 +00:00
Sign in to join this conversation.
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#38
No description provided.