JavaScript中計算方位角/投影距離/目標點算法:
let GeoUtil = (() => {
let toRadian = Math.PI / 180.0;
let radius_km = 6371;
/**
* Returns the distance from this point to the supplied point, in km
* (using Haversine formula)
*
* from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine",
* Sky and Telescope, vol 68, no 2, 1984
*
* @param {LatLon} start: Latitude/longitude of destination point
* @param {Number} [precision=4]: no of significant digits to use for returned value
* @returns {Number} Distance in km between this point and destination point
*/
function distance(start, end) {
var R = radius_km;
var lat1 = start[0] * toRadian, lon1 = start[1] * toRadian;
var lat2 = end[0] * toRadian, lon2 = end[1] * toRadian;
var dLat = lat2 - lat1;
var dLon = lon2 - lon1;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1) * Math.cos(lat2) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
}
/**
* Returns the (initial) bearing from this point to the supplied point, in degrees
* see http://williams.best.vwh.net/avform.htm#Crs
*
* @param {LatLon} point: Latitude/longitude of destination point
* @returns {Number} Initial bearing in degrees from North
*/
function bearing(start, end) {
var lat1 = start[0] * toRadian, lat2 = end[0] * toRadian;
var dLon = (end[1] - start[1]) * toRadian;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
var brng = Math.atan2(y, x) / toRadian;
return (brng + 360) % 360;
}
/**
* Returns the destination point from this point having travelled the given distance (in km) on the
* given initial bearing (bearing may vary before destination is reached)
*
* see http://williams.best.vwh.net/avform.htm#LL
*
* @param {Number} brng: Initial bearing in degrees
* @param {Number} dist: Distance in km
* @returns {LatLon} Destination point
*/
function destination(start, brng, dist) {
dist = dist / 6371; // convert dist to angular distance in radians
brng = brng * toRadian; //
var lat1 = start[0] * toRadian, lon1 = start[1] * toRadian;
var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
var lng2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) * Math.sin(lat2));
lng2 = (lng2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180...+180
return [lat2 / toRadian, lng2 / toRadian];
}
return {
distance: distance,
bearing: bearing,
destination: destination
};
})();