예제 #1
0
파일: LatLng.cs 프로젝트: Chapmania/Juniper
        /// <summary>
        /// Converts this LatLngPoint to a Universal Transverse Mercator point using the WGS-84
        /// datum. The coordinate pair's units will be in meters, and should be usable to make
        /// distance calculations over short distances.
        /// </summary>
        /// <seealso cref="http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm"/>
        /// <param name="latlng">The point on Earth to convert to UTM</param>
        /// <returns>The UTM point</returns>
        public static UTMPoint ToUTM(this LatLngPoint latlng)
        {
            if (latlng is null)
            {
                throw new ArgumentNullException(nameof(latlng));
            }

            var hemisphere = latlng.Latitude < 0
                    ? UTMPoint.GlobeHemisphere.Southern
                    : UTMPoint.GlobeHemisphere.Northern;

            const double k0 = 0.9996;

            double phi     = Degrees.Radians(latlng.Latitude);
            var    sinPhi  = Sin(phi);
            var    cosPhi  = Cos(phi);
            var    sin2Phi = 2 * sinPhi * cosPhi;
            var    cos2Phi = (2 * cosPhi * cosPhi) - 1;
            var    sin4Phi = 2 * sin2Phi * cos2Phi;
            var    cos4Phi = (2 * cos2Phi * cos2Phi) - 1;
            var    sin6Phi = (sin4Phi * cos2Phi) + (cos4Phi * sin2Phi);
            var    tanPhi  = sinPhi / cosPhi;
            var    ePhi    = DatumWGS_84.e * sinPhi;
            var    N       = DatumWGS_84.equatorialRadius / Sqrt(1 - (ePhi * ePhi));

            var utmz = 1 + (int)Floor((latlng.Longitude + 180) / 6.0);
            var zcm  = 3 + (6.0 * (utmz - 1)) - 180;
            var A    = Degrees.Radians((float)(latlng.Longitude - zcm)) * cosPhi;

            var M = DatumWGS_84.equatorialRadius * (
                (phi * DatumWGS_84.alpha1)
                - (sin2Phi * DatumWGS_84.alpha2)
                + (sin4Phi * DatumWGS_84.alpha3)
                - (sin6Phi * DatumWGS_84.alpha4));

            // Easting
            var T       = tanPhi * tanPhi;
            var C       = DatumWGS_84.e0sq * cosPhi * cosPhi;
            var Asqr    = A * A;
            var Tsqr    = T * T;
            var x0      = 1 - T + C;
            var x1      = 5 - (18 * T) + Tsqr + (72.0 * C) - (58 * DatumWGS_84.e0sq);
            var x2      = Asqr * x1 / 120.0;
            var x3      = (x0 / 6) + x2;
            var x4      = 1 + (Asqr * x3);
            var easting = k0 * N * A * x4;

            easting += DatumWGS_84.E0;

            // Northing
            var northing = k0 * (M + (N * tanPhi * (Asqr * ((1 / 2.0) + (Asqr * (((5 - T + (9 * C) + (4 * C * C)) / 24.0) + (Asqr * (61 - (58 * T) + Tsqr + (600 * C) - (330 * DatumWGS_84.e0sq)) / 720.0)))))));

            if (hemisphere == UTMPoint.GlobeHemisphere.Southern)
            {
                northing += DatumWGS_84.FalseNorthing;
            }

            return(new UTMPoint(
                       (float)easting,
                       (float)northing,
                       latlng.Altitude,
                       utmz,
                       hemisphere));
        }