#64 per-country transit stops: Warsaw metro from BDOT10k OIKM_P (official, with badge), Kraków/Łódź tram, FI Digiroad tram #66
No reviewers
Labels
No labels
claude-wip
map-report
map:is
map:se
needs-review
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
art/ismap!66
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "night/issue-64-per-country-stops"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
#64 per-country transit stops: BDOT10k OIKM_P metro+rail, Kraków/Łódź tram feeds, Digiroad tram stops
Part of the #64 per-country delegation the transit-design PR (#65) left for the
follow-up. The Warsaw metro question that PR left open is answered here — the
official source was BDOT10k all along — and the rest of the delegation's stop data
lands with it. #63 (commuter reach) stays open.
The metro, found
BDOT10k's
OIKM_Pclass ("obiekt związany z komunikacją") carries the Warsaw metroentrances —
rodzaj = 'wejście do stacji metra', 258 of them in the Warsaw county,named after their station (Bemowo ×10, Świętokrzyska ×13, …), survey-grade in
EPSG:2180. The class was always part of the national topographic database; the
Makefile's
BDOT10K_CLASSESlist simply never fetched it — the old "BDOT10k has nostop point class at all" claim (and the "no official metro source" finding built on
it) was about the 16 fetched classes, not the delivery. This PR adds the class to the
fetch (with the marker bumped to
pt-sw-sk-oikmso the done-state encodes the classset), stages it (
pl_oikm, all 380 counties), and gives thestationslayer two newbranches:
name, so the name-grouped centroid is the station point (no DBSCAN — the
Świętokrzyska ring spans 700+ m); entrance groups within 250 m of each other are
one station under the modal name (Wileński's 12 entrances absorb the 13th,
"Dworzec Wileński", instead of emitting two points 146 m apart). 38 named
stations, the full M1+M2 network.
kategoriaistnienia(BDOT10k's existence flag)excludes the under-construction M2 western-extension entrances — the unopened
Lazurowa station draws no badge (6 unnamed + 4 named Lazurowa w budowie
entrances; the flag is empty on some rows, so the predicate is IS DISTINCT FROM
'nieczynny'/'w budowie').
importance2 (the ordinary-station rung, same asStockholm's metro) → z11.
'stacja lub przystanek kolejowy'kind, onepoint per named station nationally. Same-named stations in different places stay
apart via
ST_ClusterDBSCANat 1 000 mPARTITION BY nazwa(the 150 m tram valuewould split a single big station — Warszawa Wschodnia's platform points span
319 m; measured same-name pairs sit <500 m within one station and >1 km between
different ones, so 1 000 m is the natural break).
kategoriaistnieniaexcludesclosed/unbuilt points (99 all-closed stations in the old output). 3 187 named
stations nationally (mode NULL).
importance2, with the source's ownhalt/station signals (
skrotkartograficzny'st.'/'p. kol.',informacjadodatkowaPKP PLK note) examined and rejected — see docs/country-poland.md: they
mis-grade the country's biggest stations (Białystok, Katowice, Poznań Główny and
Gdynia Główna all carry the 'p. kol.' halt mark).
The
warszawa-metrobadge (issue #64) ships in this PR: the red M on a yellow disc(public domain from Wikimedia Commons — PD-textlogo, the same tag as the Stockholm
symbols), sprite-registered under its network name, drawn by the style's
station_icons layer from z11. The SVG is normalized to the same disc size as the
Stockholm T and carries a proper viewBox.
The rest of the stop data
the
?download=1query trick and the shared 150 m DBSCAN collapse as before). OIKM_Pcannot replace them: its stop type is one value ('przystanek autobusowy lub
tramwajowy') and track proximity cannot separate the two — validated: 91% of ALL
Warsaw stops sit within 75 m of a tram line. GTFS route_type is the exact
discriminator. The ~184k national bus/tram points OIKM_P also carries are
documented as the source of a future national stop layer (the same idea as
Finland's DR_PYSAKKI bus stops).
stations— the country's tram stops from Digiroad's DR_PYSAKKI (unchangedfrom the previous revision of this PR): the
pysakitproduct,PYS_TYYPPI[1]=tram/light rail — 469 poles in Helsinki/Tampere/Raide-Jokeri → 288 stop points. The
shapefile reader gained point support and fetch.go fetches shapefile siblings.
Verification (live DB, after the review round)
make build;go test ./...in importer/ and mapsrv/ — pass; configs parsethrough the real loader;
git diff --checkclean.map_stations_14_pl= 3 187 rail / 827 tram / 38metro; all 38 metro rows carry
unique_icon = 'warszawa-metro'. Zoom filters perrung (tram z12, metro/rail z11).
spread >1 km groups) no longer collapse into a single midway point; the largest
single-station spread (Narzym, 667 m) stays one station.
nieczynny/w budowie points; the unopened Lazurowa M2 station is absent from the
metro set.
apart before).
name/mode/importance/unique_iconon every feature; metro features carrythe
warszawa-metroicon name.on the yellow disc at the same disc size as the Stockholm T (50 px vs 48 px at a
60 px render, vs the previous ~59 px full-grid fill).
Docs
docs/country-poland.md— stations section rewritten: the three-rung table(metro + rail from OIKM_P, tram from GTFS), the corrected "no stop class" claim,
the metro-entrance→station derivation (Lazurowa exclusion, Wileński merge), the
rail DBSCAN eps and kategoriaistnienia reasoning, the halt/station importance
rejection, and the national totals (3 187 rail / 38 metro, not "89 in the Warsaw
county").
docs/country-finland.md— DR_PYSAKKI row + stations section (unchanged from theprevious revision).
docs/workstream-a.md— the OIKM_P catalogue row (17 classes now), the correctedclass count.
Makefile—OIKM_Padded toBDOT10K_CLASSES;BDOT10K_MARKERbumped topt-sw-sk-oikm.mapsrv/icons/README.md— three badges, Warsaw colours, no more hypotheticals.This PR does not close #64 — the FI metro stops (HSL GTFS) and the commuter reach
question (#63) remain.
#64 per-country transit stops: Kraków/Łódź tram feeds, Digiroad tram stops, Warsaw metro findingto #64 per-country transit stops: Warsaw metro from BDOT10k OIKM_P (official, with badge), Kraków/Łódź tram, FI Digiroad tramThe "no official source for Warsaw's metro stations" finding was wrong, and this commit lands the correction. **BDOT10k's OIKM_P class ("obiekt związany z komunikacją") carries the metro entrances** — rodzaj 'wejście do stacji metra', 258 of them in the Warsaw county, named after their station. The class was always part of the national topographic database; the Makefile's BDOT10K_CLASSES list simply never fetched it, and the old "BDOT10k has no stop point class" claim was about the 16 fetched classes, not the delivery. - Makefile: OIKM_P added to BDOT10K_CLASSES, with a per-file skip condition so already-done counties re-fetch once (all 380 landed, ~15 GB one-time). - conf/plmap.yaml: pl_oikm staging (glob over all counties), and the stations query gains two branches: - metro: entrances collapsed by name to the station point (the general entrance-collapse recipe — same-named nearby points to their mean position; the name-grouped centroid of a point collection IS the mean). 40 named stations, the full M1+M2 network. importance 2 (same as Stockholm's metro). - heavy rail: rodzaj 'stacja lub przystanek kolejowy', one point per named station — 89 in the Warsaw county, 3 269 nationally, which finally gives Poland the rail rung of the stations contract (mode NULL). - tram stays on the three GTFS feeds: OIKM_P's stop type is one value ('przystanek autobusowy lub tramwajowy') and track proximity cannot separate the modes (91% of ALL Warsaw stops sit within 75 m of a tram line). - The warszawa-metro badge lands (issue #64): the red M on a yellow disc, public domain from Wikimedia Commons (Witold Popiel 1983; SVG by Kubek15), registered in sprite.go under its network name and carried by the metro branch's unique_icon — the style's station_icons layer draws it from z11, the slot the old comment said would stay empty. Probe-verified (red + yellow both rasterize; probe deleted). - docs: country-poland.md stations section rewritten (three-rung table, the corrected claim, the entrance-collapse recipe); workstream-a.md gains the OIKM_P row (17 classes). Verified: make build, go test ./... (importer, mapsrv), full reimport — map_stations_14_pl 827 → 4 136: tram 827 (unchanged), metro 40 (all named, unique_icon warszawa-metro), rail 3 269 (named, mode NULL). Zoom filters: metro + rail at z11/z10, +tram at z12, z9 empty. Decoded z13 tiles: the Bemowo tile carries Bemowo + Lazurowa with mode=metro + unique_icon='warszawa-metro'; a Łódź tile carries the tram stops + rail stations (Łódź Dąbrowa/Zarzew). Co-Authored-By: Hermes Agent <noreply@nousresearch.com>Review
The OIKM_P finding is real and well argued, the tram-vs-bus validation is the right call, and the FI half is clean. The Poland rail branch is where I'd push back: it is the only branch that runs nationally, and it drops the two safeguards the other branches have. Everything below is verified against the live
mapsDB (the branch's own staging tables are still loaded).Blocking
1. The rail branch's
GROUP BY nazwais national — same-named stations across Poland collapse into one phantom point. The metro/rail branches inconf/plmap.yamlgroup by name alone, with no DBSCAN. For metro that's fine (one city). For rail it isn't:20 name groups spread >1 km, 9 over 10 km.
Żabno's two stations sit ~470 real km apart and render as a single station halfway between them. The tram branch's own comment states the reason the eps exists — "the eps is what keeps two same-named groups in different places apart" — and the rail branch is exactly the case it describes. Fix is the pattern already in the file:ST_ClusterDBSCAN(geom, eps, 1) OVER (PARTITION BY nazwa), thenGROUP BY nazwa, cl.2.
kategoriaistnieniais never filtered, so closed and unbuilt stations render as live ones. The column is BDOT10k's existence flag and it is populated:99 output rail stations consist entirely of
nieczynny/w budowiepoints. And the metro claim in the config comment — "Five unnamed entrances (two clusters — under-construction stations) are excluded by the nazwa filter" — doesn't hold: of the 10w budowieentrances, 6 are unnamed (excluded) but 4 are namedLazurowa, so the unopened M2 western-extension station is in the 40 and draws an M badge. Thenazwa IS NOT NULLfilter is a proxy for a flag the source actually carries. Note 773 rail rows have the column empty, so the predicate wants to bekategoriaistnienia IS DISTINCT FROM 'nieczynny' AND IS DISTINCT FROM 'w budowie', not= 'eksploatowany'.Worth fixing
3. Duplicate metro station point. BDOT10k names 12 entrances
Wileńskiand oneDworzec Wileński— the same M2 station. Name-only grouping emits two stations 146 m apart, both badged, from z11. The argument against DBSCAN here (Świętokrzyska's ring spans 700+ m) is sound, so the fix isn't DBSCAN — either normalise the name, or, since 40 stations is a hand-checkable set, collapse metro entrances spatially at ~250 m and take the modal name.4.
importance2 for every rail point contradicts the shared ladder.common.yamldefines rung 1 as "halt, minor stop, non-passenger operating point", and the class is literally stacja lub przystanek. The source does carry a discriminator —skrotkartograficznyis'st.'(68) vs'p. kol.'(2 327), andinformacjadodatkowasays"stacja kolejowa - wg danych PKP PLK"on 857 rows. As it stands Poland puts 3 269 points on the z11 rung where Finland grades named-vs-unnamed and Sweden grades on ResUtbyte/PlTyp. Either use the signal or record in the docs that it was seen and why it was rejected — the docs currently mention neither the halt/station split nor the national total (they stop at "89 in the Warsaw county").Stale text
5. The PR body describes the previous revision: it says the badge is a sprite decision that hasn't landed and "the metro renders as the style's blue-ringed mode=metro dot", and reports
unique_iconNULL on every row and ~1 900 rows. The branch shipswarszawa-metro.svg, and the live table is 4 136 rows (3 269 rail / 827 tram / 40 metro, all 40 withunique_icon).6.
docs/country-poland.mdcontradicts itself — line ~242 announces the Warsaw badge, line ~297 still says "the metro T and the commuter J are the only station badges, and both are Stockholm's". The adjacent line was edited in this PR, so it was in view.7.
mapsrv/icons/README.md: "Both are scaled from their original artwork…" immediately after listing three; the colour list (#000080,#aeacad,#231f20) doesn't include the Warsaw red/yellow; and "A new network's badge (say, a Warsaw metro M)" is no longer hypothetical.Minor
8. The badge rasterizes correctly (rendered at 60 px — the M reads clean), but it fills the grid:
r=44.5of a 91-unit box vs Stockholm's6.35of 15, so the M draws ~13% larger than the T at the sameicon-size. It also has noviewBox, relying on oksvg's width/height fallback, unlike the other two — which is what the README's "scaled by the sprite pipeline" sentence describes but isn't quite what happens. Also worth a second look at the PD claim: Wikimedia's tag rests on Polish law's official-symbols exemption, which is thinner ground than the Swedish two.9. The Makefile skip condition
[ -f "$marker" ] && [ -f "…OT_OIKM_P.gpkg" ]re-downloads a county's whole zip on every run forever if that county's delivery ever lacks the class. All 380 carry it today (count(distinct teryt)= 380 inpl_oikm, vs 372 inpl_sktr), so it's cosmetic — but bumpingBDOT10K_MARKERtopt-sw-sk-oikmis what that variable is for and stays idempotent.Checks out
fetch.go's sibling marking is safe —neededonly gates declareddownloads:entries, so marking.prj/.cpgcan't invent a 404. The shapefile point support is a tidy split (esriShapeToEWKT). FI is clean: 288 tram / 383 named rail / 176 unnamed, zero unnamed tram stops, so theNULLIF(BTRIM(nimi_su),'')NULL path never fires.zoom_filtersmatch SE and FI (11/9).style.jsonneeds no change — it selects onunique_icongenerically.importerbuilds and tests pass;mapsrv'sTestDumpGlyphPNGfails identically onmain(it writes/tmp/glyph_g.png, sandbox permission), so it is not this PR.Review round answered — every item fixed and verified against the live DB
All changes are on
night/issue-64-per-country-stops(commit5a1ea58, pushed), andthe PR body now describes the current revision. Verification was done against the
live
mapsDB after a full-layer stationsreimport.Blocking 1 — rail DBSCAN (fixed)
The rail branch now clusters like the tram branch:
ST_ClusterDBSCAN(geom, 1000, 1) OVER (PARTITION BY nazwa),GROUP BY nazwa, cl. The eps is 1 000 m, justified fromthe data: 150 m (the tram value) would split a single big station — Warszawa
Wschodnia's platform points span 319 m with a 255 m gap between groups — while
measured same-name pairs sit <500 m within one station and >1 km between different
ones, so 1 000 m is the natural break between the two populations. Verified: the
review's phantoms all split into 2 stations (Baranowo's two are 473 147 m apart —
the exact spread the review measured), as do Głuchów, Majdan, Chrząstowice, Janówek,
Tarnobrzeg; the largest single-station spread (Narzym, 667 m) stays whole, and
Warszawa Wschodnia / Zachodnia remain one station each. (Żabno and Wierzchosławice
now emit one station, not two — see blocking 2: their second point is
nieczynnyand is now filtered out.)
Blocking 2 — kategoriaistnienia filter (fixed)
kategoriaistnienia IS DISTINCT FROM 'nieczynny' AND IS DISTINCT FROM 'w budowie'is applied in both the rail and the metro branches (in the source query, not the
outer select), keeping the 773 rows where the flag is empty — so it is the
IS DISTINCT FROMform the review specified, not= 'eksploatowany'. Verified:every one of the 3 187 output rail stations has ≥1 source point that is
eksploatowanyor flag-empty (0 all-closed stations remain; the old output had 99).The metro claim is corrected too: the 4 named
w budowieentrances are Lazurowa,and Lazurowa is absent from the output — the unopened M2 station draws no M badge.
(The config comment no longer claims the nazwa filter excludes the under-
construction stations.)
Worth fixing 3 — metro dedupe (fixed)
Entrance groups within 250 m of each other are now one station under the modal
name (no DBSCAN — the Świętokrzyska ring spans 700+ m, untouched): Wileński (12
entrances) absorbs Dworzec Wileński (1), so the output has one Wileński point
instead of two 146 m apart. Verified:
Dworzec Wileńskiis absent frommap_stations_14_pl, Wileński present once. The metro count is 38, not 36:40 minus Lazurowa (one station name with 4 entrances) minus the Wileński merge.
Full hand-checkable list, all with
unique_icon = warszawa-metro: Bemowo, Bródno,Centrum, Centrum Nauki Kopernik, Dworzec Gdański, Imielin, Kabaty, Kondratowicza,
Księcia Janusza, Marymont, Młociny, Młynów, Natolin, Nowy Świat Uniwersytet, Plac
Wilsona, Płocka, Pole Mokotowskie, Politechnika, Racławicka, Ratusz Arsenał, Rondo
Daszyńskiego, Rondo ONZ, Słodowiec, Służew, Stadion Narodowy, Stare Bielany,
Stokłosy, Świętokrzyska, Szwedzka, Targówek Mieszkaniowy, Trocka, Ulrychów,
Ursynów, Wawrzyszew, Wierzbno, Wilanowska, Wileński, Zacisze.
Worth fixing 4 — importance, with the rejection documented (fixed)
The signals were examined and rejected, with the reasoning recorded in
docs/country-poland.md (the option the review offered).
skrotkartograficzny'st.' vs 'p. kol.' is 71 vs 2 329 rows and
informacjadodatkowa"stacja kolejowa -wg danych PKP PLK" covers 830 rows — but Białystok, Katowice, Poznań Główny and
Gdynia Główna all carry the 'p. kol.' halt mark, 1 055 rows have no skrot at all,
and 433 'p. kol.' rows also carry the "stacja kolejowa" note. Any grading built on
them would demote the country's biggest stations to the halt rung, so Poland grades
the way Finland's rail does (named-vs-unnamed: all named → 2). The docs now mention
both the halt/station split and the national total: 3 187 rail stations (the old
text stopped at "89 in the Warsaw county").
Stale text 5–7 and minor 8–9 (fixed)
warszawa-metro.svgships, livetable is 4 052 rows = 3 187 rail / 827 tram / 38 metro, all 38 metro with
unique_icon."T and J are the only badges" line now agree (three network badges: the Warsaw M
in this PR, Stockholm's T and J).
#f8d958) added to the colour list, the "say, a Warsaw metro M" hypothetical
dropped.
105.1-unit box, like the commuter J's own coordinate system) and its disc now
fills the same fraction of the icon grid as the Stockholm T. Pixel-verified
through the real pipeline at 60 px: Warsaw disc 48 px vs Stockholm 50 px (was
~59 px full-grid before). The PD claim was re-checked against the Commons file:
the tag is PD-textlogo (below the threshold of originality) — the same tag
as the Stockholm metro symbol, not the Polish official-symbols exemption — and
the SVG/README state that precisely.
BDOT10K_MARKERbumped topt-sw-sk-oikm; docs/workstream-a.md marker listupdated to match.
Verification chain (repo convention)
make buildandgo test ./...pass in importer/ and mapsrv/ (the knownTestDumpGlyphPNG failure on main is unchanged); the conf loads through the real
loader;
git diff --checkclean. After the reimport:map_stations_14_pl= 4 052rows (3 187 / 827 / 38), all 38 metro with
unique_icon; per-zoom partitionscorrect (z11 = 3 225 = 38 + 3 187, z9 empty); decoded z11 tile over Warsaw carries
name/mode/importance/unique_icon/countryon stations with the badge name on themetro features; real-browser CDP check at z14 over Wileński renders the three metro
badges (Szwedzka, Stadion Narodowy, Wileński) with
unique_icon: warszawa-metro,and the sprite sheet pixel-check shows the red M on the yellow disc at the right
size. FI is untouched, per the review.
Review
The BDOT10k OIKM_P finding is genuinely good work, and the honesty about why the old "no official source" conclusion was wrong (16 fetched classes ≠ the delivery) is the right way to record it.
Everything I could check against the live DB holds up:
pl_oikmloaded, all 258 metro entrances in teryt 1465 (Warszawa), 39 metro names → 38 stations withDworzec Wileński → Wileńskias the only merge, 3,187 rail stations, FI'spys_tyyppiexactly[1]/[2]/[5]/[6]with 469 tram poles and zero unnamed, all 94,869 Digiroad rows loaded. Builds and vet pass. Thefetch.gosibling marking is safe —ensureDownloadsfilters the downloads list, so an unlisted.cpgis a no-op.1. Poland's z9 rung is empty, and z10 is crowded
Poland shows every rail halt in the country (3.3× Sweden) at a whole-country zoom, then nothing at z9 while Sweden shows its 485 major stations.
I agree with rejecting BDOT10k's own discriminator — Poznań Główny and Katowice carrying the
p. kol.halt mark is disqualifying, and the PR documents that well. But it leaves rung 3 unfilled. A name/administrative proxy (Główny/Centralna, voivodeship capitals) would fill it. Worth an issue rather than a blocker, since Finland has the same documented gap.2.
metro_mergedis non-transitive — latent misplacementconf/plmap.yaml, themetro_mergedCTE. Each name maps to the largest group within 250 m, independently. In a chain A(5) — B(10) — C(12) where A–C > 250 m, A→win=B and B→win=C, so the query emits a station named B positioned at A's entrances, plus one named C holding B's and C's.I checked: zero chain-broken cases in today's 39 names, so it doesn't fire. But the comment presents this as a general recipe ("Same recipe would apply to any future named-entrance source").
ST_ClusterDBSCAN(250)over the group centroids with a modal name per cluster would be the robust form.3.
unique_iconis hardcoded'warszawa-metro'for every metro row nationallyTrue today — verified all 258 entrances are in one teryt — but the value is a network name on a branch with no network predicate. Worth a note that this holds only while Poland has exactly one metro.
Minor
382cce0was right — but the old.pt-sw-sk.donemarkers are never cleaned up.pys_tyyppi LIKE '%[1]%'works (values are exactly[1]/[2]/[5]/[6], verified) but leans on brackets being literal in Postgres LIKE and on codes never reaching two digits.= '[1]'is exact and clearer.esriShapeToEWKThandles*shp.Pointand*shp.Polygononly;PointZ/PointM/PolygonZsilently return""and the row is skipped with no diagnostic. Fine here (all 94,869 rows loaded), but a silent skip is a bad failure mode for the next shapefile — a count of skipped shapes in the log would help.Disposition: mergeable as-is, with the z9 rung and the metro-merge transitivity filed as issues.
The one mapsrv test failure (
glyph_dump_test.go:40: open /tmp/glyph_g.png: permission denied) is environmental and reproduces onmain— not this PR.Follow-ups filed, both unassigned:
metro_mergedis non-transitive (latent; 0 chain-broken cases in today's 39 names)Neither blocks this PR.