/// <summary>
        /// The forward transform from geodetic units to linear units
        /// </summary>
        /// <param name="lp">The array of lambda, phi coordinates</param>
        /// <param name="xy">The array of x, y coordinates</param>
        protected override void OnForward(double[] lp, double[] xy)
        {
            double sp   = E * Math.Sin(lp[Phi]);
            double phip = 2 * Math.Atan(Math.Exp(_c * (
                                                     Math.Log(Math.Tan(FortPi + 0.5 * lp[Phi])) - _hlfE * Math.Log((1 + sp) / (1 - sp)))
                                                 + _k)) - HalfPi;
            double lamp  = _c * lp[Lambda];
            double cp    = Math.Cos(phip);
            double phipp = Proj.Aasin(_cosp0 * Math.Sin(phip) - _sinp0 * cp * Math.Cos(lamp));
            double lampp = Proj.Aasin(cp * Math.Sin(lamp) / Math.Cos(phipp));

            xy[X] = _kR * lampp;
            xy[Y] = _kR * Math.Log(Math.Tan(FortPi + 0.5 * phipp));
        }
        /// <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)
        {
            if (_isGuam)
            {
                GuamInverse(xy, lp);
            }

            double c;

            if ((c = Proj.Hypot(xy[X], xy[Y])) < EPS10)
            {
                lp[Phi]    = Phi0;
                lp[Lambda] = 0;
                return;
            }
            if (_mode == Modes.Oblique || _mode == Modes.Equitorial)
            {
                double az;
                double cosAz = Math.Cos(az = Math.Atan2(xy[X], xy[Y]));
                double t     = _cosph0 * cosAz;
                double b     = Es * t / OneEs;
                double a     = -b * t;
                b *= 3 * (1 - a) * _sinph0;
                double d   = c / _N1;
                double e   = d * (1 - d * d * (a * (1 + a) / 6 + b * (1 + 3 * a) * d / 24));
                double f   = 1 - e * e * (a / 2 + b * e / 6);
                double psi = Proj.Aasin(_sinph0 * Math.Cos(e) + t * Math.Sin(e));
                lp[Lambda] = Proj.Aasin(Math.Sin(az) * Math.Sin(e) / Math.Cos(psi));
                if ((t = Math.Abs(psi)) < EPS10)
                {
                    lp[Phi] = 0;
                }
                else if (Math.Abs(t - HalfPi) < 0)
                {
                    lp[Phi] = HalfPi;
                }
                else
                {
                    lp[Phi] = Math.Atan((1 - Es * f * _sinph0 / Math.Sin(psi)) * Math.Tan(psi) /
                                        OneEs);
                }
            }
            else
            {
                /* Polar */
                lp[Phi] = Proj.InvMlfn(_mode == Modes.NorthPole ? _Mp - c : _Mp + c,
                                       Es, _en);
                lp[Lambda] = Math.Atan2(xy[X], _mode == Modes.NorthPole ? -xy[Y] : xy[Y]);
            }
        }
示例#3
0
 /// <summary>
 /// The forward transform from geodetic units to linear units
 /// </summary>
 /// <param name="lp">The array of lambda, phi coordinates</param>
 /// <param name="xy">The array of x, y coordinates</param>
 protected override void OnForward(double[] lp, double[] xy)
 {
     if ((_rho = _c - (IsElliptical ? _n * Proj.Qsfn(Math.Sin(lp[Phi]),
                                                     E, OneEs) : _n2 *Math.Sin(lp[Phi]))) < 0)
     {
         xy[X] = double.NaN;
         xy[Y] = double.NaN;
         //throw new ProjectionException(20);
         return;
     }
     _rho  = _dd * Math.Sqrt(_rho);
     xy[X] = _rho * Math.Sin(lp[Lambda] *= _n);
     xy[Y] = _rho0 - _rho * Math.Cos(lp[Lambda]);
 }
        /// <summary>
        /// Performs the inverse transform from a single coordinate of linear units to the same coordinate in geodetic lambda and
        /// phi units in the special case where the shape of the earth is being approximated as a perfect sphere.
        /// </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 SphericalInverse(double[] xy, double[] lp)
        {
            double cRh;

            if ((cRh = Proj.Hypot(xy[X], xy[Y])) > Math.PI)
            {
                if (cRh - EPS10 > Math.PI)
                {
                    throw new ProjectionException(20);
                }
                cRh = Math.PI;
            }
            else if (cRh < EPS10)
            {
                lp[Phi]    = Phi0;
                lp[Lambda] = 0;
                return;
            }
            if (_mode == Modes.Oblique || _mode == Modes.Equitorial)
            {
                double sinc = Math.Sin(cRh);
                double cosc = Math.Cos(cRh);
                if (_mode == Modes.Equitorial)
                {
                    lp[Phi] = Proj.Aasin(xy[Y] * sinc / cRh);
                    xy[X]  *= sinc;
                    xy[Y]   = cosc * cRh;
                }
                else
                {
                    lp[Phi] = Proj.Aasin(cosc * _sinph0 + xy[Y] * sinc * _cosph0 /
                                         cRh);
                    xy[Y]  = (cosc - _sinph0 * Math.Sin(lp[Phi])) * cRh;
                    xy[X] *= sinc * _cosph0;
                }
                lp[Lambda] = xy[Y] == 0 ? 0 : Math.Atan2(xy[X], xy[Y]);
            }
            else if (_mode == Modes.NorthPole)
            {
                lp[Phi]    = HalfPi - cRh;
                lp[Lambda] = Math.Atan2(xy[X], -xy[Y]);
            }
            else
            {
                lp[Phi]    = cRh - HalfPi;
                lp[Lambda] = Math.Atan2(xy[X], xy[Y]);
            }
        }
        /// <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)
        {
            double sinphi;

            if (projInfo.StandardParallel1 != null)
            {
                _phi1 = projInfo.StandardParallel1.Value * Math.PI / 180;
            }
            if (projInfo.StandardParallel2 != null)
            {
                _phi2 = projInfo.StandardParallel2.Value * Math.PI / 180;
            }

            if (Math.Abs(_phi1 + _phi2) < EPS10)
            {
                throw new ProjectionException(-21);
            }
            _en = Proj.Enfn(Es);
            _n  = sinphi = Math.Sin(_phi1);
            double cosphi = Math.Cos(_phi1);
            bool   secant = Math.Abs(_phi1 - _phi2) >= EPS10;

            if (IsElliptical)
            {
                double m1  = Proj.Msfn(sinphi, cosphi, Es);
                double ml1 = Proj.Mlfn(_phi1, sinphi, cosphi, _en);
                if (secant)
                {
                    /* secant cone */
                    sinphi = Math.Sin(_phi2);
                    cosphi = Math.Cos(_phi2);
                    _n     = (m1 - Proj.Msfn(sinphi, cosphi, Es)) /
                             (Proj.Mlfn(_phi2, sinphi, cosphi, _en) - ml1);
                }
                _c    = ml1 + m1 / _n;
                _rho0 = _c - Proj.Mlfn(Phi0, Math.Sin(Phi0),
                                       Math.Cos(Phi0), _en);
            }
            else
            {
                if (secant)
                {
                    _n = (cosphi - Math.Cos(_phi2)) / (_phi2 - _phi1);
                }
                _c    = _phi1 + Math.Cos(_phi1) / _n;
                _rho0 = _c - Phi0;
            }
        }
示例#6
0
        /// <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 ph1 = Proj.InvMlfn(_m0 + xy[Y], Es, _en);

            _tn     = Math.Tan(ph1); _t = _tn * _tn;
            _n      = Math.Sin(ph1);
            _r      = 1 / (1 - Es * _n * _n);
            _n      = Math.Sqrt(_r);
            _r     *= (1 - Es) * _n;
            _dd     = xy[X] / _n;
            _d2     = _dd * _dd;
            lp[Phi] = ph1 - (_n * _tn / _r) * _d2 *
                      (.5 - (1 + 3 * _t) * _d2 * C3);
            lp[Lambda] = _dd * (1 + _t * _d2 *
                                (-C4 + (1 + 3 * _t) * _d2 * C5)) / Math.Cos(ph1);
        }
        private void GuamInverse(double[] xy, double[] lp)
        {
            double t = 0;
            int    i;

            double x2 = 0.5 * xy[X] * xy[X];

            lp[Phi] = Phi0;
            for (i = 0; i < 3; ++i)
            {
                t       = E * Math.Sin(lp[Phi]);
                lp[Phi] = Proj.InvMlfn(_M1 + xy[Y] -
                                       x2 * Math.Tan(lp[Phi]) * (t = Math.Sqrt(1 - t * t)), Es, _en);
            }
            lp[Lambda] = xy[X] * t / Math.Cos(lp[Phi]);
        }
示例#8
0
        /// <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)
        {
            if (Math.Abs(lp[Phi]) <= TOL)
            {
                xy[X] = lp[Lambda]; xy[Y] = -_ml0;
            }
            else
            {
                double sp = Math.Sin(lp[Phi]);
                double cp;
                double ms = Math.Abs(cp = Math.Cos(lp[Phi])) > TOL?Proj.Msfn(sp, cp, Es) / sp : 0;

                xy[X] = ms * Math.Sin(lp[Lambda] *= sp);
                xy[Y] = (Proj.Mlfn(lp[Phi], sp, cp, _en) - _ml0) + ms * (1 - Math.Cos(lp[Lambda]));
            }
        }
        /// <summary>
        /// The inverse transform from linear units to geodetic units
        /// </summary>
        /// <param name="xy">The double values for the input x and y values stored in an array</param>
        /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
        protected override void OnInverse(double[] xy, double[] lp)
        {
            xy[Y] /= _cY;
            double c = Math.Cos(lp[Phi] = _tanMode ? Math.Atan(xy[Y]) : Proj.Aasin(xy[Y]));

            lp[Phi]   /= _cP;
            lp[Lambda] = xy[X] / (_cX * Math.Cos(lp[Phi] /= _cP));
            if (_tanMode)
            {
                lp[Lambda] /= c * c;
            }
            else
            {
                lp[Lambda] *= c;
            }
        }
        /// <summary>
        /// The forward transform from geodetic units to linear units
        /// </summary>
        /// <param name="lp">The array of lambda, phi coordinates</param>
        /// <param name="xy">The array of x, y coordinates</param>
        protected override void OnForward(double[] lp, double[] xy)
        {
            double[] p = new double[2];

            lp[Phi] = (lp[Phi] - Phi0) * RadToSec5;
            p[R]    = _tpsi[Ntpsi];
            for (int i = Ntpsi - 1; i >= 0; i--)
            {
                p[R] = _tpsi[i] + lp[Phi] * p[R];
            }
            p[R] *= lp[Phi];
            p[I]  = lp[Lambda];
            p     = Proj.Zpoly1(p, _bf, Nbf);
            xy[X] = p[I];
            xy[Y] = p[R];
        }
示例#11
0
        /// <summary>
        /// The forward transform from geodetic units to linear units
        /// </summary>
        /// <param name="lp">The array of lambda, phi coordinates</param>
        /// <param name="xy">The array of x, y coordinates</param>
        protected override void OnForward(double[] lp, double[] xy)
        {
            double ul, us;
            double vl = Math.Sin(_bl * lp[Lambda]);

            if (Math.Abs(Math.Abs(lp[Phi]) - Math.PI / 2) <= EPS10)
            {
                ul = lp[Phi] < 0 ? -_singam : _singam;
                us = _al * lp[Phi] / _bl;
            }
            else
            {
                double q = _el / (_ellips ? Math.Pow(Proj.Tsfn(lp[Phi], Math.Sin(lp[Phi]), E), _bl) : TSFN0(lp[Phi]));
                double s = .5 * (q - 1 / q);
                ul = 2 * (s * _singam - vl * _cosgam) / (q + 1 / q);
                double con = Math.Cos(_bl * lp[Lambda]);
                if (Math.Abs(con) >= Tol)
                {
                    us = _al * Math.Atan((s * _cosgam + vl * _singam) / con) / _bl;
                    if (con < 0)
                    {
                        us += Math.PI * _al / _bl;
                    }
                }
                else
                {
                    us = _al * _bl * lp[Lambda];
                }
            }
            if (Math.Abs(Math.Abs(ul) - 1) <= EPS10)
            {
                throw new ProjectionException(20);
            }
            double vs = .5 * _al * Math.Log((1 - ul) / (1 + ul)) / _bl;

            us -= _u0;
            if (!_rot)
            {
                xy[X] = us;
                xy[Y] = vs;
            }
            else
            {
                xy[X] = vs * _cosrot + us * _sinrot;
                xy[Y] = us * _cosrot - vs * _sinrot;
            }
        }
        /// <summary>
        /// The forward transform from geodetic units to linear units
        /// </summary>
        /// <param name="lp">The array of lambda, phi coordinates</param>
        /// <param name="xy">The array of x, y coordinates</param>
        protected override void OnForward(double[] lp, double[] xy)
        {
            double t, dl1, dl2;
            double sp = Math.Sin(lp[Phi]);
            double cp = Math.Cos(lp[Phi]);
            double z1 = Proj.Aacos(_sp1 * sp + _cp1 * cp * Math.Cos(dl1 = lp[Lambda] + _dlam2));
            double z2 = Proj.Aacos(_sp2 * sp + _cp2 * cp * Math.Cos(dl2 = lp[Lambda] - _dlam2));

            z1   *= z1;
            z2   *= z2;
            xy[X] = _r2z0 * (t = z1 - z2);
            t     = _z02 - t;
            xy[Y] = _r2z0 * Proj.Asqrt(4 * _z02 * z2 - t * t);
            if ((_ccs * sp - cp * (_cs * Math.Sin(dl1) - _sc * Math.Sin(dl2))) < 0)
            {
                xy[Y] = -xy[Y];
            }
        }
