Skip to content

Bug: CoordinateUtils.coordinateString misclassifies the equator (0° lat) as 'S' and the prime meridian (0° lon) as 'W' #452

Description

@kevinelliott

Summary

CoordinateUtils.coordinateString decides the hemisphere with a strict > 0 test, so any coordinate whose latitude is exactly 0 is labeled S (south) and any whose longitude is exactly 0 is labeled W (west). The equator and the prime meridian are mathematically neither — but using >= 0 would at least label them N / E instead of the more wrong-looking opposite hemisphere. (The convention used elsewhere in the codebase — CoordinateUtils.getDirection — also treats N/E as the positive direction, so the inversion here is asymmetric.)

Affected code

lib/utils/coordinate_utils.ts:75-82

public static coordinateString(coords: {
  latitude: number;
  longitude: number;
}): string {
  const latDir = coords.latitude > 0 ? 'N' : 'S';
  const lonDir = coords.longitude > 0 ? 'E' : 'W';
  return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
}

Reproduction

CoordinateUtils.coordinateString({ latitude: 0, longitude: 0 });
// Returns "0.000 S, 0.000 W"  (Null Island claims the southern hemisphere)

CoordinateUtils.coordinateString({ latitude: 0, longitude: -77.0 });
// Returns "0.000 S, 77.000 W" instead of "0.000 N, 77.000 W"

Real-world impact is small (aircraft rarely sit on the equator or prime meridian at decoding time) but the output is also used directly inside RouteUtils.waypointToString for any waypoint that happens to lie on either axis, so the wrong hemisphere can leak into formatted route strings.

Suggested fix

Switch both comparisons to >= 0:

const latDir = coords.latitude >= 0 ? 'N' : 'S';
const lonDir = coords.longitude >= 0 ? 'E' : 'W';

A test for the equator/prime-meridian case in coordinate_utils.test.ts (coordinateString block) would make the intent explicit — the existing tests only cover strictly positive and strictly negative cases.

Bonus: silent NaN/undefined output

coordinateString does not guard against NaN the way ResultFormatter.position does, so a caller that bypasses position() (or that passes a Waypoint with latitude: NaN through RouteUtils.waypointToString) will get "NaN S, NaN W". Worth deciding whether to early-return '' for non-finite inputs in the same change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions