OSM hiking & cycling trail routing for Land mode#33
Conversation
Adds an OSM trail resolver mirroring the existing ferry one. In Land mode, /api/route and /api/multi-route now snap from/to onto the nearest hiking/cycling way and path-find through the network before falling back to a straight line. Trail metadata (length, hike/bike way counts) is surfaced in RouteView and per-leg in WaypointsView. Considered OSM tags: highway=path|footway|track|bridleway|cycleway| pedestrian|steps, plus foot=designated or bicycle=designated. Bbox is kept tight (max span 1.5°, snap budget 5km) because trail networks are dense and Overpass payloads grow quickly. i18n keys added for EN/TH/RO covering the new route-meta strings. https://claude.ai/code/session_01B9DMrLPT7hYfdCTsJgFF9q
Empty results are usually a transient server-side timeout (200 OK, zero elements) rather than a genuine "no trails here". Treat them as a failure and try the next mirror instead of caching the empty list for the full 24h TTL. https://claude.ai/code/session_01B9DMrLPT7hYfdCTsJgFF9q
fitBounds and flyTo don't need the style loaded — they only update the
camera. Move them outside the isStyleLoaded() gate so a fresh page load
from a shared URL (which arrives with markers already in the URL hash,
before the MapLibre style finishes loading) lands framed on the route
instead of the default view.
The route source/layer still need the style; keep them gated and defer
via map.once('load', …) when the style isn't ready yet.
Also prefer the polyline bounds over the marker bounds when fitting —
a routed sea / trail polyline can detour well outside the from→to bbox,
so fitting on the polyline gives a better initial frame.
https://claude.ai/code/session_01B9DMrLPT7hYfdCTsJgFF9q
|
We go with 3 from below PR #33 adds OSM hiking/cycling trail routing for Land mode — and none of it is on main. The key files (osm-land.ts, trail i18n keys, route handler changes) don't exist. However, it has merge conflicts (mergeable_state: "dirty") because main has diverged significantly since it was opened (all the wind compass, GPS follow, service worker changes). What it adds (all new, not on main): src/lib/server/osm-land.ts — Overpass query for hiking/cycling trails, path-finding via geojson-path-finder Options:
|
|
new impl #41 |
Summary
Adds an OSM trail-routing resolver for Land mode, mirroring the existing ferry/sea routing used in Sea mode. When the user is in Land mode on the Route or Waypoints tabs, each leg is now snapped onto OpenStreetMap hiking/cycling ways and path-found through the network — instead of always drawing a straight line.
Implementation
src/lib/server/osm-land.ts— analog ofosm-ferry.ts. Queries Overpass for ways tagged:highway=path | footway | track | bridleway | cycleway | pedestrian | stepsfoot=designatedorbicycle=designatedgeojson-path-findergraph, snaps each endpoint to the nearest vertex, returns the routed polyline + length + hike/bike way counts./api/route?land=1→ callscomputeLandTrailRoutefirst, falls back to straight-line if no network connects the endpoints./api/multi-route?land=1→ each leg attempts trail routing; newtrailLegscount surfaces in the response.RouteView.svelteadds a🥾 Trail route via OpenStreetMapmeta-line (with hike/bike way breakdown).WaypointsView.svelteadds🥾 N trailto the track summary.route.trailPrefix / trailWaysSuffix / trailWaysTitle / trailLabel,waypoints.trailLegs, and updatedrouteDescin the help page — translated for EN / TH / RO.Constraints
Trail networks are an order of magnitude denser than ferry ways, so:
MAX_SPAN_DEG = 1.5(vs 6 for ferry) — trips wider than ~165 km bail out early.MAX_SNAP_KM = 5— if neither endpoint is within 5 km of a trail, fall back rather than render a confusing line.cached()helper.Verified
pnpm check— 0 errorspnpm test— 75/75 passpnpm build— succeeds/api/route?from=13.7308,100.5418&to=13.7253,100.5435&land=1(Lumpini Park, Bangkok) returnskind: 'trail', 0.91 km, 52-point polyline snapped through real paths.Test plan
🥾 Trail route via OpenStreetMapwith hike/bike counts.🥾 N traillegs.(trail: snap-too-far / no-path / span-too-wide …)hint.https://claude.ai/code/session_01B9DMrLPT7hYfdCTsJgFF9q
Generated by Claude Code