using System.Collections.Generic;
public class LatLngUTMConverter
public double Lat { get; set; }
public double Lng { get; set; }
public double Easting { get; set; }
public double UTMEasting { get; set; }
public double Northing { get; set; }
public double UTMNorthing { get; set; }
public int ZoneNumber { get; set; }
public String ZoneLetter { get; set; }
return ZoneNumber + ZoneLetter;
public override string ToString()
return "" + ZoneNumber + ZoneLetter + " " + Easting + "" + Northing;
private double eccSquared;
private string datumName = "WGS 84";
public LatLngUTMConverter(String datumNameIn)
if (!String.IsNullOrEmpty(datumNameIn))
this.setEllipsoid(datumName);
private double toRadians(double grad)
return grad * Math.PI / 180;
private String getUtmLetterDesignator(double latitude)
if ((84 >= latitude) && (latitude >= 72))
else if ((72 > latitude) && (latitude >= 64))
else if ((64 > latitude) && (latitude >= 56))
else if ((56 > latitude) && (latitude >= 48))
else if ((48 > latitude) && (latitude >= 40))
else if ((40 > latitude) && (latitude >= 32))
else if ((32 > latitude) && (latitude >= 24))
else if ((24 > latitude) && (latitude >= 16))
else if ((16 > latitude) && (latitude >= 8))
else if ((8 > latitude) && (latitude >= 0))
else if ((0 > latitude) && (latitude >= -8))
else if ((-8 > latitude) && (latitude >= -16))
else if ((-16 > latitude) && (latitude >= -24))
else if ((-24 > latitude) && (latitude >= -32))
else if ((-32 > latitude) && (latitude >= -40))
else if ((-40 > latitude) && (latitude >= -48))
else if ((-48 > latitude) && (latitude >= -56))
else if ((-56 > latitude) && (latitude >= -64))
else if ((-64 > latitude) && (latitude >= -72))
else if ((-72 > latitude) && (latitude >= -80))
public UTMResult convertLatLngToUtm(double latitude, double longitude)
throw new Exception("No ecclipsoid data associated with unknown datum: " + datumName);
var LongTemp = longitude;
var LatRad = toRadians(latitude);
var LongRad = toRadians(LongTemp);
if (LongTemp >= 8 && LongTemp <= 13 && latitude > 54.5 && latitude < 58)
else if (latitude >= 56.0 && latitude < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0)
ZoneNumber = (int) ((LongTemp + 180) / 6) + 1;
if (latitude >= 72.0 && latitude < 84.0)
if (LongTemp >= 0.0 && LongTemp < 9.0)
else if (LongTemp >= 9.0 && LongTemp < 21.0)
else if (LongTemp >= 21.0 && LongTemp < 33.0)
else if (LongTemp >= 33.0 && LongTemp < 42.0)
var LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3;
var LongOriginRad = toRadians(LongOrigin);
var UTMZone = getUtmLetterDesignator(latitude);
var eccPrimeSquared = (eccSquared) / (1 - eccSquared);
var N = a / Math.Sqrt(1 - eccSquared * Math.Sin(LatRad) * Math.Sin(LatRad));
var T = Math.Tan(LatRad) * Math.Tan(LatRad);
var C = eccPrimeSquared * Math.Cos(LatRad) * Math.Cos(LatRad);
var A = Math.Cos(LatRad) * (LongRad - LongOriginRad);
var M = a * ((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));
var UTMEasting = 0.9996 * N * (A + (1 - T + C) * A * A * A / 6
+ (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120)
var UTMNorthing = 0.9996 * (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));
UTMNorthing += 10000000.0;
return new UTMResult { Easting= UTMEasting, Northing= UTMNorthing, ZoneNumber= ZoneNumber, ZoneLetter= UTMZone};
private void setEllipsoid(String name)
case "Australian National":
eccSquared = 0.006694542;
eccSquared = 0.006674372;
case "Bessel 1841 Nambia":
eccSquared = 0.006674372;
eccSquared = 0.006768658;
eccSquared = 0.006803511;
eccSquared = 0.006637847;
case "Fischer 1960 Mercury":
eccSquared = 0.006693422;
eccSquared = 0.006693422;
eccSquared = 0.006694605;
eccSquared = 0.006693422;
eccSquared = 0.006693422;
eccSquared = 0.006637847;
case "Modified Fischer 1960":
eccSquared = 0.006693422;
case "South American 1969":
eccSquared = 0.006694542;
eccSquared = 0.006693422;
eccSquared = 0.006694542;
eccSquared = 0.006694318;
public LatLng convertUtmToLatLng(double UTMEasting, double UTMNorthing, int UTMZoneNumber, String UTMZoneLetter)
var e1 = (1 - Math.Sqrt(1 - this.eccSquared)) / (1 + Math.Sqrt(1 - this.eccSquared));
var x = UTMEasting - 500000.0;
var ZoneNumber = UTMZoneNumber;
var ZoneLetter = UTMZoneLetter;
var LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3;
var eccPrimeSquared = (this.eccSquared) / (1 - this.eccSquared);
var mu = M / (this.a * (1 - this.eccSquared / 4 - 3 * this.eccSquared * this.eccSquared / 64 - 5 * this.eccSquared * this.eccSquared * this.eccSquared / 256));
var 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);
var phi1 = this.toDegrees(phi1Rad);
var N1 = this.a / Math.Sqrt(1 - this.eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad));
var T1 = Math.Tan(phi1Rad) * Math.Tan(phi1Rad);
var C1 = eccPrimeSquared * Math.Cos(phi1Rad) * Math.Cos(phi1Rad);
var R1 = this.a * (1 - this.eccSquared) / Math.Pow(1 - this.eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad), 1.5);
var D = x / (N1 * 0.9996);
var Lat = 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);
Lat = this.toDegrees(Lat);
var Long = (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);
Long = LongOrigin + this.toDegrees(Long);
return new LatLng { Lat = Lat, Lng = Long };
private double toDegrees (double rad) {
return rad / Math.PI* 180;
public static void Main()
Console.WriteLine("Test coordinate UTM 25833: 401051.31, 5813138.32 (Berlin OSW)");
LatLngUTMConverter converter = new LatLngUTMConverter("ETRS89");
LatLngUTMConverter.LatLng latlng = converter.convertUtmToLatLng(401051.31, 5813138.32, 33, "N");
Console.WriteLine("toLatLng: "+ latlng.Lat + " " + latlng.Lng);
LatLngUTMConverter.UTMResult utm = converter.convertLatLngToUtm(latlng.Lat,latlng.Lng);
Console.WriteLine("back to UTM: " + utm.Easting + " " + utm.Northing);