Skip to content

OSM hiking & cycling trail routing for Land mode#33

Closed
radumarias wants to merge 3 commits into
mainfrom
claude/ferry-weather-api-CPt9O
Closed

OSM hiking & cycling trail routing for Land mode#33
radumarias wants to merge 3 commits into
mainfrom
claude/ferry-weather-api-CPt9O

Conversation

@radumarias
Copy link
Copy Markdown
Member

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

  • New src/lib/server/osm-land.ts — analog of osm-ferry.ts. Queries Overpass for ways tagged:
    • highway=path | footway | track | bridleway | cycleway | pedestrian | steps
    • foot=designated or bicycle=designated
    • Builds a geojson-path-finder graph, snaps each endpoint to the nearest vertex, returns the routed polyline + length + hike/bike way counts.
  • /api/route?land=1 → calls computeLandTrailRoute first, falls back to straight-line if no network connects the endpoints.
  • /api/multi-route?land=1 → each leg attempts trail routing; new trailLegs count surfaces in the response.
  • RouteView.svelte adds a 🥾 Trail route via OpenStreetMap meta-line (with hike/bike way breakdown). WaypointsView.svelte adds 🥾 N trail to the track summary.
  • i18n: new keys route.trailPrefix / trailWaysSuffix / trailWaysTitle / trailLabel, waypoints.trailLegs, and updated routeDesc in 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.
  • Bbox pad is graduated by trip length to keep Overpass payloads bounded.
  • Overpass responses are cached for 24 h via the existing cached() helper.

Verified

  • pnpm check — 0 errors
  • pnpm test — 75/75 pass
  • pnpm build — succeeds
  • Manual smoke test against /api/route?from=13.7308,100.5418&to=13.7253,100.5435&land=1 (Lumpini Park, Bangkok) returns kind: 'trail', 0.91 km, 52-point polyline snapped through real paths.
  • Sea-mode path unchanged (regression check passes).

Test plan

  • Open the deployed preview, pick Land mode in the top toggle.
  • In Route tab, pick two points within a trail-rich area (e.g., inside a park) — verify the polyline follows real paths and the meta-line shows 🥾 Trail route via OpenStreetMap with hike/bike counts.
  • In Waypoints tab, drop 3+ points along a hiking area — verify the track summary shows 🥾 N trail legs.
  • Pick endpoints far from any trail — verify it gracefully falls back to straight-line with a (trail: snap-too-far / no-path / span-too-wide …) hint.
  • Switch back to Sea mode and confirm ferry/sea routing still works (no regression).
  • Language switcher → TH and RO — verify the new meta-line strings render correctly.

https://claude.ai/code/session_01B9DMrLPT7hYfdCTsJgFF9q


Generated by Claude Code

claude added 2 commits May 22, 2026 13:58
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
@radumarias
Copy link
Copy Markdown
Member Author

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
/api/route?land=1 and /api/multi-route?land=1 snap to real trail networks instead of straight lines
Trail meta-line in RouteView/WaypointsView (🥾 Trail route via OpenStreetMap)
i18n keys for trail routing in en/th/ro
The problem: The branch is based on old main and its +server.ts / i18n files conflict heavily with the wind-direction, compass, and GPS changes we've since shipped. Rebasing or merging would require resolving conflicts in ~5-6 files.

Options:

  1. Cherry-pick the trail-routing logic (osm-land.ts is self-contained) onto a fresh branch from current main, re-wire the API handlers and i18n manually — cleanest
  2. Rebase PR OSM hiking & cycling trail routing for Land mode #33 onto current main — lots of conflict resolution
  3. Close OSM hiking & cycling trail routing for Land mode #33 and re-implement from scratch on current main — since I wrote it originally, this is fast
    I'd recommend option 1 or 3 — want me to bring the trail routing onto current main?

@radumarias radumarias closed this May 25, 2026
@radumarias
Copy link
Copy Markdown
Member Author

new impl #41

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants