//converts UTM coords to lat/long. Equations from USGS Bulletin 1532 //East Longitudes are positive, West longitudes are negative. //North latitudes are positive, South latitudes are negative //Lat and Long are in decimal degrees. //Does not take into account the special UTM zones between 0 degrees //and 36 degrees longitude above 72 degrees latitude and a special //zone 32 between 56 degrees and 64 degrees north latitude //Written by Chuck Gantz- [email protected] // Ported to C by David Baird, 1998, Re-ported to C# by David Baird 2010 public static void UTMToLatLong(Ellipsoid referenceEllipsoid, double northing, double easting, string zone, out double latitude, out double longitude) { latitude = 0; longitude = 0; const double k0 = 0.9996; double a = referenceEllipsoid.EquatorialRadius; double eccSquared = referenceEllipsoid.EccentricitySquared; double e1 = (1 - Math.Sqrt(1 - eccSquared)) / (1 + Math.Sqrt(1 - eccSquared)); // int NorthernHemisphere; //1 for northern hemispher, 0 for southern double x = easting - 500000.0; double y = northing; //if ( x <= 2875) x = 2875; // -db- 01/09/1998 To stop errors when Easting = 500000 if (y == 0) y = 0.000000001; // -db- 01/09/1998 To stop errors when Northing = 0 var match = ZoneRegex.Match(zone); if (!match.Success) { return; } char zoneLetter = match.Groups[2].Value.ToUpper()[0]; int zoneNumber = Int32.Parse(match.Groups[1].Value); if ((zoneLetter - 'N') > 0) { // NorthernHemisphere = 1;//point is in northern hemisphere } else { // NorthernHemisphere = 0;//point is in southern hemisphere y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere } double longOrigin = (zoneNumber - 1) * 6 - 180 + 3; double eccPrimeSquared = (eccSquared) / (1 - eccSquared); double m = y / k0; double mu = m / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); double phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.Sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.Sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.Sin(6 * mu); double n1 = a / Math.Sqrt(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad)); double t1 = Math.Tan(phi1Rad) * Math.Tan(phi1Rad); double c1 = eccPrimeSquared * Math.Cos(phi1Rad) * Math.Cos(phi1Rad); double r1 = a * (1 - eccSquared) / Math.Pow(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad), 1.5); double d = x / (n1 * k0); latitude = phi1Rad - (n1 * Math.Tan(phi1Rad) / r1) * (d * d / 2 - (5 + 3 * t1 + 10 * c1 - 4 * c1 * c1 - 9 * eccPrimeSquared) * d * d * d * d / 24 + (61 + 90 * t1 + 298 * c1 + 45 * t1 * t1 - 252 * eccPrimeSquared - 3 * c1 * c1) * d * d * d * d * d * d / 720); latitude = latitude * RadsToDegrees; longitude = (d - (1 + 2 * t1 + c1) * d * d * d / 6 + (5 - 2 * c1 + 28 * t1 - 3 * c1 * c1 + 8 * eccPrimeSquared + 24 * t1 * t1) * d * d * d * d * d / 120) / Math.Cos(phi1Rad); longitude = longOrigin + longitude * RadsToDegrees; }
//converts UTM coords to lat/long. Equations from USGS Bulletin 1532 //East Longitudes are positive, West longitudes are negative. //North latitudes are positive, South latitudes are negative //Lat and Long are in decimal degrees. //Does not take into account the special UTM zones between 0 degrees //and 36 degrees longitude above 72 degrees latitude and a special //zone 32 between 56 degrees and 64 degrees north latitude //Written by Chuck Gantz- [email protected] // Ported to C by David Baird, 1998, Re-ported to C# by David Baird 2010 public static void UTMToLatLong(Ellipsoid referenceEllipsoid, double northing, double easting, string zone, out double latitude, out double longitude) { latitude = 0; longitude = 0; const double k0 = 0.9996; double a = referenceEllipsoid.EquatorialRadius; double eccSquared = referenceEllipsoid.EccentricitySquared; double e1 = (1 - Math.Sqrt(1 - eccSquared)) / (1 + Math.Sqrt(1 - eccSquared)); // int NorthernHemisphere; //1 for northern hemispher, 0 for southern double x = easting - 500000.0; double y = northing; //if ( x <= 2875) x = 2875; // -db- 01/09/1998 To stop errors when Easting = 500000 if (y == 0) { y = 0.000000001; // -db- 01/09/1998 To stop errors when Northing = 0 } var match = ZoneRegex.Match(zone); if (!match.Success) { return; } char zoneLetter = match.Groups[2].Value.ToUpper()[0]; int zoneNumber = Int32.Parse(match.Groups[1].Value); if ((zoneLetter - 'N') > 0) { // NorthernHemisphere = 1;//point is in northern hemisphere } else { // NorthernHemisphere = 0;//point is in southern hemisphere y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere } double longOrigin = (zoneNumber - 1) * 6 - 180 + 3; double eccPrimeSquared = (eccSquared) / (1 - eccSquared); double m = y / k0; double mu = m / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); double phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.Sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.Sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.Sin(6 * mu); double n1 = a / Math.Sqrt(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad)); double t1 = Math.Tan(phi1Rad) * Math.Tan(phi1Rad); double c1 = eccPrimeSquared * Math.Cos(phi1Rad) * Math.Cos(phi1Rad); double r1 = a * (1 - eccSquared) / Math.Pow(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad), 1.5); double d = x / (n1 * k0); latitude = phi1Rad - (n1 * Math.Tan(phi1Rad) / r1) * (d * d / 2 - (5 + 3 * t1 + 10 * c1 - 4 * c1 * c1 - 9 * eccPrimeSquared) * d * d * d * d / 24 + (61 + 90 * t1 + 298 * c1 + 45 * t1 * t1 - 252 * eccPrimeSquared - 3 * c1 * c1) * d * d * d * d * d * d / 720); latitude = latitude * RadsToDegrees; longitude = (d - (1 + 2 * t1 + c1) * d * d * d / 6 + (5 - 2 * c1 + 28 * t1 - 3 * c1 * c1 + 8 * eccPrimeSquared + 24 * t1 * t1) * d * d * d * d * d / 120) / Math.Cos(phi1Rad); longitude = longOrigin + longitude * RadsToDegrees; }
// converts lat/long to UTM coords. Equations from USGS Bulletin 1532 // East Longitudes are positive, West longitudes are negative. // North latitudes are positive, South latitudes are negative // Lat and Long are in decimal degrees // Does not take into account thespecial UTM zones between 0 degrees and // 36 degrees longitude above 72 degrees latitude and a special zone 32 // between 56 degrees and 64 degrees north latitude // Originally written by Chuck Gantz- [email protected]. Ported to C by David Baird, 1998, Re-ported to c# David Baird 2010 public static void LatLongToUTM(Ellipsoid referenceEllipsoid, double latitude, double longitude, out double northing, out double easting, out string zone) { double equatorialRadius = referenceEllipsoid.EquatorialRadius; double eccSquared = referenceEllipsoid.EccentricitySquared; const double k0 = 0.9996; // Magic constant :-( double longOrigin; double latRad = latitude * DegreesToRads; double longRad = longitude * DegreesToRads; // Outside bounds checking -db- 01/09/1998 if (latitude < -90.0) { latitude = -90.0; } if (latitude > 90.0) { latitude = 90.0; } if (longitude < -180.0) { longitude = -180.0; } if (longitude > 180.0) { longitude = 180.0; } if (longitude > -6 && longitude <= 0) { longOrigin = -3; //arbitrarily set origin at 0 longitude to 3W } else if (longitude < 6 && longitude > 0) { longOrigin = 3; } else { longOrigin = ((int)longitude / 6) * 6 + 3 * ((int)longitude / 6) / Math.Abs((int)longitude / 6); } double longOriginRad = longOrigin * DegreesToRads; //compute the UTM Zone from the latitude and longitude zone = string.Format("{0}{1}", (int)((longitude + 180) / 6) + 1, UTMLetterDesignator(latitude)); double eccPrimeSquared = (eccSquared) / (1 - eccSquared); double n = equatorialRadius / Math.Sqrt(1 - eccSquared * Math.Sin(latRad) * Math.Sin(latRad)); double T = Math.Tan(latRad) * Math.Tan(latRad); double c = eccPrimeSquared * Math.Cos(latRad) * Math.Cos(latRad); double a = Math.Cos(latRad) * (longRad - longOriginRad); double m = equatorialRadius * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * latRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.Sin(2 * latRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.Sin(4 * latRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Math.Sin(6 * latRad)); easting = k0 * n * (a + (1 - T + c) * a * a * a / 6 + (5 - 18 * T + T * T + 72 * c - 58 * eccPrimeSquared) * a * a * a * a * a / 120) + 500000.0; northing = k0 * (m + n * Math.Tan(latRad) * (a * a / 2 + (5 - T + 9 * c + 4 * c * c) * a * a * a * a / 24 + (61 - 58 * T + T * T + 600 * c - 330 * eccPrimeSquared) * a * a * a * a * a * a / 720)); if (latitude <= 0) { northing += 10000000.0; //10000000 meter offset for southern hemisphere } }