/// <summary> /// Performs the inverse transfrom from a single coordinate of linear units to the same coordinate in geodetic units /// </summary> /// <param name="xy">The double linear input x and y values organized into a 1 dimensional array</param> /// <param name="lp">The double geodetic output lambda and phi values organized into a 1 dimensional array</param> protected override void EllipticalInverse(double[] xy, double[] lp) { double arg = _ml0 + xy[Y] / K0; lp[Phi] = MeridionalDistance.AngularDistance(_ml0 + xy[Y] / K0, Es, _en); if (Math.Abs(lp[Phi]) >= HalfPi) { lp[Phi] = xy[Y] < 0 ? -HalfPi : HalfPi; lp[Lambda] = 0; } else { double sinphi = Math.Sin(lp[Phi]); double cosphi = Math.Cos(lp[Phi]); double t = Math.Abs(cosphi) > 1e-10 ? sinphi / cosphi : 0; double n = _esp * cosphi * cosphi; double con; double d = xy[X] * Math.Sqrt(con = 1 - Es * sinphi * sinphi) / K0; con *= t; t *= t; double ds = d * d; lp[Phi] -= (con * ds / (1 - Es)) * FC2 * (1 - ds * FC4 * (5 + t * (3 - 9 * n) + n * (1 - 4 * n) - ds * FC6 * (61 + t * (90 - 252 * n + 45 * t) + 46 * n - ds * FC8 * (1385 + t * (3633 + t * (4095 + 1574 * t)))))); lp[Lambda] = d * (FC1 - ds * FC3 * (1 + 2 * t + n - ds * FC5 * (5 + t * (28 + 24 * t + 8 * n) + 6 * n - ds * FC7 * (61 + t * (662 + t * (1320 + 720 * t)))))) / cosphi; } }
/// <summary> /// Initializes the transform using the parameters from the specified coordinate system information /// </summary> /// <param name="projInfo">A ProjectionInfo class contains all the standard and custom parameters needed to initialize this transform</param> protected override void OnInit(ProjectionInfo projInfo) { if (Es != 0) { _en = MeridionalDistance.GetEN(Es); if (_en == null) { throw new ProjectionException(0); } _ml0 = MeridionalDistance.MeridionalLength(Phi0, Math.Sin(Phi0), Math.Cos(Phi0), _en); _esp = Es / (1 - Es); } else { _esp = K0; _ml0 = .5 * _esp; } }
/// <summary> /// The forward transform where the spheroidal model of the earth has a flattening factor, /// matching more closely with the oblique spheroid of the actual earth /// </summary> /// <param name="lp">The double values for geodetic lambda and phi organized into a one dimensional array</param> /// <param name="xy">The double values for linear x and y organized into a one dimensional array</param> protected override void EllipticalForward(double[] lp, double[] xy) { /* * Fail if our longitude is more than 90 degrees from the * central meridian since the results are essentially garbage. * Is error -20 really an appropriate return value? * * http://trac.osgeo.org/proj/ticket/5 */ if (lp[Lambda] < -HalfPi || lp[Lambda] > HalfPi) { xy[X] = double.NaN; xy[Y] = double.NaN; //xy[X] = double.PositiveInfinity; //xy[Y] = double.PositiveInfinity; //throw new ProjectionException(14); } else { double sinphi = Math.Sin(lp[Phi]); double cosphi = Math.Cos(lp[Phi]); double t = Math.Abs(cosphi) > 1E-10 ? sinphi / cosphi : 0; t *= t; double al = cosphi * lp[Lambda]; double als = al * al; al /= Math.Sqrt(1 - Es * sinphi * sinphi); double n = _esp * cosphi * cosphi; xy[X] = K0 * al * (FC1 + FC3 * als * (1 - t + n + FC5 * als * (5 + t * (t - 18) + n * (14 - 58 * t) + FC7 * als * (61 + t * (t * (179 - t) - 479))))); xy[Y] = K0 * (MeridionalDistance.MeridionalLength(lp[Phi], sinphi, cosphi, _en) - _ml0 + sinphi * al * lp[Lambda] * FC2 * (1 + FC4 * als * (5 - t + n * (9 + 4 * n) + FC6 * als * (61 + t * (t - 58) + n * (270 - 330 * t) + FC8 * als * (1385 + t * (t * (543 - t) - 3111)))))); } }
/// <summary> /// /// </summary> /// <param name="arg"></param> /// <param name="es"></param> /// <param name="en"></param> /// <returns></returns> public static double InvMlfn(double arg, double es, double[] en) { return(MeridionalDistance.AngularDistance(arg, es, en)); }
/// <summary> /// Meridonal length function /// </summary> /// <param name="phi"></param> /// <param name="sphi"></param> /// <param name="cphi"></param> /// <param name="en"></param> /// <returns></returns> public static double Mlfn(double phi, double sphi, double cphi, double[] en) { return(MeridionalDistance.MeridionalLength(phi, sphi, cphi, en)); }
/// <summary> /// Obtains the EN parameters for the Meridional distance /// </summary> /// <param name="es"></param> /// <returns></returns> public static double[] Enfn(double es) { return(MeridionalDistance.GetEN(es)); }