offset method
Vincenty inverse calculation
More on Wikipedia
Implementation
@override
LatLng offset(
final LatLng from, final double distanceInMeter, final double bearing) {
final equatorialRadius = equatorRadius;
final latitude = from.latitudeInRad;
final longitude = from.longitudeInRad;
final alpha1 = degToRadian(bearing);
final sinAlpha1 = math.sin(alpha1);
final cosAlpha1 = math.cos(alpha1);
final tanU1 = (1 - flattening) * math.tan(latitude);
final cosU1 = 1 / math.sqrt((1 + tanU1 * tanU1));
final sinU1 = tanU1 * cosU1;
final sigma1 = math.atan2(tanU1, cosAlpha1);
final sinAlpha = cosU1 * sinAlpha1;
final cosSqAlpha = 1 - sinAlpha * sinAlpha;
final dfUSq = cosSqAlpha *
(equatorialRadius * equatorialRadius - polarRadius * polarRadius) /
(polarRadius * polarRadius);
final a = 1 +
dfUSq / 16384 * (4096 + dfUSq * (-768 + dfUSq * (320 - 175 * dfUSq)));
final b = dfUSq / 1024 * (256 + dfUSq * (-128 + dfUSq * (74 - 47 * dfUSq)));
var sigma = distanceInMeter / (polarRadius * a);
var sigmaP = 2 * pi;
var sinSigma = 0.0;
var cosSigma = 0.0;
var cos2SigmaM = 0.0;
double deltaSigma;
var maxIterations = 200;
do {
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 = distanceInMeter / (polarRadius * a) + deltaSigma;
} while ((sigma - sigmaP).abs() > 1e-12 && --maxIterations > 0);
if (maxIterations == 0) {
throw StateError('offset calculation faild to converge!');
}
final tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
final lat2 = math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
(1 - flattening) * math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
final lambda = math.atan2(
sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
final c =
flattening / 16 * cosSqAlpha * (4 + flattening * (4 - 3 * cosSqAlpha));
final l = lambda -
(1 - c) *
flattening *
sinAlpha *
(sigma +
c *
sinSigma *
(cos2SigmaM +
c * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
var lon2 = longitude + l;
// print("LA ${radianToDeg(lat2)}, LO ${radianToDeg(lon2)}");
if (lon2 > pi) {
lon2 = lon2 - 2 * pi;
}
if (lon2 < -1 * pi) {
lon2 = lon2 + 2 * pi;
}
return LatLng(radianToDeg(lat2), radianToDeg(lon2));
}