mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
71 lines
2.0 KiB
JavaScript
71 lines
2.0 KiB
JavaScript
/**
|
|
* Canonical geographic point used by shared spatial utilities.
|
|
*
|
|
* @typedef {{lat: number, lon: number}} GeoPoint
|
|
*/
|
|
|
|
/** IUGG mean spherical Earth radius, in kilometres. */
|
|
export const EARTH_RADIUS_KM = 6371.0088;
|
|
|
|
const DEGREES_TO_RADIANS = Math.PI / 180;
|
|
|
|
/**
|
|
* Whether a value is a canonical, finite WGS84-style point in degrees.
|
|
* Longitudes are not implicitly wrapped because an out-of-range value usually
|
|
* indicates a broken coordinate contract at the caller.
|
|
*
|
|
* @param {*} point
|
|
* @returns {point is GeoPoint}
|
|
*/
|
|
export function isGeoPoint(point) {
|
|
return (
|
|
Number.isFinite(point?.lat) &&
|
|
point.lat >= -90 &&
|
|
point.lat <= 90 &&
|
|
Number.isFinite(point?.lon) &&
|
|
point.lon >= -180 &&
|
|
point.lon <= 180
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Great-circle distance in kilometres between two `{ lat, lon }` points.
|
|
*
|
|
* `{ lat, lon }` is the canonical shared coordinate representation. Invalid,
|
|
* missing, non-finite, or out-of-range coordinates return `Infinity`, which
|
|
* keeps invalid points out of threshold and nearest-neighbour selections.
|
|
*
|
|
* @param {GeoPoint} from
|
|
* @param {GeoPoint} to
|
|
* @returns {number}
|
|
*/
|
|
export function greatCircleKm(from, to) {
|
|
if (!isGeoPoint(from) || !isGeoPoint(to)) return Number.POSITIVE_INFINITY;
|
|
|
|
const latitude1 = from.lat * DEGREES_TO_RADIANS;
|
|
const latitude2 = to.lat * DEGREES_TO_RADIANS;
|
|
const latitudeDelta = (to.lat - from.lat) * DEGREES_TO_RADIANS;
|
|
const longitudeDelta = (to.lon - from.lon) * DEGREES_TO_RADIANS;
|
|
const haversine =
|
|
Math.sin(latitudeDelta / 2) ** 2 +
|
|
Math.cos(latitude1) *
|
|
Math.cos(latitude2) *
|
|
Math.sin(longitudeDelta / 2) ** 2;
|
|
const bounded = Math.min(1, Math.max(0, haversine));
|
|
return (
|
|
2 * EARTH_RADIUS_KM * Math.atan2(Math.sqrt(bounded), Math.sqrt(1 - bounded))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Great-circle distance in metres, with the same point and invalid-input
|
|
* contract as {@link greatCircleKm}.
|
|
*
|
|
* @param {GeoPoint} from
|
|
* @param {GeoPoint} to
|
|
* @returns {number}
|
|
*/
|
|
export function greatCircleMeters(from, to) {
|
|
return greatCircleKm(from, to) * 1000;
|
|
}
|