offset method

  1. @override
LatLng offset(
  1. dynamic from,
  2. double? distanceInMeter,
  3. double bearing
)
override

Implementation

@override
LatLng offset(dynamic from, double? distanceInMeter, double bearing) {
  final latlng = LatLng.from(from);

  final latInRad = latlng.latitudeInRad;
  final lngInRad = latlng.longitudeInRad;

  double alpha1 = degToRadian(bearing);
  double sinAlpha1 = sin(alpha1);
  double cosAlpha1 = cos(alpha1);

  double tanU1 = (1 - FLATTENING) * tan(latInRad);
  double cosU1 = 1 / sqrt((1 + tanU1 * tanU1));
  double sinU1 = tanU1 * cosU1;

  double sigma1 = atan2(tanU1, cosAlpha1);
  double sinAlpha = cosU1 * sinAlpha1;
  double cosSqAlpha = 1 - sinAlpha * sinAlpha;
  double dfUSq = cosSqAlpha *
      (EQUATOR_RADIUS * EQUATOR_RADIUS - POLAR_RADIUS * POLAR_RADIUS) /
      (POLAR_RADIUS * POLAR_RADIUS);

  double a = 1 +
      dfUSq / 16384 * (4096 + dfUSq * (-768 + dfUSq * (320 - 175 * dfUSq)));
  double b =
      dfUSq / 1024 * (256 + dfUSq * (-128 + dfUSq * (74 - 47 * dfUSq)));

  double sigma = distanceInMeter! / (POLAR_RADIUS * a);
  double sigmaP = 2 * PI;

  double sinSigma = 0.0;
  double cosSigma = 0.0;
  double cos2SigmaM = 0.0;
  double deltaSigma;
  int maxIterations = 200;

  do {
    cos2SigmaM = cos(2 * sigma1 + sigma);
    sinSigma = sin(sigma);
    cosSigma = 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 / (POLAR_RADIUS * a) + deltaSigma;
  } while ((sigma - sigmaP).abs() > 1e-12 && --maxIterations > 0);

  if (maxIterations == 0) {
    throw StateError("offset calculation faild to converge!");
  }

  double tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
  double latitude = atan2(
    sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
    (1 - FLATTENING) * sqrt(sinAlpha * sinAlpha + tmp * tmp),
  );

  double lambda = atan2(
      sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
  double c =
      FLATTENING / 16 * cosSqAlpha * (4 + FLATTENING * (4 - 3 * cosSqAlpha));
  double l = lambda -
      (1 - c) *
          FLATTENING *
          sinAlpha *
          (sigma +
              c *
                  sinSigma *
                  (cos2SigmaM +
                      c * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

  double longitude = lngInRad + l;

  if (longitude > PI) {
    longitude = longitude - 2 * PI;
  }

  if (longitude < -1 * PI) {
    longitude = longitude + 2 * PI;
  }

  return LatLng(radianToDeg(latitude), radianToDeg(longitude));
}