Skip to content

feat: add antimeridian output option for dateline-crossing routes - #19

Merged
mayurrawte merged 1 commit into
mainfrom
feat/issue-9-antimeridian
Jul 3, 2026
Merged

feat: add antimeridian output option for dateline-crossing routes#19
mayurrawte merged 1 commit into
mainfrom
feat/issue-9-antimeridian

Conversation

@mayurrawte

@mayurrawte mayurrawte commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

Routes crossing the ±180° antimeridian (e.g. Yokohama → LA) come back wrapped to [-180, 180], so a segment jumps from +179 to -179. Fed straight into MapLibre / Leaflet / Deck.gl, that draws as a straight streak across the whole map instead of across the Pacific. This was already solved for our own demo (examples/web-demo/src/geo.ts); this PR moves the capability into the library so downstream map consumers don't each rediscover it.

What changed

New antimeridian option on seaRoute and seaRouteMulti:

seaRoute(yokohama, la, { antimeridian: 'unwrap' }); // continuous coords (may exceed ±180)
seaRoute(yokohama, la, { antimeridian: 'split' });  // MultiLineString split at ±180
  • Default undefined — current behaviour, wrapped LineString (no breaking change).
  • 'unwrap' — one continuous LineString; longitudes shifted by multiples of 360° so consecutive points never jump the dateline (the demo's approach).
  • 'split' — a MultiLineString cut at ±180°, keeping every coordinate within ±180° (RFC 7946-friendly), inserting the interpolated dateline point at both ends of each cut.

Details:

  • New src/lib/antimeridian.ts with unwrapCoords / splitAtAntimeridian.
  • Return types are narrowed by overload: { antimeridian: 'split' } returns the new SeaRouteMultiFeature (Feature<MultiLineString, …>); everything else still returns SeaRouteFeature. So existing TS consumers see no type change.
  • seaRouteMulti applies the option once to the concatenated route (legs are computed as plain wrapped LineStrings so they still join cleanly).
  • seaRouteAlternatives continues to return wrapped LineStrings (documented).
  • properties.length and bbox are computed from the geodesic path and are unaffected by the representation.
  • New exports: Antimeridian, SeaRouteMultiFeature. README / DOCS / CHANGELOG updated.

One subtlety worth noting

The bundled network normalizes lon === 180 vertices to -180, so a trans-Pacific route can pass through a vertex sitting exactly on the dateline. splitAtAntimeridian works in unwrapped space and assigns each sub-line a 360°-panel offset, so boundary-coincident vertices are handled as crossings (and de-duplicated) rather than being dropped — verified against Yokohama → LA (vertex on 180) and Sydney → Vancouver (interpolated crossing at lat 0).

Validation

All steps CI runs, from a clean tree:

  • npm ci
  • npm run lint
  • npm run format:check
  • npm run build
  • npm test ✅ (50 tests; 6 new covering unwrap continuity, split cut points at ±180 with continuous latitude, all coords within ±180, non-crossing routes unchanged, seaRouteMulti split, and alternatives staying LineString)

Also verified end-to-end against the built dist (CJS + ESM) that unwrap removes all dateline jumps and split produces valid in-range MultiLineString geometry with length preserved.

Closes #9

@mayurrawte
mayurrawte force-pushed the feat/issue-9-antimeridian branch from f50d6e9 to 8986583 Compare July 3, 2026 07:57
Routes that cross the ±180° antimeridian (e.g. Yokohama -> LA) come back
wrapped to [-180, 180], so a segment jumps from +179 to -179 and map renderers
draw a straight streak across the whole map.

Add an `antimeridian` option to `seaRoute` and `seaRouteMulti`:
- 'unwrap' -> one continuous LineString, longitudes shifted by multiples of
  360° so the line never jumps the dateline (may exceed ±180°).
- 'split'  -> a MultiLineString cut at ±180°, keeping every coordinate in
  range (RFC 7946-friendly).

The default is unchanged (wrapped LineString), so this is non-breaking. Return
types are narrowed by overload: 'split' yields a SeaRouteMultiFeature. The
split routine works on unwrapped coordinates and handles vertices that sit
exactly on the dateline (the bundled network normalizes ±180° vertices).

New exports: Antimeridian, SeaRouteMultiFeature.
@mayurrawte
mayurrawte force-pushed the feat/issue-9-antimeridian branch from 8986583 to f5453aa Compare July 3, 2026 08:28
@mayurrawte
mayurrawte merged commit c888219 into main Jul 3, 2026
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.

Add antimeridian output option so map consumers don't hit the straight-line bug

1 participant