s2-tools
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
87 lines • 3.05 kB
JavaScript
import { degToRad, radToDeg } from '../geometry';
/**
* # Orthodrome
*
* ## Description
* Represents an orthodrome, which is the shortest path between two points on a sphere.
* [Learn more here](http://www.movable-type.co.uk/scripts/latlong.html)
*
* ## Usage
* ```ts
* import { Orthodrome } from 's2-tools'
*
* // starting at lon-lat (-60, -40) and ending at (20, 10)
* const orthodrome = new Orthodrome(-60, -40, 20, 10);
* // { x: -39.13793657428956, y: -33.72852197561652 }
* const intermediatePoint = orthodrome.intermediatePoint(0.2);
* // Distance in KM: 1.5514126949321814
* const distance = orthodrome.distanceTo();
*/
export class Orthodrome {
/** start longitude */
lon1;
/** start latitude */
lat1;
/** end longitude */
lon2;
/** end latitude */
lat2;
/** distance property */
a;
/** distance property */
dist;
/**
* @param startLon - start longitude
* @param startLat - start latitude
* @param endLon - end longitude
* @param endLat - end latitude
*/
constructor(startLon, startLat, endLon, endLat) {
const { sin, cos, atan2, sqrt } = Math;
const lon1 = (this.lon1 = degToRad(startLon));
const lat1 = (this.lat1 = degToRad(startLat));
const lon2 = (this.lon2 = degToRad(endLon));
const lat2 = (this.lat2 = degToRad(endLat));
const dLat = lat2 - lat1;
const dLon = lon2 - lon1;
const a = (this.a =
sin(dLat / 2) * sin(dLat / 2) + cos(lat1) * cos(lat2) * sin(dLon / 2) * sin(dLon / 2));
this.dist = 2 * atan2(sqrt(a), sqrt(1 - a));
}
/**
* input t 0->1. Find a point along the orthodrome.
* @param t - distance along the orthodrome to find
* @returns [lon, lat]
*/
intermediatePoint(t) {
const { lon1, lon2, lat1, lat2, dist } = this;
const { sin, cos, atan2, sqrt } = Math;
// check corner cases first
if (t === 0)
return { x: radToDeg(lon1), y: radToDeg(lat1) };
else if (t === 1)
return { x: radToDeg(lon2), y: radToDeg(lat2) };
// check if points are equal
else if (lon1 === lon2 && lat1 === lat2)
return { x: radToDeg(lon1), y: radToDeg(lat1) };
const A = sin((1 - t) * dist) / sin(dist);
const B = sin(t * dist) / sin(dist);
const x = A * cos(lat1) * cos(lon1) + B * cos(lat2) * cos(lon2);
const y = A * cos(lat1) * sin(lon1) + B * cos(lat2) * sin(lon2);
const z = A * sin(lat1) + B * sin(lat2);
const lat = atan2(z, sqrt(x * x + y * y));
const lon = atan2(y, x);
return { x: radToDeg(lon), y: radToDeg(lat) };
}
/**
* Finds the distance between the two points in kilometers
* projected normalized (0->1)
* @returns - total distance between the two points
*/
distanceTo() {
const { a } = this;
const { atan2, sqrt } = Math;
return 2 * atan2(sqrt(a), sqrt(1 - a));
}
}
//# sourceMappingURL=orthodrome.js.map