示例#13
0
        /// <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 s;

            if ((s = Math.Abs(lp[Phi] = Proj.InvMlfn(xy[Y], Es, _en))) < HalfPi)
            {
                s          = Math.Sin(lp[Phi]);
                lp[Lambda] = xy[X] * Math.Sqrt(1 - Es * s * s) / Math.Cos(lp[Phi]);
            }
            else if ((s - EPS10) < HalfPi)
            {
                lp[Lambda] = 0;
            }
            else
            {
                throw new ProjectionException(20);
            }
        }
示例#14
0
        /// <summary>
        /// Performs the inverse transform from a single coordinate of linear units to the same coordinate in geodetic lambda and
        /// phi units in the special case where the shape of the earth is being approximated as a perfect sphere.
        /// </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 SphericalInverse(double[] xy, double[] lp)
        {
            double rh = Proj.Hypot(xy[X], xy[Y] = _cphi1 - xy[Y]);

            lp[Phi] = _cphi1 + _phi1 - rh;
            if (Math.Abs(lp[Phi]) > HalfPi)
            {
                throw new ProjectionException(20);
            }
            if (Math.Abs(Math.Abs(lp[Phi]) - HalfPi) <= EPS10)
            {
                lp[Lambda] = 0;
            }
            else
            {
                lp[Lambda] = rh * Math.Atan2(xy[X], xy[Y]) / Math.Cos(lp[Phi]);
            }
        }
        /// <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)
        {
            double phip0;

            _hlfE = 0.5 * E;
            double cp = Math.Cos(Phi0);

            cp *= cp;
            _c  = Math.Sqrt(1 + Es * cp * cp * ROneEs);
            double sp = Math.Sin(Phi0);

            _cosp0 = Math.Cos(phip0 = Proj.Aasin(_sinp0 = sp / _c));
            sp    *= E;
            _k     = Math.Log(Math.Tan(FortPi + 0.5 * phip0)) - _c * (
                Math.Log(Math.Tan(FortPi + 0.5 * Phi0)) - _hlfE *
                Math.Log((1 + sp) / (1 - sp)));
            _kR = K0 * Math.Sqrt(OneEs) / (1 - sp * sp);
        }
示例#16
0
 /// <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)
 {
     xy[Y] += _ml0;
     if (Math.Abs(xy[Y]) <= TOL)
     {
         lp[Lambda] = xy[X];
         lp[Phi]    = 0;
     }
     else
     {
         double c;
         int    i;
         double r = xy[Y] * xy[Y] + xy[X] * xy[X];
         for (lp[Phi] = xy[Y], i = I_ITER; i > 0; --i)
         {
             double sp = Math.Sin(lp[Phi]);
             double cp;
             double s2ph = sp * (cp = Math.Cos(lp[Phi]));
             if (Math.Abs(cp) < ITOL)
             {
                 throw new ProjectionException(20);
             }
             double mlp;
             c = sp * (mlp = Math.Sqrt(1 - Es * sp * sp)) / cp;
             double ml  = Proj.Mlfn(lp[Phi], sp, cp, _en);
             double mlb = ml * ml + r;
             mlp = OneEs / (mlp * mlp * mlp);
             double dPhi;
             lp[Phi] += (dPhi =
                             (ml + ml + c * mlb - 2 * xy[Y] * (c * ml + 1)) / (Es * s2ph * (mlb - 2 * xy[Y] * ml) / c +
                                                                               2 * (xy[Y] - ml) * (c * mlp - 1 / s2ph) - mlp - mlp));
             if (Math.Abs(dPhi) <= ITOL)
             {
                 break;
             }
         }
         if (i == 0)
         {
             throw new ProjectionException(20);
         }
         c          = Math.Sin(lp[Phi]);
         lp[Lambda] = Math.Asin(xy[X] * Math.Tan(lp[Phi]) * Math.Sqrt(1 - Es * c * c)) / Math.Sin(lp[Phi]);
     }
 }
        /// <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)
        {
            double sinX = 0.0, cosX = 0.0;

            double coslam = Math.Cos(lp[Lambda]);
            double sinlam = Math.Sin(lp[Lambda]);
            double sinphi = Math.Sin(lp[Phi]);

            if (_mode == Modes.Oblique || _mode == Modes.Equitorial)
            {
                double x;
                sinX = Math.Sin(x = 2 * Math.Atan(Ssfn(lp[Phi], sinphi, E)) - HalfPi);
                cosX = Math.Cos(x);
            }
            if (_mode == Modes.Oblique || _mode == Modes.Equitorial)
            {
                double a;
                if (_mode == Modes.Oblique)
                {
                    a = _akm1 / (_cosX1 * (1 + _sinX1 * sinX +
                                           _cosX1 * cosX * coslam));
                    xy[Y] = a * (_cosX1 * sinX - _sinX1 * cosX * coslam);
                }
                else
                {
                    a     = 2 * _akm1 / (1 + cosX * coslam);
                    xy[Y] = a * sinX;
                }
                xy[X] = a * cosX;
            }
            else
            {
                if (_mode == Modes.SouthPole)
                {
                    lp[Phi] = -lp[Phi];
                    coslam  = -coslam;
                    sinphi  = -sinphi;
                }
                xy[X] = _akm1 * Proj.Tsfn(lp[Phi], sinphi, E);
                xy[Y] = -xy[X] * coslam;
            }
            xy[X] = xy[X] * sinlam;
        }
示例#18
0
        /// <summary>
        /// The inverse transform from linear units to geodetic units
        /// </summary>
        /// <param name="xy">The double values for the input x and y values stored in an array</param>
        /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
        protected override void OnInverse(double[] xy, double[] lp)
        {
            double us, vs;

            if (!_rot)
            {
                us = xy[X];
                vs = xy[Y];
            }
            else
            {
                vs = xy[X] * _cosrot - xy[Y] * _sinrot;
                us = xy[Y] * _cosrot + xy[X] * _sinrot;
            }
            us += _u0;
            double q  = Math.Exp(-_bl * vs / _al);
            double s  = .5 * (q - 1 / q);
            double vl = Math.Sin(_bl * us / _al);
            double ul = 2 * (vl * _cosgam + s * _singam) / (q + 1 / q);

            if (Math.Abs(Math.Abs(ul) - 1) < EPS10)
            {
                lp[Lambda] = 0;
                lp[Phi]    = ul < 0 ? -HalfPi : HalfPi;
            }
            else
            {
                lp[Phi] = _el / Math.Sqrt((1 + ul) / (1 - ul));
                if (_ellips)
                {
                    if ((lp[Phi] = Proj.Phi2(Math.Pow(lp[Phi], 1 / _bl), E)) == double.MaxValue)
                    {
                        throw new ProjectionException(20);
                    }
                }
                else
                {
                    lp[Phi] = HalfPi - 2 * Math.Atan(lp[Phi]);
                }
                lp[Lambda] = -Math.Atan2((s * _cosgam - vl * _singam), Math.Cos(_bl * us / _al)) / _bl;
            }
        }
示例#19
0
        /// <summary>
        /// Performs the inverse transform from a single coordinate of linear units to the same coordinate in geodetic lambda and
        /// phi units in the special case where the shape of the earth is being approximated as a perfect sphere.
        /// </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 SphericalInverse(double[] xy, double[] lp)
        {
            double cosz = 0, sinz = 0;
            double x  = xy[X];
            double y  = xy[Y];
            double rh = Proj.Hypot(x, y);

            if ((lp[Phi] = rh * .5) > 1)
            {
                throw new ProjectionException(20);
            }
            lp[Phi] = 2 * Math.Asin(lp[Phi]);
            if (_mode == Modes.Oblique || _mode == Modes.Equitorial)
            {
                sinz = Math.Sin(lp[Phi]);
                cosz = Math.Cos(lp[Phi]);
            }
            switch (_mode)
            {
            case Modes.Equitorial:
                lp[Phi] = Math.Abs(rh) <= EPS10 ? 0 : Math.Asin(y * sinz / rh);
                x      *= sinz;
                y       = cosz * rh;
                break;

            case Modes.Oblique:
                lp[Phi] = Math.Abs(rh) <= EPS10 ? Phi0 : Math.Asin(cosz * _sinb1 + y * sinz * _sinb1 / rh);
                x      *= sinz * _cosb1;
                y       = (cosz - Math.Sin(lp[Phi]) * _sinb1) * rh;
                break;

            case Modes.NorthPole:
                y       = -y;
                lp[Phi] = HalfPi - lp[Phi];
                break;

            case Modes.SouthPole:
                lp[Phi] -= HalfPi;
                break;
            }
            lp[Lambda] = (y == 0 && (_mode == Modes.Equitorial || _mode == Modes.Oblique)) ? 0 : Math.Atan2(x, y);
        }
