computeOffsetOrigin static method
Returns the origin when provided with a destination to, distance in
meters, and original heading. Returns null when no solution exists.
Implementation
static Point<double>? computeOffsetOrigin(
Point<double> to, double distance, double heading) {
distance /= MathUtils.earthRadius;
heading = toRadians(heading);
// http://lists.maptools.org/pipermail/proj/2008-October/003939.html
final n1 = cos(distance);
final n2 = sin(distance) * cos(heading);
final n3 = sin(distance) * sin(heading);
final n4 = sin(toRadians(to.x));
// There are two solutions for b. b = n2 * n4 +/- sqrt(), one solution
// results in the latitude outside the [-90, 90] range. We first try one
// solution and back off to the other if we are outside that range.
final n12 = n1 * n1;
final discriminant = n2 * n2 * n12 + n12 * n12 - n12 * n4 * n4;
// No real solution which would make sense in lat-lng space.
if (discriminant < 0) {
return null;
}
double b = n2 * n4 + sqrt(discriminant);
b /= n1 * n1 + n2 * n2;
final a = (n4 - n2 * b) / n1;
double fromLatRadians = atan2(a, b);
if (fromLatRadians < -pi / 2 || fromLatRadians > pi / 2) {
b = n2 * n4 - sqrt(discriminant);
b /= n1 * n1 + n2 * n2;
fromLatRadians = atan2(a, b);
}
// No solution which would make sense in lat-lng space.
if (fromLatRadians < -pi / 2 || fromLatRadians > pi / 2) {
return null;
}
final fromLngRadians = toRadians(to.y) -
atan2(n3, n1 * cos(fromLatRadians) - n2 * sin(fromLatRadians));
return Point(toDegrees(fromLatRadians), toDegrees(fromLngRadians));
}