Add bus whitelist, route exclusions, crow-fly shape filter, and KML export #2

Open
marvin wants to merge 16 commits from add-kml-export-and-bus-filtering into master
Showing only changes of commit 8b2433ae93 - Show all commits
+29 -3
View File
@@ -234,8 +234,25 @@ def plot_stations(ax, stations, styling, active_styles):
linewidths=lw, zorder=top_z, alpha=1.0) linewidths=lw, zorder=top_z, alpha=1.0)
def plot_bus_stops(ax, stops, styling, active_styles): def rail_station_names(stations):
"""Draw small markers for bus stops from the stops layer.""" """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: if stops is None or stops.empty or "bus" not in active_styles:
return return
cfg = styling.get("stations", {}) cfg = styling.get("stations", {})
@@ -245,6 +262,9 @@ def plot_bus_stops(ax, stops, styling, active_styles):
if bus.empty: if bus.empty:
return return
if rail_names is None:
rail_names = set()
cluster_cfg = cfg.get("stop_cluster_m", {}) cluster_cfg = cfg.get("stop_cluster_m", {})
cluster_m = cluster_cfg.get("bus", 50) if isinstance(cluster_cfg, dict) else cluster_cfg cluster_m = cluster_cfg.get("bus", 50) if isinstance(cluster_cfg, dict) else cluster_cfg
mk = cfg.get("marker", {}) mk = cfg.get("marker", {})
@@ -258,8 +278,13 @@ def plot_bus_stops(ax, stops, styling, active_styles):
top_z = max(styling["zorder"].values()) + 1 top_z = max(styling["zorder"].values()) + 1
# cluster same-name bus stops within threshold (opposite sides of road) # cluster same-name bus stops within threshold (opposite sides of road)
# skip names that match a rail station (merged into station marker)
centroids = [] centroids = []
skipped = 0
for name, grp in bus.groupby("name"): 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()] coords = [(r.geometry.x, r.geometry.y) for _, r in grp.iterrows()]
if name and len(coords) > 1: if name and len(coords) > 1:
centroids.extend(cluster_stops(coords, cluster_m)) centroids.extend(cluster_stops(coords, cluster_m))
@@ -372,7 +397,8 @@ 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) rail_names = rail_station_names(stations)
plot_bus_stops(ax, stops, styling, active_styles, rail_names=rail_names)
# station labels (opt-in via --labels) # station labels (opt-in via --labels)
if args.labels: if args.labels: