Add bus whitelist, route exclusions, crow-fly shape filter, and KML export #2
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user