s-haversine
Version:
Get distance between any two latitute/longitude coordinates
72 lines (55 loc) • 1.72 kB
text/typescript
/**
* [Latitude, Longitude]
*/
export type Coords = [number, number];
/**
* Convert degrees to radians
*/
export function degreesToRadians(deg: number) {
return deg * (Math.PI / 180);
}
/**
* Convert dms (degrees/minutes/seconds) string to decimal degrees
* toDecimal(`40 20 50W`) => -40.34722
* toDecimal(`40°20'50" S`) => -40.34722
*/
export function dmsToDecimal(str: string) {
const lastChar = str.slice(-1).toLowerCase();
let negative = false;
// south and west => negative
if (lastChar === 'w' || lastChar === 's') negative = true;
// convert strings to numbers
const values = str
.split(/[^0-9.]/)
.filter((x) => x !== '') // remove empty values
.map((x) => parseFloat(x));
// make sure array has length 3
for (let i = 0; i < 3; i++) {
values[i] = values[i] || 0;
}
const result = values[0] + (values[1] / 60) + (values[2] / 3600);
return negative ? -result : result;
}
const haversine = {
/**
* Configurable earthRadius (in meters)
*/
earthRadius: 6371000,
/**
* Get distance between two points
*/
distance(coords1: Coords, coords2: Coords) {
const [lat1, lon1] = coords1;
const [lat2, lon2] = coords2;
const latitudeDifference = degreesToRadians(lat2 - lat1);
const logitudeDifference = degreesToRadians(lon2 - lon1);
const n =
Math.sin(latitudeDifference / 2) * Math.sin(latitudeDifference / 2) +
Math.cos(degreesToRadians(lat1)) * Math.cos(degreesToRadians(lat2)) *
Math.sin(logitudeDifference / 2) * Math.sin(logitudeDifference / 2);
const distance = 2 * Math.atan2(Math.sqrt(n), Math.sqrt(1 - n));
return this.earthRadius * distance;
},
dmsToDecimal
};
export default haversine;