Honor "Hidden" points of interest for bus stops and declutter at low zoom

Bus stop markers are our own Marker overlay drawn from Overpass data, not
Apple's native POI layer, so setting Points of Interest to "Hidden" (which
only sets MapStyle's pointsOfInterest category filter) had no effect on
them -- they kept showing regardless of the setting.

Separately, a bus route can have dozens of stops close together; zoomed
out they overlap into an unreadable stack of pins (see reported
screenshot: a wall of stacked bus icons across a multi-city view).

Fixes:
- Gate the bus stop markers on mapPointsOfInterestMode != .hidden so
  "Hidden" actually hides them.
- Track the map's visible latitude span via onMapCameraChange and thin
  markers through the existing dedupedBusStops spatial merge, using a
  spacing that scales with the visible span -- full detail at close zoom,
  progressively fewer markers as the map zooms out. The full-fidelity
  routeBusStops list (used for dwell pacing during playback) is
  untouched; only the on-screen marker set is thinned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DNqCsHShA4yNqgZ6ZZQy3
This commit is contained in:
Claude 2026-07-15 05:38:41 +00:00
parent a7792d0289
commit d2f09bea32
No known key found for this signature in database

View file

@ -1436,6 +1436,7 @@ struct LocationSimulationView: View {
@State private var routePolyline: MKPolyline?
@State private var routePlaybackSamples: [RoutePlaybackSample] = []
@State private var routeBusStops: [CLLocationCoordinate2D] = []
@State private var visibleLatitudeDelta: CLLocationDegrees = 0.05
@State private var routePlaybackCoordinate: CLLocationCoordinate2D?
@State private var simulatedCoordinate: CLLocationCoordinate2D?
@State private var routeRequestID = UUID()
@ -1494,6 +1495,29 @@ struct LocationSimulationView: View {
}
}
/// Bus stop markers to actually draw on the map. Two adjustments on top of
/// the raw fetched `routeBusStops`:
///
/// - Honors "Points of Interest: Hidden" — the stops are drawn as our own
/// Marker overlay, not Apple's native POI layer, so Apple's
/// `pointsOfInterest` style option (set from the same picker) has no
/// effect on them; that had to be handled here explicitly.
/// - Thins markers as the map zooms out, since a bus route easily has
/// dozens of stops that overlap into an unreadable stack of pins at a
/// city-wide zoom. Spacing scales with the visible latitude span so
/// roughly the same number of markers are visible on screen at any
/// zoom level; the full-fidelity `routeBusStops` list (used for dwell
/// pacing during playback) is untouched.
private var displayedBusStops: [CLLocationCoordinate2D] {
guard speedProfile == .bus, mapPointsOfInterestMode != .hidden else { return [] }
let visibleSpanMeters = visibleLatitudeDelta * 111_320
let minimumSpacing = max(
SpeedProfileSettings.busStopSnapRadius,
visibleSpanMeters / 25
)
return dedupedBusStops(routeBusStops, radius: minimumSpacing)
}
private var speedProfile: SpeedProfile {
SpeedProfile(rawValue: speedProfileRawValue) ?? .driving
}
@ -1648,11 +1672,9 @@ struct LocationSimulationView: View {
MapPolyline(routePolyline)
.stroke(.blue.opacity(0.8), lineWidth: 5)
}
if speedProfile == .bus {
ForEach(Array(routeBusStops.enumerated()), id: \.offset) { _, stop in
Marker("Bus Stop", systemImage: "bus.fill", coordinate: stop)
.tint(.orange)
}
ForEach(Array(displayedBusStops.enumerated()), id: \.offset) { _, stop in
Marker("Bus Stop", systemImage: "bus.fill", coordinate: stop)
.tint(.orange)
}
if let routeStartCoordinate {
Marker("Start", coordinate: routeStartCoordinate)
@ -1680,6 +1702,9 @@ struct LocationSimulationView: View {
.mapControls {
MapCompass()
}
.onMapCameraChange(frequency: .onEnd) { context in
visibleLatitudeDelta = context.region.span.latitudeDelta
}
}
.ignoresSafeArea()
.onChange(of: coordinate.map(CoordinateSnapshot.init)) { _, new in