diff --git a/copenhagen/scripts/render.py b/copenhagen/scripts/render.py index b48e202..ed3794a 100644 --- a/copenhagen/scripts/render.py +++ b/copenhagen/scripts/render.py @@ -234,8 +234,25 @@ def plot_stations(ax, stations, styling, active_styles): linewidths=lw, zorder=top_z, alpha=1.0) -def plot_bus_stops(ax, stops, styling, active_styles): - """Draw small markers for bus stops from the stops layer.""" +def rail_station_names(stations): + """Return the set of names for rail stations (metro/s_tog/regional).""" + if stations is None or stations.empty: + return set() + names = set() + for _, r in stations.iterrows(): + if classify_station(r) is not None: + name = r.get("name") + if isinstance(name, str) and name.strip(): + names.add(name) + return names + + +def plot_bus_stops(ax, stops, styling, active_styles, rail_names=None): + """Draw small markers for bus stops from the stops layer. + + Bus stops whose name matches a rail station are skipped — the rail + station marker represents that stop. + """ if stops is None or stops.empty or "bus" not in active_styles: return cfg = styling.get("stations", {}) @@ -245,6 +262,9 @@ def plot_bus_stops(ax, stops, styling, active_styles): if bus.empty: return + if rail_names is None: + rail_names = set() + cluster_cfg = cfg.get("stop_cluster_m", {}) cluster_m = cluster_cfg.get("bus", 50) if isinstance(cluster_cfg, dict) else cluster_cfg mk = cfg.get("marker", {}) @@ -258,8 +278,13 @@ def plot_bus_stops(ax, stops, styling, active_styles): top_z = max(styling["zorder"].values()) + 1 # cluster same-name bus stops within threshold (opposite sides of road) + # skip names that match a rail station (merged into station marker) centroids = [] + skipped = 0 for name, grp in bus.groupby("name"): + if name and name in rail_names: + skipped += len(grp) + continue coords = [(r.geometry.x, r.geometry.y) for _, r in grp.iterrows()] if name and len(coords) > 1: centroids.extend(cluster_stops(coords, cluster_m)) @@ -372,7 +397,8 @@ 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) + rail_names = rail_station_names(stations) + plot_bus_stops(ax, stops, styling, active_styles, rail_names=rail_names) # station labels (opt-in via --labels) if args.labels: