Esempio n. 1
0
        /// <summary>
        /// The function convertFromGeodetic converts geodetic (latitude and
        /// longitude) coordinates to UPS (hemisphere, easting, and northing)
        /// coordinates, according to the current ellipsoid parameters.
        /// If any errors occur, an exception is thrown with a description
        /// of the error.
        /// </summary>
        /// <param name="geodeticCoordinates"></param>
        /// <returns></returns>
        public UPSCoordinates convertFromGeodetic(GeodeticCoordinates geodeticCoordinates)
        {
            /*
             *    latitude      : Latitude in radians                       (input)
             *    longitude     : Longitude in radians                      (input)
             *    hemisphere    : Hemisphere either 'N' or 'S'              (output)
             *    easting       : Easting/X in meters                       (output)
             *    northing      : Northing/Y in meters                      (output)
             */

            char   hemisphere;
            string errorStatus = "";

            double longitude = geodeticCoordinates.longitude;
            double latitude  = geodeticCoordinates.latitude;

            if ((latitude < -MAX_LAT) || (latitude > MAX_LAT))
            {   /* latitude out of range */
                errorStatus += ErrorMessages.latitude;
            }
            else if ((latitude < 0) && (latitude >= (MAX_SOUTH_LAT + EPSILON)))
            {
                errorStatus += ErrorMessages.latitude;
            }
            else if ((latitude >= 0) && (latitude < (MIN_NORTH_LAT - EPSILON)))
            {
                errorStatus += ErrorMessages.latitude;
            }
            if ((longitude < -Math.PI) || (longitude > (2 * Math.PI)))
            {  /* longitude out of range */
                errorStatus += ErrorMessages.longitude;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            if (latitude < 0)
            {
                //this.UPS_Origin_Latitude = -MAX_ORIGIN_LAT;
                hemisphere = 'S';
            }
            else
            {
                //this.UPS_Origin_Latitude = MAX_ORIGIN_LAT;
                hemisphere = 'N';
            }

            PolarStereographic       polarStereographic            = new PolarStereographic(this.semiMajorAxis, this.flattening, this.UPS_Origin_Longitude, 0.994, hemisphere, this.UPS_False_Easting, this.UPS_False_Northing);
            MapProjectionCoordinates polarStereographicCoordinates = polarStereographic.convertFromGeodetic(geodeticCoordinates);

            double easting  = polarStereographicCoordinates.getEasting();
            double northing = polarStereographicCoordinates.getNorthing();

            return(new UPSCoordinates(CoordinateType.Enum.universalPolarStereographic, hemisphere, easting, northing));
        }
        /// <summary>
        /// The function convertToGeodetic converts Transverse
        /// Mercator projection (easting and northing) coordinates to geodetic
        /// (latitude and longitude) coordinates, according to the current ellipsoid
        /// and Transverse Mercator projection parameters.  If any errors occur, 
        /// an exception is thrown with a description of the error.
        /// </summary>
        /// <param name="mapProjectionCoordinates"></param>
        /// <returns></returns>
        public GeodeticCoordinates convertToGeodetic(MapProjectionCoordinates mapProjectionCoordinates)
        {
            /*
             *    easting       : Easting/X in meters                         (input)
             *    northing      : Northing/Y in meters                        (input)
             *    longitude     : Longitude in radians                        (output)
             *    latitude      : Latitude in radians                         (output)
             */

            double c;       /* Cosine of latitude                          */
            double de;      /* Delta easting - Difference in Easting (easting-Fe)    */
            double dlam;    /* Delta longitude - Difference in Longitude       */
            double eta1;    /* constant - TranMerc_ebs *c *c                   */
            double eta2;
            double eta3;
            double eta4;
            double ftphi;   /* Footpoint latitude                              */
            int i;          /* Loop iterator                   */
            double s;       /* Sine of latitude                        */
            double sn;      /* Radius of curvature in the prime vertical       */
            double sr;      /* Radius of curvature in the meridian             */
            double tan1;    /* Tangent of latitude                             */
            double tan2;
            double tan4;
            double t10;     /* Term in coordinate conversion formula - GP to Y */
            double t11;     /* Term in coordinate conversion formula - GP to Y */
            double t12;     /* Term in coordinate conversion formula - GP to Y */
            double t13;     /* Term in coordinate conversion formula - GP to Y */
            double t14;     /* Term in coordinate conversion formula - GP to Y */
            double t15;     /* Term in coordinate conversion formula - GP to Y */
            double t16;     /* Term in coordinate conversion formula - GP to Y */
            double t17;     /* Term in coordinate conversion formula - GP to Y */
            double tmd;     /* True Meridianal distance                        */
            double tmdo;    /* True Meridianal distance for latitude of origin */
            string errorStatus = "";

            double latitude;
            double longitude;

            double easting = mapProjectionCoordinates.getEasting();
            double northing = mapProjectionCoordinates.getNorthing();

            if ((easting < (TranMerc_False_Easting - TranMerc_Delta_Easting)) || (easting > (TranMerc_False_Easting + TranMerc_Delta_Easting)))
            { /* easting out of range  */
                errorStatus += ErrorMessages.easting;
            }
            if ((northing < (TranMerc_False_Northing - TranMerc_Delta_Northing)) || (northing > (TranMerc_False_Northing + TranMerc_Delta_Northing)))
            { /* northing out of range */
                errorStatus += ErrorMessages.northing;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            /* True Meridianal Distances for latitude of origin */
            tmdo = sphtmd(TranMerc_Origin_Lat);

            /*  Origin  */
            tmd = tmdo + (northing - TranMerc_False_Northing) / TranMerc_Scale_Factor;

            /* First Estimate */
            sr = sphsr(0.0);
            ftphi = tmd / sr;

            for (i = 0; i < 5; i++)
            {
                t10 = sphtmd(ftphi);
                sr = sphsr(ftphi);
                ftphi += (tmd - t10) / sr;
            }

            /* Radius of Curvature in the meridian */
            sr = sphsr(ftphi);

            /* Radius of Curvature in the meridian */
            sn = sphsn(ftphi);

            /* Sine CoMath.Sine terms */
            s = Math.Sin(ftphi);
            c = Math.Cos(ftphi);

            /* Tangent Value  */
            tan1 = Math.Tan(ftphi);
            tan2 = tan1 * tan1;
            tan4 = tan2 * tan2;
            eta1 = TranMerc_ebs * Math.Pow(c, 2.0);
            eta2 = eta1 * eta1;
            eta3 = eta2 * eta1;
            eta4 = eta3 * eta1;
            de = easting - TranMerc_False_Easting;
            if (Math.Abs(de) < 0.0001)
            {
                de = 0.0;
            }

            /* Latitude */
            t10 = tan1 / (2.0 * sr * sn * Math.Pow(TranMerc_Scale_Factor, 2.0));
            t11 = tan1 * (5.0 + 3.0 * tan2 + eta1 - 4.0 * Math.Pow(eta1, 2.0) - 9.0 * tan2 * eta1) / (24.0 * sr * Math.Pow(sn, 3.0) * Math.Pow(this.TranMerc_Scale_Factor, 4.0));
            t12 = tan1 * (61.0 + 90.0 * tan2 + 46.0 * eta1 + 45.0 * tan4 - 252.0 * tan2 * eta1 - 3.0 * eta2 + 100.0 * eta3 - 66.0 * tan2 * eta2 - 90.0 * tan4 * eta1 + 88.0 * eta4 + 225.0 * tan4 * eta2 + 84.0 * tan2 * eta3 - 192.0 * tan2 * eta4) / (720.0 * sr * Math.Pow(sn, 5.0) * Math.Pow(this.TranMerc_Scale_Factor, 6.0));
            t13 = tan1 * (1385.0 + 3633.0 * tan2 + 4095.0 * tan4 + 1575.0 * Math.Pow(tan1, 6.0)) / (40320.0 * sr * Math.Pow(sn, 7.0) * Math.Pow(TranMerc_Scale_Factor, 8.0));

            latitude = ftphi - Math.Pow(de, 2.0) * t10 + Math.Pow(de, 4.0) * t11 - Math.Pow(de, 6.0) * t12 + Math.Pow(de, 8.0) * t13;

            t14 = 1.0 / (sn * c * this.TranMerc_Scale_Factor);
            t15 = (1.0 + 2.0 * tan2 + eta1) / (6.0 * Math.Pow(sn, 3.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 3.0));
            t16 = (5.0 + 6.0 * eta1 + 28.0 * tan2 - 3.0 * eta2 + 8.0 * tan2 * eta1 + 24.0 * tan4 - 4.0 * eta3 + 4.0 * tan2 * eta2 + 24.0 * tan2 * eta3) / (120.0 * Math.Pow(sn, 5.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 5.0));
            t17 = (61.0 + 662.0 * tan2 + 1320.0 * tan4 + 720.0 * Math.Pow(tan1, 6.0)) / (5040.0 * Math.Pow(sn, 7.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 7.0));

            /* Difference in Longitude */
            dlam = de * t14 - Math.Pow(de, 3.0) * t15 + Math.Pow(de, 5.0) * t16 - Math.Pow(de, 7.0) * t17;

            /* Longitude */
            longitude = this.TranMerc_Origin_Long + dlam;

            if (Math.Abs(latitude) > PI_OVER_2)
            {
                throw new ArgumentException(ErrorMessages.northing);
            }

            if (longitude > Math.PI)
            {
                longitude -= (2 * Math.PI);
                if (Math.Abs(longitude) > Math.PI)
                {
                    throw new ArgumentException(ErrorMessages.easting);
                }
            }
            else if (longitude < -Math.PI)
            {
                longitude += (2 * Math.PI);
                if (Math.Abs(longitude) > Math.PI)
                {
                    throw new ArgumentException(ErrorMessages.easting);
                }
            }

            if (Math.Abs(dlam) > Math.PI / 20 * Math.Cos(latitude))
            { /* Distortion will result if longitude is more than 9 degrees from the Central Meridian at the equator */
                /* and decreases to 0 degrees at the poles */
                /* As you move towards the poles, distortion will become more significant */
                errorStatus += WarningMessages.longitude;
            }

            return new GeodeticCoordinates(CoordinateType.Enum.geodetic, longitude, latitude);
        }
Esempio n. 3
0
        /// <summary>
        /// The function convertFromGeodetic converts geodetic (latitude and
        /// longitude) coordinates to UTM projection (zone, hemisphere, easting and
        /// northing) coordinates according to the current ellipsoid and UTM zone
        /// zoneOverride parameters.  If any errors occur, an exception is thrown with a description
        /// of the error.
        /// </summary>
        /// <param name="geodeticCoordinates"></param>
        /// <returns></returns>
        public UTMCoordinates convertFromGeodetic(GeodeticCoordinates geodeticCoordinates)
        {
            /*
             *
             *    longitude         : Longitude in radians                (input)
             *    latitude          : Latitude in radians                 (input)
             *    zone              : UTM zone                            (output)
             *    hemisphere        : North or South hemisphere           (output)
             *    easting           : Easting (X) in meters               (output)
             *    northing          : Northing (Y) in meters              (output)
             */

            long   Lat_Degrees;
            long   Long_Degrees;
            int    temp_zone;
            char   hemisphere;
            double False_Northing = 0;
            string errorStatus    = "";

            double longitude = geodeticCoordinates.longitude;
            double latitude  = geodeticCoordinates.latitude;

            if ((latitude < (MIN_LAT - EPSILON)) || (latitude >= (MAX_LAT + EPSILON)))
            { /* latitude out of range */
                errorStatus += ErrorMessages.latitude;
            }
            if ((longitude < -Math.PI) || (longitude > (2 * Math.PI)))
            { /* longitude out of range */
                errorStatus += ErrorMessages.longitude;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            if ((latitude > -1.0e-9) && (latitude < 0))
            {
                latitude = 0.0;
            }

            if (longitude < 0)
            {
                longitude += (2 * Math.PI) + 1.0e-10;
            }

            Lat_Degrees  = (long)(latitude * 180.0 / Math.PI);
            Long_Degrees = (long)(longitude * 180.0 / Math.PI);

            if (longitude < Math.PI)
            {
                temp_zone = (int)(31 + ((longitude * 180.0 / Math.PI) / 6.0));
            }
            else
            {
                temp_zone = (int)(((longitude * 180.0 / Math.PI) / 6.0) - 29);
            }

            if (temp_zone > 60)
            {
                temp_zone = 1;
            }

            if (zoneOverride > 0)
            {
                if ((temp_zone == 1) && (this.zoneOverride == 60))
                {
                    temp_zone = (int)this.zoneOverride;
                }
                else if ((temp_zone == 60) && (zoneOverride == 1))
                {
                    temp_zone = (int)this.zoneOverride;
                }
                else if (((temp_zone - 1) <= zoneOverride) && (zoneOverride <= (temp_zone + 1)))
                {
                    temp_zone = (int)this.zoneOverride;
                }
                else
                {
                    throw new ArgumentException(ErrorMessages.zoneOverride);
                }
            }

            TransverseMercator transverseMercator = getTransverseMercator(temp_zone);

            if (latitude < 0)
            {
                False_Northing = 10000000.0;
                hemisphere     = 'S';
            }
            else
            {
                hemisphere = 'N';
            }

            MapProjectionCoordinates transverseMercatorCoordinates = transverseMercator.convertFromGeodetic(new GeodeticCoordinates(CoordinateType.Enum.geodetic, longitude, latitude));
            double easting  = transverseMercatorCoordinates.getEasting();
            double northing = transverseMercatorCoordinates.getNorthing() + False_Northing;

            if ((easting < MIN_EASTING) || (easting > MAX_EASTING))
            {
                throw new ArgumentException(ErrorMessages.easting);
            }

            if ((northing < MIN_NORTHING) || (northing > MAX_NORTHING))
            {
                throw new ArgumentException(ErrorMessages.northing);
            }

            return(new UTMCoordinates(CoordinateType.Enum.universalTransverseMercator, temp_zone, hemisphere, easting, northing));
        }
        /// <summary>
        /// The function convertToGeodetic converts Polar
        /// Stereographic coordinates (easting and northing) to geodetic
        /// coordinates (latitude and longitude) according to the current ellipsoid
        /// and Polar Stereographic projection Parameters. If any errors occur, 
        /// an exception is thrown with a description of the error.
        /// </summary>
        /// <param name="mapProjectionCoordinates"></param>
        /// <returns></returns>
        public GeodeticCoordinates convertToGeodetic(MapProjectionCoordinates mapProjectionCoordinates)
        {
            /*
             *  easting          : Easting (X), in meters                   (input)
             *  northing         : Northing (Y), in meters                  (input)
             *  longitude        : Longitude, in radians                    (output)
             *  latitude         : Latitude, in radians                     (output)
             *
             */

            double dy = 0, dx = 0;
            double rho = 0;
            double t;
            double PHI, sin_PHI;
            double tempPHI = 0.0;
            double essin;
            double pow_es;
            double delta_radius;
            double longitude, latitude;
            string errorStatus = "";

            double easting = mapProjectionCoordinates.getEasting();
            double northing = mapProjectionCoordinates.getNorthing();

            double min_easting = this.Polar_False_Easting - this.Polar_Delta_Easting;
            double max_easting = this.Polar_False_Easting + this.Polar_Delta_Easting;
            double min_northing = this.Polar_False_Northing - this.Polar_Delta_Northing;
            double max_northing = this.Polar_False_Northing + this.Polar_Delta_Northing;

            if (easting > max_easting || easting < min_easting)
            { /* easting out of range */
                errorStatus += ErrorMessages.easting;
            }
            if (northing > max_northing || northing < min_northing)
            { /* northing out of range */
                errorStatus += ErrorMessages.northing;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            dy = northing - this.Polar_False_Northing;
            dx = easting - this.Polar_False_Easting;

            /* Radius of point with origin of false easting, false northing */
            rho = Math.Sqrt(dx * dx + dy * dy);

            delta_radius = Math.Sqrt(this.Polar_Delta_Easting * this.Polar_Delta_Easting + this.Polar_Delta_Northing * this.Polar_Delta_Northing);

            if (rho > delta_radius)
            { /* Point is outside of projection area */
                throw new ArgumentException(ErrorMessages.radius);
            }

            if ((dy == 0.0) && (dx == 0.0))
            {
                latitude = PI_OVER_2;
                longitude = this.Polar_Central_Meridian;

            }
            else
            {
                if (this.Southern_Hemisphere != 0)
                {
                    dy *= -1.0;
                    dx *= -1.0;
                }

                if (Math.Abs(Math.Abs(this.Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
                {
                    t = rho * this.Polar_tc / (this.Polar_a_mc);
                }
                else
                {
                    t = rho * Polar_k90 / (two_Polar_a);
                }
                PHI = PI_OVER_2 - 2.0 * Math.Atan(t);
                while (Math.Abs(PHI - tempPHI) > 1.0e-10)
                {
                    tempPHI = PHI;
                    sin_PHI = Math.Sin(PHI);
                    essin = es * sin_PHI;
                    pow_es = polarPow(essin);
                    PHI = PI_OVER_2 - 2.0 * Math.Atan(t * pow_es);
                }
                latitude = PHI;
                longitude = Polar_Central_Meridian + Math.Atan2(dx, -dy);

                if (longitude > Math.PI)
                {
                    longitude -= TWO_PI;
                }
                else if (longitude < -Math.PI)
                {
                    longitude += TWO_PI;
                }

                // Force distorted values
                if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
                {
                    latitude = PI_OVER_2;
                }
                else if (latitude < -PI_OVER_2)
                {
                    latitude = -PI_OVER_2;
                }

                if (longitude > Math.PI)  /* force distorted values to 180, -180 degrees */
                {
                    longitude = Math.PI;
                }
                else if (longitude < -Math.PI)
                {
                    longitude = -Math.PI;
                }
            }
            if (Southern_Hemisphere != 0)
            {
                latitude *= -1.0;
                longitude *= -1.0;
            }

            return new GeodeticCoordinates(CoordinateType.Enum.geodetic, longitude, latitude);
        }
Esempio n. 5
0
        /// <summary>
        /// The constructor receives the ellipsoid
        /// parameters and Polar Stereograpic (Standard Parallel) projection parameters as inputs, and
        /// sets the corresponding state variables.  If any errors occur, an
        /// exception is thrown with a description of the error.
        /// </summary>
        /// <param name="ellipsoidSemiMajorAxis">Semi-major axis of ellipsoid, in meters</param>
        /// <param name="ellipsoidFlattening">Flattening of ellipsoid</param>
        /// <param name="centralMeridian">Longitude down from pole, in radians</param>
        /// <param name="standardParallel">Latitude of true scale, in radians</param>
        /// <param name="falseEasting">Easting (X) at center of projection, in meters</param>
        /// <param name="falseNorthing">Northing (Y) at center of projection, in meters</param>
        public PolarStereographic(double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double standardParallel, double falseEasting, double falseNorthing)
        {
            this.coordinateType          = CoordinateType.Enum.polarStereographicStandardParallel;
            this.es                      = 0.08181919084262188000;
            this.es_OVER_2               = .040909595421311;
            this.Southern_Hemisphere     = 0;
            this.Polar_tc                = 1.0;
            this.Polar_k90               = 1.0033565552493;
            this.Polar_a_mc              = 6378137.0;
            this.two_Polar_a             = 12756274.0;
            this.Polar_Central_Meridian  = 0.0;
            this.Polar_Standard_Parallel = ((Math.PI * 90) / 180);
            this.Polar_False_Easting     = 0.0;
            this.Polar_False_Northing    = 0.0;
            this.Polar_Scale_Factor      = 1.0;
            this.Polar_Delta_Easting     = 12713601.0;
            this.Polar_Delta_Northing    = 12713601.0;

            double es2;
            double slat, sinolat, cosolat;
            double essin;
            double one_PLUS_es, one_MINUS_es;
            double one_PLUS_es_sinolat, one_MINUS_es_sinolat;
            double pow_es;
            double inv_f       = 1 / ellipsoidFlattening;
            string errorStatus = "";

            if (ellipsoidSemiMajorAxis <= 0.0)
            { /* Semi-major axis must be greater than zero */
                errorStatus += ErrorMessages.semiMajorAxis;
            }
            if ((inv_f < 250) || (inv_f > 350))
            { /* Inverse flattening must be between 250 and 350 */
                errorStatus += ErrorMessages.ellipsoidFlattening;
            }
            if ((standardParallel < -PI_OVER_2) || (standardParallel > PI_OVER_2))
            { /* Origin Latitude out of range */
                errorStatus += ErrorMessages.originLatitude;
            }
            if ((centralMeridian < -Math.PI) || (centralMeridian > TWO_PI))
            { /* Origin Longitude out of range */
                errorStatus += ErrorMessages.centralMeridian;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            this.semiMajorAxis = ellipsoidSemiMajorAxis;
            this.flattening    = ellipsoidFlattening;

            two_Polar_a = 2.0 * semiMajorAxis;

            if (centralMeridian > Math.PI)
            {
                centralMeridian -= TWO_PI;
            }
            if (standardParallel < 0)
            {
                this.Southern_Hemisphere     = 1;
                this.Polar_Standard_Parallel = -standardParallel;
                this.Polar_Central_Meridian  = -centralMeridian;
            }
            else
            {
                Southern_Hemisphere          = 0;
                this.Polar_Standard_Parallel = standardParallel;
                this.Polar_Central_Meridian  = centralMeridian;
            }
            this.Polar_False_Easting  = falseEasting;
            this.Polar_False_Northing = falseNorthing;

            es2       = 2 * this.flattening - this.flattening * this.flattening;
            es        = Math.Sqrt(es2);
            es_OVER_2 = es / 2.0;

            if (Math.Abs(Math.Abs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
            {
                sinolat = Math.Sin(Polar_Standard_Parallel);
                essin   = es * sinolat;
                pow_es  = polarPow(essin);
                cosolat = Math.Cos(Polar_Standard_Parallel);
                double mc = cosolat / Math.Sqrt(1.0 - essin * essin);
                this.Polar_a_mc = semiMajorAxis * mc;
                this.Polar_tc   = Math.Tan(PI_OVER_4 - Polar_Standard_Parallel / 2.0) / pow_es;
            }

            one_PLUS_es    = 1.0 + es;
            one_MINUS_es   = 1.0 - es;
            this.Polar_k90 = Math.Sqrt(Math.Pow(one_PLUS_es, one_PLUS_es) * Math.Pow(one_MINUS_es, one_MINUS_es));

            slat = Math.Sin(Math.Abs(standardParallel));
            one_PLUS_es_sinolat     = 1.0 + es * slat;
            one_MINUS_es_sinolat    = 1.0 - es * slat;
            this.Polar_Scale_Factor = ((1 + slat) / 2) * (Polar_k90 / Math.Sqrt(Math.Pow(one_PLUS_es_sinolat, one_PLUS_es) * Math.Pow(one_MINUS_es_sinolat, one_MINUS_es)));

            /* Calculate Radius */
            MapProjectionCoordinates tempCoordinates = convertFromGeodetic(new GeodeticCoordinates(CoordinateType.Enum.geodetic, centralMeridian, 0, 0));

            this.Polar_Delta_Northing = tempCoordinates.getNorthing();

            if (this.Polar_False_Northing != 0)
            {
                this.Polar_Delta_Northing -= this.Polar_False_Northing;
            }
            if (Polar_Delta_Northing < 0)
            {
                this.Polar_Delta_Northing = -this.Polar_Delta_Northing;
            }
            this.Polar_Delta_Northing *= 1.01;

            this.Polar_Delta_Easting = this.Polar_Delta_Northing;
        }
Esempio n. 6
0
        /// <summary>
        /// The function convertToGeodetic converts Polar
        /// Stereographic coordinates (easting and northing) to geodetic
        /// coordinates (latitude and longitude) according to the current ellipsoid
        /// and Polar Stereographic projection Parameters. If any errors occur,
        /// an exception is thrown with a description of the error.
        /// </summary>
        /// <param name="mapProjectionCoordinates"></param>
        /// <returns></returns>
        public GeodeticCoordinates convertToGeodetic(MapProjectionCoordinates mapProjectionCoordinates)
        {
            /*
             *  easting          : Easting (X), in meters                   (input)
             *  northing         : Northing (Y), in meters                  (input)
             *  longitude        : Longitude, in radians                    (output)
             *  latitude         : Latitude, in radians                     (output)
             *
             */

            double dy = 0, dx = 0;
            double rho = 0;
            double t;
            double PHI, sin_PHI;
            double tempPHI = 0.0;
            double essin;
            double pow_es;
            double delta_radius;
            double longitude, latitude;
            string errorStatus = "";

            double easting  = mapProjectionCoordinates.getEasting();
            double northing = mapProjectionCoordinates.getNorthing();

            double min_easting  = this.Polar_False_Easting - this.Polar_Delta_Easting;
            double max_easting  = this.Polar_False_Easting + this.Polar_Delta_Easting;
            double min_northing = this.Polar_False_Northing - this.Polar_Delta_Northing;
            double max_northing = this.Polar_False_Northing + this.Polar_Delta_Northing;

            if (easting > max_easting || easting < min_easting)
            { /* easting out of range */
                errorStatus += ErrorMessages.easting;
            }
            if (northing > max_northing || northing < min_northing)
            { /* northing out of range */
                errorStatus += ErrorMessages.northing;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            dy = northing - this.Polar_False_Northing;
            dx = easting - this.Polar_False_Easting;

            /* Radius of point with origin of false easting, false northing */
            rho = Math.Sqrt(dx * dx + dy * dy);

            delta_radius = Math.Sqrt(this.Polar_Delta_Easting * this.Polar_Delta_Easting + this.Polar_Delta_Northing * this.Polar_Delta_Northing);

            if (rho > delta_radius)
            { /* Point is outside of projection area */
                throw new ArgumentException(ErrorMessages.radius);
            }

            if ((dy == 0.0) && (dx == 0.0))
            {
                latitude  = PI_OVER_2;
                longitude = this.Polar_Central_Meridian;
            }
            else
            {
                if (this.Southern_Hemisphere != 0)
                {
                    dy *= -1.0;
                    dx *= -1.0;
                }

                if (Math.Abs(Math.Abs(this.Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
                {
                    t = rho * this.Polar_tc / (this.Polar_a_mc);
                }
                else
                {
                    t = rho * Polar_k90 / (two_Polar_a);
                }
                PHI = PI_OVER_2 - 2.0 * Math.Atan(t);
                while (Math.Abs(PHI - tempPHI) > 1.0e-10)
                {
                    tempPHI = PHI;
                    sin_PHI = Math.Sin(PHI);
                    essin   = es * sin_PHI;
                    pow_es  = polarPow(essin);
                    PHI     = PI_OVER_2 - 2.0 * Math.Atan(t * pow_es);
                }
                latitude  = PHI;
                longitude = Polar_Central_Meridian + Math.Atan2(dx, -dy);

                if (longitude > Math.PI)
                {
                    longitude -= TWO_PI;
                }
                else if (longitude < -Math.PI)
                {
                    longitude += TWO_PI;
                }

                // Force distorted values
                if (latitude > PI_OVER_2)  /* force distorted values to 90, -90 degrees */
                {
                    latitude = PI_OVER_2;
                }
                else if (latitude < -PI_OVER_2)
                {
                    latitude = -PI_OVER_2;
                }

                if (longitude > Math.PI)  /* force distorted values to 180, -180 degrees */
                {
                    longitude = Math.PI;
                }
                else if (longitude < -Math.PI)
                {
                    longitude = -Math.PI;
                }
            }
            if (Southern_Hemisphere != 0)
            {
                latitude  *= -1.0;
                longitude *= -1.0;
            }

            return(new GeodeticCoordinates(CoordinateType.Enum.geodetic, longitude, latitude));
        }
Esempio n. 7
0
        /// <summary>
        /// The constructor receives the ellipsoid
        /// parameters and Polar Stereograpic (Scale Factor) projection parameters as inputs, and
        /// sets the corresponding state variables.  If any errors occur, an
        /// exception is thrown with a description of the error.
        /// </summary>
        /// <param name="ellipsoidSemiMajorAxis">Semi-major axis of ellipsoid, in meters</param>
        /// <param name="ellipsoidFlattening">Flattening of ellipsoid</param>
        /// <param name="centralMeridian">Longitude down from pole, in radians</param>
        /// <param name="scaleFactor">Scale Factor</param>
        /// <param name="hemisphere">Hemisphere</param>
        /// <param name="falseEasting">Easting (X) at center of projection, in meters</param>
        /// <param name="falseNorthing">Northing (Y) at center of projection, in meters</param>
        public PolarStereographic(double ellipsoidSemiMajorAxis, double ellipsoidFlattening, double centralMeridian, double scaleFactor, char hemisphere, double falseEasting, double falseNorthing)
        {
            this.coordinateType          = CoordinateType.Enum.polarStereographicScaleFactor;
            this.es                      = 0.08181919084262188000;
            this.es_OVER_2               = .040909595421311;
            this.Southern_Hemisphere     = 0;
            this.Polar_tc                = 1.0;
            this.Polar_k90               = 1.0033565552493;
            this.Polar_a_mc              = 6378137.0;
            this.two_Polar_a             = 12756274.0;
            this.Polar_Central_Meridian  = 0.0;
            this.Polar_Standard_Parallel = PI_OVER_2;
            this.Polar_False_Easting     = 0.0;
            this.Polar_False_Northing    = 0.0;
            this.Polar_Scale_Factor      = 1.0;
            this.Polar_Delta_Easting     = 12713601.0;
            this.Polar_Delta_Northing    = 12713601.0;

            double es2;
            double sinolat, cosolat;
            double essin;
            double pow_es;
            double mc;
            double one_PLUS_es, one_MINUS_es;
            double one_PLUS_es_sk, one_MINUS_es_sk;
            double sk, sk_PLUS_1;
            double tolerance   = 1.0e-15;
            int    count       = 30;
            double inv_f       = 1 / ellipsoidFlattening;
            string errorStatus = "";

            if (ellipsoidSemiMajorAxis <= 0.0)
            { /* Semi-major axis must be greater than zero */
                errorStatus += ErrorMessages.semiMajorAxis;
            }
            if ((inv_f < 250) || (inv_f > 350))
            { /* Inverse flattening must be between 250 and 350 */
                errorStatus += ErrorMessages.ellipsoidFlattening;
            }
            if ((scaleFactor < MIN_SCALE_FACTOR) || (scaleFactor > MAX_SCALE_FACTOR))
            {
                errorStatus += ErrorMessages.scaleFactor;
            }
            if ((centralMeridian < -Math.PI) || (centralMeridian > TWO_PI))
            { /* Origin Longitude out of range */
                errorStatus += ErrorMessages.centralMeridian;
            }
            if ((hemisphere != 'N') && (hemisphere != 'S'))
            {
                errorStatus += ErrorMessages.hemisphere;
            }

            if (errorStatus.Length > 0)
            {
                // throw CoordinateConversionException(errorStatus);
            }

            this.semiMajorAxis        = ellipsoidSemiMajorAxis;
            this.flattening           = ellipsoidFlattening;
            this.Polar_Scale_Factor   = scaleFactor;
            this.Polar_False_Easting  = falseEasting;
            this.Polar_False_Northing = falseNorthing;

            this.two_Polar_a = 2.0 * this.semiMajorAxis;
            es2       = 2 * this.flattening - this.flattening * this.flattening;
            es        = Math.Sqrt(es2);
            es_OVER_2 = es / 2.0;

            one_PLUS_es    = 1.0 + es;
            one_MINUS_es   = 1.0 - es;
            this.Polar_k90 = Math.Sqrt(Math.Pow(one_PLUS_es, one_PLUS_es) * Math.Pow(one_MINUS_es, one_MINUS_es));

            sk        = 0;
            sk_PLUS_1 = -1 + 2 * this.Polar_Scale_Factor;
            while (Math.Abs(sk_PLUS_1 - sk) > tolerance && count > 0)
            {
                sk              = sk_PLUS_1;
                one_PLUS_es_sk  = 1.0 + es * sk;
                one_MINUS_es_sk = 1.0 - es * sk;
                sk_PLUS_1       = ((2 * this.Polar_Scale_Factor * Math.Sqrt(Math.Pow(one_PLUS_es_sk, one_PLUS_es) * Math.Pow(one_MINUS_es_sk, one_MINUS_es))) / this.Polar_k90) - 1;
                count--;
            }

            if (count > 0)
            {
                //throw new ArgumentException(ErrorMessages.originLatitude);
            }

            double standardParallel = 0.0;

            if (sk_PLUS_1 >= -1.0 && sk_PLUS_1 <= 1.0)
            {
                standardParallel = Math.Asin(sk_PLUS_1);
            }
            else
            {
                throw new ArgumentException(ErrorMessages.originLatitude);
            }

            if (hemisphere == 'S')
            {
                standardParallel *= -1.0;
            }

            if (centralMeridian > Math.PI)
            {
                centralMeridian -= TWO_PI;
            }
            if (standardParallel < 0)
            {
                Southern_Hemisphere     = 1;
                Polar_Standard_Parallel = -standardParallel;
                Polar_Central_Meridian  = -centralMeridian;
            }
            else
            {
                Southern_Hemisphere     = 0;
                Polar_Standard_Parallel = standardParallel;
                Polar_Central_Meridian  = centralMeridian;
            }

            sinolat = Math.Sin(Polar_Standard_Parallel);

            if (Math.Abs(Math.Abs(Polar_Standard_Parallel) - PI_OVER_2) > 1.0e-10)
            {
                essin      = es * sinolat;
                pow_es     = polarPow(essin);
                cosolat    = Math.Cos(Polar_Standard_Parallel);
                mc         = cosolat / Math.Sqrt(1.0 - essin * essin);
                Polar_a_mc = semiMajorAxis * mc;
                Polar_tc   = Math.Tan(PI_OVER_4 - Polar_Standard_Parallel / 2.0) / pow_es;
            }

            /* Calculate Radius */
            MapProjectionCoordinates tempCoordinates = convertFromGeodetic(new GeodeticCoordinates(CoordinateType.Enum.geodetic, centralMeridian, 0));

            Polar_Delta_Northing = tempCoordinates.getNorthing();

            if (this.Polar_False_Northing > 0)
            {
                this.Polar_Delta_Northing -= this.Polar_False_Northing;
            }
            if (this.Polar_Delta_Northing < 0)
            {
                this.Polar_Delta_Northing = -this.Polar_Delta_Northing;
            }
            this.Polar_Delta_Northing *= 1.01;

            this.Polar_Delta_Easting = this.Polar_Delta_Northing;
        }
Esempio n. 8
0
        /// <summary>
        /// The function convertToGeodetic converts Transverse
        /// Mercator projection (easting and northing) coordinates to geodetic
        /// (latitude and longitude) coordinates, according to the current ellipsoid
        /// and Transverse Mercator projection parameters.  If any errors occur,
        /// an exception is thrown with a description of the error.
        /// </summary>
        /// <param name="mapProjectionCoordinates"></param>
        /// <returns></returns>
        public GeodeticCoordinates convertToGeodetic(MapProjectionCoordinates mapProjectionCoordinates)
        {                /*
                          *    easting       : Easting/X in meters                         (input)
                          *    northing      : Northing/Y in meters                        (input)
                          *    longitude     : Longitude in radians                        (output)
                          *    latitude      : Latitude in radians                         (output)
                          */
            double c;    /* Cosine of latitude                          */
            double de;   /* Delta easting - Difference in Easting (easting-Fe)    */
            double dlam; /* Delta longitude - Difference in Longitude       */
            double eta1; /* constant - TranMerc_ebs *c *c                   */
            double eta2;
            double eta3;
            double eta4;
            double ftphi;   /* Footpoint latitude                              */
            int    i;       /* Loop iterator                   */
            double s;       /* Sine of latitude                        */
            double sn;      /* Radius of curvature in the prime vertical       */
            double sr;      /* Radius of curvature in the meridian             */
            double tan1;    /* Tangent of latitude                             */
            double tan2;
            double tan4;
            double t10;     /* Term in coordinate conversion formula - GP to Y */
            double t11;     /* Term in coordinate conversion formula - GP to Y */
            double t12;     /* Term in coordinate conversion formula - GP to Y */
            double t13;     /* Term in coordinate conversion formula - GP to Y */
            double t14;     /* Term in coordinate conversion formula - GP to Y */
            double t15;     /* Term in coordinate conversion formula - GP to Y */
            double t16;     /* Term in coordinate conversion formula - GP to Y */
            double t17;     /* Term in coordinate conversion formula - GP to Y */
            double tmd;     /* True Meridianal distance                        */
            double tmdo;    /* True Meridianal distance for latitude of origin */
            string errorStatus = "";

            double latitude;
            double longitude;

            double easting  = mapProjectionCoordinates.getEasting();
            double northing = mapProjectionCoordinates.getNorthing();

            if ((easting < (TranMerc_False_Easting - TranMerc_Delta_Easting)) || (easting > (TranMerc_False_Easting + TranMerc_Delta_Easting)))
            { /* easting out of range  */
                errorStatus += ErrorMessages.easting;
            }
            if ((northing < (TranMerc_False_Northing - TranMerc_Delta_Northing)) || (northing > (TranMerc_False_Northing + TranMerc_Delta_Northing)))
            { /* northing out of range */
                errorStatus += ErrorMessages.northing;
            }

            if (errorStatus.Length > 0)
            {
                throw new ArgumentException(errorStatus);
            }

            /* True Meridianal Distances for latitude of origin */
            tmdo = sphtmd(TranMerc_Origin_Lat);

            /*  Origin  */
            tmd = tmdo + (northing - TranMerc_False_Northing) / TranMerc_Scale_Factor;

            /* First Estimate */
            sr    = sphsr(0.0);
            ftphi = tmd / sr;

            for (i = 0; i < 5; i++)
            {
                t10    = sphtmd(ftphi);
                sr     = sphsr(ftphi);
                ftphi += (tmd - t10) / sr;
            }

            /* Radius of Curvature in the meridian */
            sr = sphsr(ftphi);

            /* Radius of Curvature in the meridian */
            sn = sphsn(ftphi);

            /* Sine CoMath.Sine terms */
            s = Math.Sin(ftphi);
            c = Math.Cos(ftphi);

            /* Tangent Value  */
            tan1 = Math.Tan(ftphi);
            tan2 = tan1 * tan1;
            tan4 = tan2 * tan2;
            eta1 = TranMerc_ebs * Math.Pow(c, 2.0);
            eta2 = eta1 * eta1;
            eta3 = eta2 * eta1;
            eta4 = eta3 * eta1;
            de   = easting - TranMerc_False_Easting;
            if (Math.Abs(de) < 0.0001)
            {
                de = 0.0;
            }

            /* Latitude */
            t10 = tan1 / (2.0 * sr * sn * Math.Pow(TranMerc_Scale_Factor, 2.0));
            t11 = tan1 * (5.0 + 3.0 * tan2 + eta1 - 4.0 * Math.Pow(eta1, 2.0) - 9.0 * tan2 * eta1) / (24.0 * sr * Math.Pow(sn, 3.0) * Math.Pow(this.TranMerc_Scale_Factor, 4.0));
            t12 = tan1 * (61.0 + 90.0 * tan2 + 46.0 * eta1 + 45.0 * tan4 - 252.0 * tan2 * eta1 - 3.0 * eta2 + 100.0 * eta3 - 66.0 * tan2 * eta2 - 90.0 * tan4 * eta1 + 88.0 * eta4 + 225.0 * tan4 * eta2 + 84.0 * tan2 * eta3 - 192.0 * tan2 * eta4) / (720.0 * sr * Math.Pow(sn, 5.0) * Math.Pow(this.TranMerc_Scale_Factor, 6.0));
            t13 = tan1 * (1385.0 + 3633.0 * tan2 + 4095.0 * tan4 + 1575.0 * Math.Pow(tan1, 6.0)) / (40320.0 * sr * Math.Pow(sn, 7.0) * Math.Pow(TranMerc_Scale_Factor, 8.0));

            latitude = ftphi - Math.Pow(de, 2.0) * t10 + Math.Pow(de, 4.0) * t11 - Math.Pow(de, 6.0) * t12 + Math.Pow(de, 8.0) * t13;

            t14 = 1.0 / (sn * c * this.TranMerc_Scale_Factor);
            t15 = (1.0 + 2.0 * tan2 + eta1) / (6.0 * Math.Pow(sn, 3.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 3.0));
            t16 = (5.0 + 6.0 * eta1 + 28.0 * tan2 - 3.0 * eta2 + 8.0 * tan2 * eta1 + 24.0 * tan4 - 4.0 * eta3 + 4.0 * tan2 * eta2 + 24.0 * tan2 * eta3) / (120.0 * Math.Pow(sn, 5.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 5.0));
            t17 = (61.0 + 662.0 * tan2 + 1320.0 * tan4 + 720.0 * Math.Pow(tan1, 6.0)) / (5040.0 * Math.Pow(sn, 7.0) * c * Math.Pow(this.TranMerc_Scale_Factor, 7.0));

            /* Difference in Longitude */
            dlam = de * t14 - Math.Pow(de, 3.0) * t15 + Math.Pow(de, 5.0) * t16 - Math.Pow(de, 7.0) * t17;

            /* Longitude */
            longitude = this.TranMerc_Origin_Long + dlam;

            if (Math.Abs(latitude) > PI_OVER_2)
            {
                throw new ArgumentException(ErrorMessages.northing);
            }

            if (longitude > Math.PI)
            {
                longitude -= (2 * Math.PI);
                if (Math.Abs(longitude) > Math.PI)
                {
                    throw new ArgumentException(ErrorMessages.easting);
                }
            }
            else if (longitude < -Math.PI)
            {
                longitude += (2 * Math.PI);
                if (Math.Abs(longitude) > Math.PI)
                {
                    throw new ArgumentException(ErrorMessages.easting);
                }
            }

            if (Math.Abs(dlam) > Math.PI / 20 * Math.Cos(latitude))
            { /* Distortion will result if longitude is more than 9 degrees from the Central Meridian at the equator */
                /* and decreases to 0 degrees at the poles */
                /* As you move towards the poles, distortion will become more significant */
                errorStatus += WarningMessages.longitude;
            }

            return(new GeodeticCoordinates(CoordinateType.Enum.geodetic, longitude, latitude));
        }