computeOffsetOrigin static method

Point<num>? computeOffsetOrigin(
  1. Point<num> to,
  2. double distance,
  3. double heading
)

Returns the location of origin when provided with a Point destination, meters travelled and original heading. Headings are expressed in degrees clockwise from North. This function returns null when no solution is available.

to The destination Point.

distance The distance travelled, in meters.

heading The heading in degrees clockwise from north.

Implementation

static Point? computeOffsetOrigin(Point to, double distance, double heading) {
  distance /= MathUtils.earthRadius;
  heading = toRadians(heading);
  // http://lists.maptools.org/pipermail/proj/2008-October/003939.html
  double n1 = cos(distance);
  double n2 = sin(distance) * cos(heading);
  double n3 = sin(distance) * sin(heading);
  double n4 = sin(toRadians(to.x));
  // There are two solutions for b. b = n2 * n4 +/- sqrt(), one solution results
  // in the x outside the [-90, 90] range. We first try one solution and
  // back off to the other if we are outside that range.
  double n12 = n1 * n1;
  double discriminant = n2 * n2 * n12 + n12 * n12 - n12 * n4 * n4;

  // No real solution which would make sense in Point-space.
  if (discriminant < 0) {
    return null;
  }

  double b = n2 * n4 + sqrt(discriminant);
  b /= n1 * n1 + n2 * n2;
  double 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 Point-space.
  if (fromLatRadians < -pi / 2 || fromLatRadians > pi / 2) {
    return null;
  }

  double fromLngRadians = toRadians(to.y) -
      atan2(n3, n1 * cos(fromLatRadians) - n2 * sin(fromLatRadians));
  return Point(toDegrees(fromLatRadians), toDegrees(fromLngRadians));
}