From d1a8383cb794e9d270feb2849fa2c5dd70f66ff3 Mon Sep 17 00:00:00 2001 From: marvin Date: Sun, 13 Sep 2026 22:42:05 +0200 Subject: [PATCH] Add bus stop markers from stops layer - plot_bus_stops(): loads bus stops from master.gpkg stops layer (1610 points), draws small white-filled circles (1.5pt) at each location - stops layer loaded in main() alongside stations - 'bus' added to stations.styles and marker.size in styling.yaml - bus stops respect --no-stops and --no-buses / --modes filters - bus marker zorder sits just above bus lines --- copenhagen/config/styling.yaml | 3 ++- copenhagen/scripts/render.py | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/copenhagen/config/styling.yaml b/copenhagen/config/styling.yaml index 1eaa982..b79a479 100644 --- a/copenhagen/config/styling.yaml +++ b/copenhagen/config/styling.yaml @@ -72,7 +72,7 @@ basemap: stations: show: true # draw station markers (symbols without text) - styles: [metro, s_tog, regional] + styles: [metro, s_tog, regional, bus] marker: shape: circle # circle | square fill: white @@ -81,6 +81,7 @@ stations: metro: 3.5 s_tog: 3.0 regional: 2.5 + bus: 1.5 linewidth: 0.8 labels: diff --git a/copenhagen/scripts/render.py b/copenhagen/scripts/render.py index 7cfc050..762b6ea 100644 --- a/copenhagen/scripts/render.py +++ b/copenhagen/scripts/render.py @@ -201,6 +201,31 @@ def plot_stations(ax, stations, styling, active_styles): linewidths=lw, zorder=z, alpha=1.0) +def plot_bus_stops(ax, stops, styling, active_styles): + """Draw small markers for bus stops from the stops layer.""" + if stops is None or stops.empty or "bus" not in active_styles: + return + cfg = styling.get("stations", {}) + if not cfg.get("show", True) or "bus" not in set(cfg.get("styles", [])): + return + bus = stops[stops["style"] == "bus"] + if bus.empty: + return + + mk = cfg.get("marker", {}) + sizes = mk.get("size", {}) + sz = sizes.get("bus", 1.5) + fill = mk.get("fill", "white") + edge = mk.get("edge", "#2b2b2b") + lw = mk.get("linewidth", 0.8) + shape = mk.get("shape", "circle") + marker = "o" if shape == "circle" else "s" + z = styling["zorder"].get("bus", 1) + 0.5 + + ax.scatter(bus.geometry.x, bus.geometry.y, s=sz ** 2, marker=marker, + c=fill, edgecolors=edge, linewidths=lw, zorder=z, alpha=0.8) + + def label_stations(ax, stations, styling, active_styles): if stations is None or stations.empty: return @@ -263,6 +288,10 @@ def main(): stations = gpd.read_file(PROCESSED / "master.gpkg", layer="stations").to_crs(TARGET_CRS) except Exception: stations = None + try: + stops = gpd.read_file(PROCESSED / "master.gpkg", layer="stops").to_crs(TARGET_CRS) + except Exception: + stops = None lines = filter_lines(lines, args) print(f"rendering {len(lines)} line features", flush=True) @@ -298,6 +327,7 @@ def main(): # station markers (symbols, no text) if not args.no_stops: plot_stations(ax, stations, styling, active_styles) + plot_bus_stops(ax, stops, styling, active_styles) # station labels (opt-in via --labels) if args.labels: @@ -306,7 +336,7 @@ def main(): label_stations(ax, stations, styling, active_styles) # title + attribution - ax.text(0.5, 0.985, "Copenhagen — Public Transit", + ax.text(0.5, 0.985, "Kurragömma Köpenhamn", transform=ax.transAxes, ha="center", va="top", fontsize=fig_w * 1.1, fontweight="bold", color="#222", bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="none", alpha=0.7))