示例#20
0
 /// <summary>
 /// The inverse transform from linear units to geodetic units
 /// </summary>
 /// <param name="xy">The double values for the input x and y values stored in an array</param>
 /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
 protected override void OnInverse(double[] xy, double[] lp)
 {
     if ((_rho = Proj.Hypot(xy[X], xy[Y] = _rho0 - xy[Y])) != 0.0)
     {
         if (_n < 0)
         {
             _rho  = -_rho;
             xy[X] = -xy[X];
             xy[Y] = -xy[Y];
         }
         lp[Phi] = _rho / _dd;
         if (IsElliptical)
         {
             lp[Phi] = (_c - lp[Phi] * lp[Phi]) / _n;
             if (Math.Abs(_ec - Math.Abs(lp[Phi])) > TOL7)
             {
                 if ((lp[Phi] = PhiFn(lp[Phi], E, OneEs)) == double.MaxValue)
                 {
                     throw new ProjectionException(20);
                 }
             }
             else
             {
                 lp[Phi] = lp[Phi] < 0 ? -HalfPi : HalfPi;
             }
         }
         else if (Math.Abs(lp[Phi] = (_c - lp[Phi] * lp[Phi]) / _n2) <= 1)
         {
             lp[Phi] = Math.Asin(lp[Phi]);
         }
         else
         {
             lp[Phi] = lp[Phi] < 0 ? -HalfPi : HalfPi;
         }
         lp[Lambda] = Math.Atan2(xy[X], xy[Y]) / _n;
     }
     else
     {
         lp[Lambda] = 0;
         lp[Phi]    = _n > 0? HalfPi : -HalfPi;
     }
 }
 /// <summary>
 /// Special factor calculations for a factors calculation
 /// </summary>
 /// <param name="lp">lambda-phi</param>
 /// <param name="p">The projection</param>
 /// <param name="fac">The Factors</param>
 protected override void OnSpecial(double[] lp, ProjectionInfo p, Factors fac)
 {
     if (Math.Abs(Math.Abs(lp[Phi]) - HalfPi) < EPS10)
     {
         if ((lp[Phi] * _n) <= 0)
         {
             return;
         }
         _rho = 0;
     }
     else
     {
         _rho = _c * (_ellipse ? Math.Pow(Proj.Tsfn(lp[Phi], Math.Sin(lp[Phi]),
                                                    p.GeographicInfo.Datum.Spheroid.Eccentricity()), _n)
                            : Math.Pow(Math.Tan(Math.PI / 4 + .5 * lp[Phi]), -_n));
     }
     fac.code = AnalyticModes.IsAnalHK | AnalyticModes.IsAnalConv;
     fac.k    = fac.h = p.ScaleFactor * _n * _rho / Proj.Msfn(Math.Sin(lp[Phi]), Math.Cos(lp[Phi]), p.GeographicInfo.Datum.Spheroid.EccentricitySquared());
     fac.conv = -_n * lp[Lambda];
 }
        /// <summary>
        /// The inverse transform from linear units to geodetic units
        /// </summary>
        /// <param name="xy">The double values for the input x and y values stored in an array</param>
        /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
        protected override void OnInverse(double[] xy, double[] lp)
        {
            double cz1 = Math.Cos(Proj.Hypot(xy[Y], xy[X] + _hz0));
            double cz2 = Math.Cos(Proj.Hypot(xy[Y], xy[X] - _hz0));
            double s   = cz1 + cz2;
            double d   = cz1 - cz2;

            lp[Lambda] = -Math.Atan2(d, (s * _thz0));
            lp[Phi]    = Proj.Aacos(Proj.Hypot(_thz0 * s, d) * _rhshz0);
            if (xy[Y] < 0)
            {
                lp[Phi] = -lp[Phi];
            }
            /* lam--phi now in system relative to P1--P2 base equator */
            double sp = Math.Sin(lp[Phi]);
            double cp = Math.Cos(lp[Phi]);

            lp[Phi]    = Proj.Aasin(_sa * sp + _ca * cp * (s = Math.Cos(lp[Lambda] -= _lp)));
            lp[Lambda] = Math.Atan2(cp * Math.Sin(lp[Lambda]), _sa * cp * s - _ca * sp) + _lamc;
        }
示例#23
0
        /// <summary>
        /// Internal code handling the setup operations for the transform
        /// </summary>
        protected void Setup()
        {
            double sinphi;

            if (Math.Abs(_phi1 + _phi2) < EPS10)
            {
                throw new ProjectionException(-21);
            }
            _n = sinphi = Math.Sin(_phi1);
            double cosphi = Math.Cos(_phi1);
            bool   secant = Math.Abs(_phi1 - _phi2) >= EPS10;

            if (IsElliptical)
            {
                double m1  = Proj.Msfn(sinphi, cosphi, Es);
                double ml1 = Proj.Qsfn(sinphi, E, OneEs);
                if (secant)
                { /* secant cone */
                    sinphi = Math.Sin(_phi2);
                    cosphi = Math.Cos(_phi2);
                    double m2  = Proj.Msfn(sinphi, cosphi, Es);
                    double ml2 = Proj.Qsfn(sinphi, E, OneEs);
                    _n = (m1 * m1 - m2 * m2) / (ml2 - ml1);
                }
                _ec   = 1 - .5 * OneEs * Math.Log((1 - E) / (1 + E)) / E;
                _c    = m1 * m1 + _n * ml1;
                _dd   = 1 / _n;
                _rho0 = _dd * Math.Sqrt(_c - _n * Proj.Qsfn(Math.Sin(Phi0), E, OneEs));
            }
            else
            {
                if (secant)
                {
                    _n = .5 * (_n + Math.Sin(_phi2));
                }
                _n2   = _n + _n;
                _c    = cosphi * cosphi + _n2 * sinphi;
                _dd   = 1 / _n;
                _rho0 = _dd * Math.Sqrt(_c - _n2 * Math.Sin(Phi0));
            }
        }
示例#24
0
        /// <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 s;

            double rh = Proj.Hypot(xy[X], xy[Y] = _am1 - xy[Y]);

            lp[Phi] = Proj.InvMlfn(_am1 + _m1 - rh, Es, _en);
            if ((s = Math.Abs(lp[Phi])) < HalfPi)
            {
                s          = Math.Sin(lp[Phi]);
                lp[Lambda] = rh * Math.Atan2(xy[X], xy[Y]) *
                             Math.Sqrt(1 - Es * s * s) / Math.Cos(lp[Phi]);
            }
            else if (Math.Abs(s - HalfPi) <= EPS10)
            {
                lp[Lambda] = 0;
            }
            else
            {
                throw new ProjectionException(20);
            }
        }
        /// <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)
        {
            double pp;

            /* get control point locations */
            double phi1 = projInfo.GetPhi1();
            double lam1 = projInfo.GetLam1();
            double phi2 = projInfo.GetPhi2();
            double lam2 = projInfo.GetLam2();

            if (phi1 == phi2 && lam1 == lam2)
            {
                throw new ProjectionException(-25);
            }
            Lam0   = Proj.Adjlon(0.5 * (lam1 + lam2));
            _dlam2 = Proj.Adjlon(lam2 - lam1);
            _cp1   = Math.Cos(phi1);
            _cp2   = Math.Cos(phi2);
            _sp1   = Math.Sin(phi1);
            _sp2   = Math.Sin(phi2);
            _cs    = _cp1 * _sp2;
            _sc    = _sp1 * _cp2;
            _ccs   = _cp1 * _cp2 * Math.Sin(_dlam2);
            _z02   = Proj.Aacos(_sp1 * _sp2 + _cp1 * _cp2 * Math.Cos(_dlam2));
            _hz0   = .5 * _z02;
            double A12 = Math.Atan2(_cp2 * Math.Sin(_dlam2),
                                    _cp1 * _sp2 - _sp1 * _cp2 * Math.Cos(_dlam2));

            _ca     = Math.Cos(pp = Proj.Aasin(_cp1 * Math.Sin(A12)));
            _sa     = Math.Sin(pp);
            _lp     = Proj.Adjlon(Math.Atan2(_cp1 * Math.Cos(A12), _sp1) - _hz0);
            _dlam2 *= .5;
            _lamc   = HalfPi - Math.Atan2(Math.Sin(A12) * _sp1, Math.Cos(A12)) - _dlam2;
            _thz0   = Math.Tan(_hz0);
            _rhshz0 = .5 / Math.Sin(_hz0);
            _r2z0   = 0.5 / _z02;
            _z02   *= _z02;
        }
        /// <summary>
        /// The forward transform in the special case where there is no flattening of the spherical model of the earth.
        /// </summary>
        /// <param name="lp">The input lambda and phi geodetic values organized in an array</param>
        /// <param name="xy">The output x and y values organized in an array</param>
        protected override void SphericalForward(double[] lp, double[] xy)
        {
            /* Calculation of the three components of the vector from satellite to
            ** position on earth surface (lon,lat).*/
            double tmp = Math.Cos(lp[Phi]);
            double vx  = Math.Cos(lp[Lambda]) * tmp;
            double vy  = Math.Sin(lp[Lambda]) * tmp;
            double vz  = Math.Sin(lp[Phi]);

            /* Check visibility.*/
            if (((_radiusG - vx) * vx - vy * vy - vz * vz) < 0)
            {
                xy[X] = double.NaN;
                xy[Y] = double.NaN;
                //throw new ProjectionException(20);
                return;
            }

            /* Calculation based on view angles from satellite.*/
            tmp   = _radiusG - vx;
            xy[X] = _radiusG1 * Math.Atan(vy / tmp);
            xy[Y] = _radiusG1 * Math.Atan(vz / Proj.Hypot(vy, tmp));
        }
 /// <summary>
 /// The inverse transform from linear units to geodetic units
 /// </summary>
 /// <param name="xy">The double values for the input x and y values stored in an array</param>
 /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
 protected override void OnInverse(double[] xy, double[] lp)
 {
     if ((_rho = Proj.Hypot(xy[X], xy[Y] = _rho0 - xy[Y])) != 0.0)
     {
         if (_n < 0)
         {
             _rho  = -_rho;
             xy[X] = -xy[X];
             xy[Y] = -xy[Y];
         }
         lp[Phi] = _c - _rho;
         if (IsElliptical)
         {
             lp[Phi] = Proj.InvMlfn(lp[Phi], Es, _en);
         }
         lp[Lambda] = Math.Atan2(xy[X], xy[Y]) / _n;
     }
     else
     {
         lp[Lambda] = 0;
         lp[Phi]    = _n > 0 ? HalfPi : -HalfPi;
     }
 }
示例#28
0
        /// <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)
        {
            double t = 0;

            if (projInfo.StandardParallel1 != null)
            {
                t = projInfo.StandardParallel1.Value * Math.PI / 180;
            }
            t = projInfo.ParamD("lat_ts") * Math.PI / 180;
            if ((K0 = Math.Cos(t)) < 0)
            {
                throw new ProjectionException(-24);
            }
            if (!IsElliptical)
            {
                return;
            }
            t    = Math.Sin(t);
            K0  /= Math.Sqrt(1 - Es * t * t);
            E    = Math.Sqrt(Es);
            _apa = Proj.Authset(Es);
            _qp  = Proj.Qsfn(1, E, OneEs);
        }
        /// <summary>
        /// The inverse transform from linear units to geodetic units
        /// </summary>
        /// <param name="xy">The double values for the input x and y values stored in an array</param>
        /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
        protected override void OnInverse(double[] xy, double[] lp)
        {
            int nn;

            double[] p  = new double[2];
            double[] dp = new double[2];
            p[R] = xy[Y];
            p[I] = xy[X];
            for (nn = 20; nn > 0; --nn)
            {
                double[] fp;
                double[] f = Proj.Zpolyd1(p, _bf, Nbf, out fp);
                f[R] -= xy[Y];
                f[I] -= xy[X];
                double den = fp[R] * fp[R] + fp[I] * fp[I];
                p[R] += dp[R] = -(f[R] * fp[R] + f[I] * fp[I]) / den;
                p[I] += dp[I] = -(f[I] * fp[R] - f[R] * fp[I]) / den;
                if ((Math.Abs(dp[R]) + Math.Abs(dp[I])) <= EPS10)
                {
                    break;
                }
            }
            if (nn > 0)
            {
                lp[Lambda] = p[I];
                lp[Phi]    = _tphi[Ntphi];
                for (int i = Ntphi - 1; i > 0; i++)
                {
                    lp[Phi] = _tphi[i] + p[R] * lp[Phi];
                }
                lp[Phi] = Phi0 + p[R] * lp[Phi] * Sec5ToRad;
            }
            else
            {
                lp[Lambda] = lp[Phi] = double.MaxValue;
            }
        }
        /// <summary>
        /// The inverse transform from linear units to geodetic units
        /// </summary>
        /// <param name="xy">The double values for the input x and y values stored in an array</param>
        /// <param name="lp">The double values for the output lambda and phi values stored in an array</param>
        protected override void OnInverse(double[] xy, double[] lp)
        {
            double rho;

            xy[X] /= K0;
            xy[Y] /= K0;
            if ((rho = Proj.Hypot(xy[X], xy[Y])) > 0)
            {
                double c    = 2 * Math.Atan2(rho, _r2);
                double sinc = Math.Sin(c);
                double cosc = Math.Cos(c);
                lp[Phi]    = Math.Asin(cosc * _sinc0 + xy[Y] * sinc * _cosc0 / rho);
                lp[Lambda] = Math.Atan2(xy[X] * sinc, rho * _cosc0 * cosc -
                                        xy[Y] * _sinc0 * sinc);
            }
            else
            {
                lp[Phi]    = _phic0;
                lp[Lambda] = 0;
            }
            double[] temp = _gauss.Inverse(lp);
            lp[Phi]    = temp[Phi];
            lp[Lambda] = temp[Lambda];
        }