/// <summary> /// Converts UTM coordinate to Signed Degree Lat/Long /// </summary> /// <param name="utm">utm</param> /// <returns>Coordinate</returns> /// <example> /// The following example creates (converts to) a signed degree lat long based on a UTM object. /// <code> /// UniversalTransverseMercator utm = new UniversalTransverseMercator("T", 32, 233434, 234234); /// double[] signed = UniversalTransverseMercator.ConvertUTMtoSignedDegree(utm); /// Coordinate c = new Coordinate(signed[0], signed[1], new EagerLoad(false)); /// Console.WriteLine(c); //N 2º 7' 2.332" E 6º 36' 12.653" /// </code> /// </example> public static double[] ConvertUTMtoSignedDegree(UniversalTransverseMercator utm) { bool southhemi = false; Regex upsCheck = new Regex("[AaBbYyZz]"); if (upsCheck.IsMatch(utm.latZone)) { Coordinate c = UPS.UPS_To_Geodetic(utm, new EagerLoad(false)); return(new double[] { c.Latitude.ToDouble(), c.Longitude.ToDouble() }); } if (utm.latZone == "A" || utm.latZone == "B" || utm.latZone == "C" || utm.latZone == "D" || utm.latZone == "E" || utm.latZone == "F" || utm.latZone == "G" || utm.latZone == "H" || utm.latZone == "J" || utm.latZone == "K" || utm.latZone == "L" || utm.latZone == "M") { southhemi = true; } double cmeridian; double x = utm.Easting - 500000.0; double UTMScaleFactor = 0.9996; x /= UTMScaleFactor; /* If in southern hemisphere, adjust y accordingly. */ double y = utm.Northing; if (southhemi) { y -= 10000000.0; } y /= UTMScaleFactor; cmeridian = UTMCentralMeridian(utm.LongZone); double[] signed = UTMtoSigned(x, y, cmeridian, utm.equatorial_radius, utm.inverse_flattening); return(signed); }
/// <summary> /// Converts UTM coordinate to Lat/Long /// </summary> /// <param name="utm">utm</param> /// <param name="eagerLoad">EagerLoad</param> /// <returns>Coordinate</returns> /// <example> /// The following example creates (converts to) a geodetic Coordinate object based on a UTM object. /// Performance is maximized by turning off EagerLoading. /// <code> /// EagerLoad el = new EagerLoad(false); /// UniversalTransverseMercator utm = new UniversalTransverseMercator("T", 32, 233434, 234234); /// Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm, el); /// Console.WriteLine(c); //N 2º 7' 2.332" E 6º 36' 12.653" /// </code> /// </example> public static Coordinate ConvertUTMtoLatLong(UniversalTransverseMercator utm, EagerLoad eagerLoad) { bool southhemi = false; Regex upsCheck = new Regex("[AaBbYyZz]"); if (upsCheck.IsMatch(utm.latZone)) { return(UPS.UPS_To_Geodetic(utm, eagerLoad)); } Regex regex = new Regex("[CcDdEeFfGgHhJjKkLlMm]"); if (regex.IsMatch(utm.latZone)) { southhemi = true; } double cmeridian; double x = utm.Easting - 500000.0; double UTMScaleFactor = 0.9996; x /= UTMScaleFactor; /* If in southern hemisphere, adjust y accordingly. */ double y = utm.Northing; if (southhemi) { y -= 10000000.0; } y /= UTMScaleFactor; cmeridian = UTMCentralMeridian(utm.LongZone); Coordinate c = UTMtoLatLong(x, y, cmeridian, utm.equatorial_radius, utm.inverse_flattening, eagerLoad); return(c); }
/// <summary> /// Assigns UTM values based of Lat/Long /// </summary> /// <param name="lat">DD Latitude</param> /// <param name="longi">DD longitude</param> /// <param name="utm">UTM Object to modify</param> /// <param name="szone">specified zone (for under/over projection</param> internal void ToUTM(double lat, double longi, UniversalTransverseMercator utm, int?szone = null) { //Switch to UPS if (lat < -80 || lat > 84) { UPS ups = new UPS(); ups.Geodetic_To_UPS(lat, longi, utm); systemType = UTM_Type.UPS; return; } else { systemType = UTM_Type.UTM; } //Within UTM BOUNDS string letter = ""; double easting = 0; double northing = 0; int zone; if (szone == null) { zone = (int)Math.Floor(longi / 6 + 31); } else { zone = szone.Value; } if (lat < -72) { letter = "C"; } else if (lat < -64) { letter = "D"; } else if (lat < -56) { letter = "E"; } else if (lat < -48) { letter = "F"; } else if (lat < -40) { letter = "G"; } else if (lat < -32) { letter = "H"; } else if (lat < -24) { letter = "J"; } else if (lat < -16) { letter = "K"; } else if (lat < -8) { letter = "L"; } else if (lat < 0) { letter = "M"; } else if (lat < 8) { letter = "N"; } else if (lat < 16) { letter = "P"; } else if (lat < 24) { letter = "Q"; } else if (lat < 32) { letter = "R"; } else if (lat < 40) { letter = "S"; } else if (lat < 48) { letter = "T"; } else if (lat < 56) { letter = "U"; } else if (lat < 64) { letter = "V"; } else if (lat < 72) { letter = "W"; } else { letter = "X"; } double a = utm.equatorial_radius; double f = 1.0 / utm.inverse_flattening; double b = a * (1 - f); // polar radius double e = Math.Sqrt(1 - Math.Pow(b, 2) / Math.Pow(a, 2)); double e0 = e / Math.Sqrt(1 - Math.Pow(e, 1)); double drad = Math.PI / 180; double k0 = 0.9996; double phi = lat * drad; // convert latitude to radians double lng = longi * drad; // convert longitude to radians double utmz; if (szone == null) { utmz = 1 + Math.Floor((longi + 180) / 6.0); } else { utmz = szone.Value; } // longitude to utm zone double zcm = 3 + 6.0 * (utmz - 1) - 180; // central meridian of a zone // this gives us zone A-B for below 80S double esq = (1 - (b / a) * (b / a)); double e0sq = e * e / (1 - Math.Pow(e, 2)); double M = 0; double N = a / Math.Sqrt(1 - Math.Pow(e * Math.Sin(phi), 2)); double T = Math.Pow(Math.Tan(phi), 2); double C = e0sq * Math.Pow(Math.Cos(phi), 2); double A = (longi - zcm) * drad * Math.Cos(phi); // calculate M (USGS style) M = phi * (1 - esq * (1.0 / 4.0 + esq * (3.0 / 64.0 + 5.0 * esq / 256.0))); M = M - Math.Sin(2.0 * phi) * (esq * (3.0 / 8.0 + esq * (3.0 / 32.0 + 45.0 * esq / 1024.0))); M = M + Math.Sin(4.0 * phi) * (esq * esq * (15.0 / 256.0 + esq * 45.0 / 1024.0)); M = M - Math.Sin(6.0 * phi) * (esq * esq * esq * (35.0 / 3072.0)); M = M * a; //Arc length along standard meridian double M0 = 0; // if another point of origin is used than the equator // Calculate the UTM values... // first the easting var x = k0 * N * A * (1 + A * A * ((1 - T + C) / 6 + A * A * (5 - 18 * T + T * T + 72.0 * C - 58 * e0sq) / 120.0)); //Easting relative to CM x = x + 500000; // standard easting // Northing double y = k0 * (M - M0 + N * Math.Tan(phi) * (A * A * (1 / 2.0 + A * A * ((5 - T + 9 * C + 4 * C * C) / 24.0 + A * A * (61 - 58 * T + T * T + 600 * C - 330 * e0sq) / 720.0)))); // first from the equator double yg = y + 10000000; //yg = y global, from S. Pole if (y < 0) { y = 10000000 + y; // add in false northing if south of the equator } //Last zone is 60, but will hit 61 at 180 degrees exactly. Reset to 1. if (zone == 61) { zone = 1; } easting = x; northing = y; utm.latZone = letter; utm.longZone = zone; utm.easting = easting; utm.northing = northing; utm.systemType = systemType; }