From 2c7d07162b9a7bd0186e045b678272e53bd991a7 Mon Sep 17 00:00:00 2001 From: JSap0914 Date: Sat, 27 Jun 2026 18:46:40 +0900 Subject: [PATCH] fix(rhumb-bearing): return NaN for coincident points When start and end points are identical, rhumbBearing() was returning 0 (north) because Math.atan2(0, 0) === 0. This is misleading since no bearing can be defined for a zero-length segment. The Geodesy library (which this implementation is adapted from) explicitly guards for this case and returns NaN. Align turf's behaviour accordingly. Closes #2478 --- packages/turf-rhumb-bearing/index.ts | 4 ++++ packages/turf-rhumb-bearing/test.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/packages/turf-rhumb-bearing/index.ts b/packages/turf-rhumb-bearing/index.ts index c3d48ccc9f..f821a31d11 100644 --- a/packages/turf-rhumb-bearing/index.ts +++ b/packages/turf-rhumb-bearing/index.ts @@ -54,6 +54,10 @@ function rhumbBearing( * var d = p1.rhumbBearingTo(p2); // 116.7 m */ function calculateRhumbBearing(from: number[], to: number[]) { + // Coincident points have no defined bearing (matches Geodesy reference impl) + if (from[0] === to[0] && from[1] === to[1]) { + return NaN; + } // φ => phi // Δλ => deltaLambda // Δψ => deltaPsi diff --git a/packages/turf-rhumb-bearing/test.ts b/packages/turf-rhumb-bearing/test.ts index 377a0c9a41..a9f40767fc 100644 --- a/packages/turf-rhumb-bearing/test.ts +++ b/packages/turf-rhumb-bearing/test.ts @@ -46,6 +46,18 @@ test("bearing", (t) => { ); }); + // Coincident points have no defined bearing — must return NaN, not 0 + // Regression test for https://github.com/Turfjs/turf/issues/2478 + const coincident = point([5, 5]); + t.ok( + isNaN(rhumbBearing(coincident, coincident)), + "coincident points return NaN" + ); + t.ok( + isNaN(rhumbBearing(coincident, coincident, { final: true })), + "coincident points return NaN (final bearing)" + ); + t.throws(() => { rhumbBearing(point([12, -54]), "point"); }, "invalid point");