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
This commit is contained in:
2026-09-13 22:42:05 +02:00
parent 7dc9a15932
commit a81b52a456
2 changed files with 33 additions and 2 deletions
+2 -1
View File
@@ -72,7 +72,7 @@ basemap:
stations: stations:
show: true # draw station markers (symbols without text) show: true # draw station markers (symbols without text)
styles: [metro, s_tog, regional] styles: [metro, s_tog, regional, bus]
marker: marker:
shape: circle # circle | square shape: circle # circle | square
fill: white fill: white
@@ -81,6 +81,7 @@ stations:
metro: 3.5 metro: 3.5
s_tog: 3.0 s_tog: 3.0
regional: 2.5 regional: 2.5
bus: 1.5
linewidth: 0.8 linewidth: 0.8
labels: labels:
+31 -1
View File
@@ -201,6 +201,31 @@ def plot_stations(ax, stations, styling, active_styles):
linewidths=lw, zorder=z, alpha=1.0) 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): def label_stations(ax, stations, styling, active_styles):
if stations is None or stations.empty: if stations is None or stations.empty:
return return
@@ -263,6 +288,10 @@ def main():
stations = gpd.read_file(PROCESSED / "master.gpkg", layer="stations").to_crs(TARGET_CRS) stations = gpd.read_file(PROCESSED / "master.gpkg", layer="stations").to_crs(TARGET_CRS)
except Exception: except Exception:
stations = None 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) lines = filter_lines(lines, args)
print(f"rendering {len(lines)} line features", flush=True) print(f"rendering {len(lines)} line features", flush=True)
@@ -298,6 +327,7 @@ def main():
# station markers (symbols, no text) # station markers (symbols, no text)
if not args.no_stops: if not args.no_stops:
plot_stations(ax, stations, styling, active_styles) plot_stations(ax, stations, styling, active_styles)
plot_bus_stops(ax, stops, styling, active_styles)
# station labels (opt-in via --labels) # station labels (opt-in via --labels)
if args.labels: if args.labels:
@@ -306,7 +336,7 @@ def main():
label_stations(ax, stations, styling, active_styles) label_stations(ax, stations, styling, active_styles)
# title + attribution # 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", transform=ax.transAxes, ha="center", va="top",
fontsize=fig_w * 1.1, fontweight="bold", color="#222", fontsize=fig_w * 1.1, fontweight="bold", color="#222",
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="none", alpha=0.7)) bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="none", alpha=0.7))