-
-
Save mathiasbynens/354587 to your computer and use it in GitHub Desktop.
/*! | |
* JavaScript function to calculate the destination point given start point latitude / longitude (numeric degrees), bearing (numeric degrees) and distance (in m). | |
* | |
* Original scripts by Chris Veness | |
* Taken from http://movable-type.co.uk/scripts/latlong-vincenty-direct.html and optimized / cleaned up by Mathias Bynens <http://mathiasbynens.be/> | |
* Based on the Vincenty direct formula by T. Vincenty, “Direct and Inverse Solutions of Geodesics on the Ellipsoid with application of nested equations”, Survey Review, vol XXII no 176, 1975 <http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf> | |
*/ | |
function toRad(n) { | |
return n * Math.PI / 180; | |
}; | |
function toDeg(n) { | |
return n * 180 / Math.PI; | |
}; | |
function destVincenty(lat1, lon1, brng, dist) { | |
var a = 6378137, | |
b = 6356752.3142, | |
f = 1 / 298.257223563, // WGS-84 ellipsiod | |
s = dist, | |
alpha1 = toRad(brng), | |
sinAlpha1 = Math.sin(alpha1), | |
cosAlpha1 = Math.cos(alpha1), | |
tanU1 = (1 - f) * Math.tan(toRad(lat1)), | |
cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1, | |
sigma1 = Math.atan2(tanU1, cosAlpha1), | |
sinAlpha = cosU1 * sinAlpha1, | |
cosSqAlpha = 1 - sinAlpha * sinAlpha, | |
uSq = cosSqAlpha * (a * a - b * b) / (b * b), | |
A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))), | |
B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))), | |
sigma = s / (b * A), | |
sigmaP = 2 * Math.PI; | |
while (Math.abs(sigma - sigmaP) > 1e-12) { | |
var cos2SigmaM = Math.cos(2 * sigma1 + sigma), | |
sinSigma = Math.sin(sigma), | |
cosSigma = Math.cos(sigma), | |
deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM))); | |
sigmaP = sigma; | |
sigma = s / (b * A) + deltaSigma; | |
}; | |
var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1, | |
lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1, (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp)), | |
lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1), | |
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)), | |
L = lambda - (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM))), | |
revAz = Math.atan2(sinAlpha, -tmp); // final bearing | |
return new LatLon(toDeg(lat2), lon1 + toDeg(L)); | |
}; |
/*! | |
* JavaScript function to calculate the geodetic distance between two points specified by latitude/longitude using the Vincenty inverse formula for ellipsoids. | |
* | |
* Original scripts by Chris Veness | |
* Taken from http://movable-type.co.uk/scripts/latlong-vincenty.html and optimized / cleaned up by Mathias Bynens <http://mathiasbynens.be/> | |
* Based on the Vincenty direct formula by T. Vincenty, “Direct and Inverse Solutions of Geodesics on the Ellipsoid with application of nested equations”, Survey Review, vol XXII no 176, 1975 <http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf> | |
* | |
* @param {Number} lat1, lon1: first point in decimal degrees | |
* @param {Number} lat2, lon2: second point in decimal degrees | |
* @returns {Number} distance in metres between points | |
*/ | |
function toRad(n) { | |
return n * Math.PI / 180; | |
}; | |
function distVincenty(lat1, lon1, lat2, lon2) { | |
var a = 6378137, | |
b = 6356752.3142, | |
f = 1 / 298.257223563, // WGS-84 ellipsoid params | |
L = toRad(lon2-lon1), | |
U1 = Math.atan((1 - f) * Math.tan(toRad(lat1))), | |
U2 = Math.atan((1 - f) * Math.tan(toRad(lat2))), | |
sinU1 = Math.sin(U1), | |
cosU1 = Math.cos(U1), | |
sinU2 = Math.sin(U2), | |
cosU2 = Math.cos(U2), | |
lambda = L, | |
lambdaP, | |
iterLimit = 100; | |
do { | |
var sinLambda = Math.sin(lambda), | |
cosLambda = Math.cos(lambda), | |
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)); | |
if (0 === sinSigma) { | |
return 0; // co-incident points | |
}; | |
var cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda, | |
sigma = Math.atan2(sinSigma, cosSigma), | |
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma, | |
cosSqAlpha = 1 - sinAlpha * sinAlpha, | |
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha, | |
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)); | |
if (isNaN(cos2SigmaM)) { | |
cos2SigmaM = 0; // equatorial line: cosSqAlpha = 0 (§6) | |
}; | |
lambdaP = lambda; | |
lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM))); | |
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0); | |
if (!iterLimit) { | |
return NaN; // formula failed to converge | |
}; | |
var uSq = cosSqAlpha * (a * a - b * b) / (b * b), | |
A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))), | |
B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))), | |
deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM))), | |
s = b * A * (sigma - deltaSigma); | |
return s.toFixed(3); // round to 1mm precision | |
}; |
Where I can find
LatLon
function?
I ran the code in the browser console and it was throwing that error
I found you can just change that line to
return {
lat: toDeg(lat2),
lng: lon1 + toDeg(L),
};
From this: https://www.movable-type.co.uk/scripts/latlong.html
toRad() is not a function
bruh this is broken
The original source code is broken. toRad() is not a function.
Here is an alternative implementation that worked for me:
function destinationPoint(latitude, longitude, bearing, distance) {
const radius = 6371e3; // Earth's radius in meters
const lat1 = toRadians(latitude);
const lon1 = toRadians(longitude);
const bearingRadians = toRadians(bearing);
const sinLat1 = Math.sin(lat1);
const cosLat1 = Math.cos(lat1);
const sinDistanceOverRadius = Math.sin(distance / radius);
const cosDistanceOverRadius = Math.cos(distance / radius);
const sinBearing = Math.sin(bearingRadians);
const cosBearing = Math.cos(bearingRadians);
const lat2 = Math.asin(sinLat1 * cosDistanceOverRadius +
cosLat1 * sinDistanceOverRadius * cosBearing);
const lon2 = lon1 + Math.atan2(sinBearing * sinDistanceOverRadius * cosLat1,
cosDistanceOverRadius - sinLat1 * Math.sin(lat2));
return {
latitude: toDegrees(lat2),
longitude: toDegrees(lon2),
};
}
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
function toDegrees(radians) {
return radians * 180 / Math.PI;
}
Where I can find
LatLon
function?I ran the code in the browser console and it was throwing that error