computeOffsetOrigin static method

Point<num>? computeOffsetOrigin(
  1. Point<num> to,
  2. num distance,
  3. num 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, num distance, num heading) {
  distance /= MathUtils.earthRadius;
  heading = toRadians(heading);
  // http://lists.maptools.org/pipermail/proj/2008-October/003939.html
  num n1 = cos(distance);
  num n2 = sin(distance) * cos(heading);
  num n3 = sin(distance) * sin(heading);
  num 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.
  num n12 = n1 * n1;
  num discriminant = n2 * n2 * n12 + n12 * n12 - n12 * n4 * n4;

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

  num b = n2 * n4 + sqrt(discriminant);
  b /= n1 * n1 + n2 * n2;
  num a = (n4 - n2 * b) / n1;
  num 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;
  }

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