87 lines
3.6 KiB
JavaScript
Executable File
87 lines
3.6 KiB
JavaScript
Executable File
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
// https://en.wikipedia.org/wiki/Rhumb_line
|
||
var helpers_1 = require("@turf/helpers");
|
||
var invariant_1 = require("@turf/invariant");
|
||
/**
|
||
* Calculates the distance along a rhumb line between two {@link Point|points} in degrees, radians,
|
||
* miles, or kilometers.
|
||
*
|
||
* @name rhumbDistance
|
||
* @param {Coord} from origin point
|
||
* @param {Coord} to destination point
|
||
* @param {Object} [options] Optional parameters
|
||
* @param {string} [options.units="kilometers"] can be degrees, radians, miles, or kilometers
|
||
* @returns {number} distance between the two points
|
||
* @example
|
||
* var from = turf.point([-75.343, 39.984]);
|
||
* var to = turf.point([-75.534, 39.123]);
|
||
* var options = {units: 'miles'};
|
||
*
|
||
* var distance = turf.rhumbDistance(from, to, options);
|
||
*
|
||
* //addToMap
|
||
* var addToMap = [from, to];
|
||
* from.properties.distance = distance;
|
||
* to.properties.distance = distance;
|
||
*/
|
||
function rhumbDistance(from, to, options) {
|
||
if (options === void 0) { options = {}; }
|
||
var origin = invariant_1.getCoord(from);
|
||
var destination = invariant_1.getCoord(to);
|
||
// compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)
|
||
// solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678
|
||
destination[0] +=
|
||
destination[0] - origin[0] > 180
|
||
? -360
|
||
: origin[0] - destination[0] > 180
|
||
? 360
|
||
: 0;
|
||
var distanceInMeters = calculateRhumbDistance(origin, destination);
|
||
var distance = helpers_1.convertLength(distanceInMeters, "meters", options.units);
|
||
return distance;
|
||
}
|
||
/**
|
||
* Returns the distance travelling from ‘this’ point to destination point along a rhumb line.
|
||
* Adapted from Geodesy: https://github.com/chrisveness/geodesy/blob/master/latlon-spherical.js
|
||
*
|
||
* @private
|
||
* @param {Array<number>} origin point.
|
||
* @param {Array<number>} destination point.
|
||
* @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
|
||
* @returns {number} Distance in km between this point and destination point (same units as radius).
|
||
*
|
||
* @example
|
||
* var p1 = new LatLon(51.127, 1.338);
|
||
* var p2 = new LatLon(50.964, 1.853);
|
||
* var d = p1.distanceTo(p2); // 40.31 km
|
||
*/
|
||
function calculateRhumbDistance(origin, destination, radius) {
|
||
// φ => phi
|
||
// λ => lambda
|
||
// ψ => psi
|
||
// Δ => Delta
|
||
// δ => delta
|
||
// θ => theta
|
||
radius = radius === undefined ? helpers_1.earthRadius : Number(radius);
|
||
// see www.edwilliams.org/avform.htm#Rhumb
|
||
var R = radius;
|
||
var phi1 = (origin[1] * Math.PI) / 180;
|
||
var phi2 = (destination[1] * Math.PI) / 180;
|
||
var DeltaPhi = phi2 - phi1;
|
||
var DeltaLambda = (Math.abs(destination[0] - origin[0]) * Math.PI) / 180;
|
||
// if dLon over 180° take shorter rhumb line across the anti-meridian:
|
||
if (DeltaLambda > Math.PI) {
|
||
DeltaLambda -= 2 * Math.PI;
|
||
}
|
||
// on Mercator projection, longitude distances shrink by latitude; q is the 'stretch factor'
|
||
// q becomes ill-conditioned along E-W line (0/0); use empirical tolerance to avoid it
|
||
var DeltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4));
|
||
var q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);
|
||
// distance is pythagoras on 'stretched' Mercator projection
|
||
var delta = Math.sqrt(DeltaPhi * DeltaPhi + q * q * DeltaLambda * DeltaLambda); // angular distance in radians
|
||
var dist = delta * R;
|
||
return dist;
|
||
}
|
||
exports.default = rhumbDistance;
|