16

I've been searching for a while now (here and on google obviously) for a neat way to convert a set of UTM coordinates to Latitude and Longitude. I've got the coordinates and I know in what zone they are, but how do I convert this to Latitude and Longitude? I Was hoping there would be some kind of class that could do at least some of the magic for me, but it doesn't seem so :(

Any suggestions on this?

I know it can be done, as this converter seems to work just fine Geographic/UTM Coordinate Converter.

Any input is greatly appreciated! :)

Thanks!

bomortensen
  • 3,198
  • 9
  • 49
  • 73
  • Both good answers! :) Thanks a lot. I fixed it a bit different by finding the Lat and Lon from a given address. Not the most neat way of programming, but it does the work. I'm going to explore the ProjNet library though. Thanks again :) – bomortensen Apr 22 '10 at 13:40

7 Answers7

19

Here is:

 public static void ToLatLon(double utmX, double utmY, string utmZone, out double latitude, out double longitude)
    {
        bool isNorthHemisphere = utmZone.Last() >= 'N';

        var diflat = -0.00066286966871111111111111111111111111;
        var diflon = -0.0003868060578;

        var zone = int.Parse(utmZone.Remove(utmZone.Length - 1));
        var c_sa = 6378137.000000;
        var c_sb = 6356752.314245;
        var e2 = Math.Pow((Math.Pow(c_sa,2) - Math.Pow(c_sb,2)),0.5)/c_sb;
        var e2cuadrada = Math.Pow(e2,2);
        var c = Math.Pow(c_sa,2) / c_sb;
        var x = utmX - 500000;
        var y = isNorthHemisphere ? utmY : utmY - 10000000;

        var s = ((zone * 6.0) - 183.0);
        var lat = y / (c_sa * 0.9996);
        var v = (c / Math.Pow(1 + (e2cuadrada * Math.Pow(Math.Cos(lat), 2)), 0.5)) * 0.9996;
        var a = x / v;
        var a1 = Math.Sin(2 * lat);
        var a2 = a1 * Math.Pow((Math.Cos(lat)), 2);
        var j2 = lat + (a1 / 2.0);
        var j4 = ((3 * j2) + a2) / 4.0;
        var j6 = ((5 * j4) + Math.Pow(a2 * (Math.Cos(lat)), 2)) / 3.0;
        var alfa = (3.0 / 4.0) * e2cuadrada;
        var beta = (5.0 / 3.0) * Math.Pow(alfa, 2);
        var gama = (35.0 / 27.0) * Math.Pow(alfa, 3);
        var bm = 0.9996 * c * (lat - alfa * j2 + beta * j4 - gama * j6);
        var b = (y - bm) / v;
        var epsi = ((e2cuadrada * Math.Pow(a, 2)) / 2.0) * Math.Pow((Math.Cos(lat)), 2);
        var eps = a * (1 - (epsi / 3.0));
        var nab = (b * (1 - epsi)) + lat;
        var senoheps = (Math.Exp(eps) - Math.Exp(-eps)) / 2.0;
        var delt  = Math.Atan(senoheps/(Math.Cos(nab) ) );
        var tao = Math.Atan(Math.Cos(delt) * Math.Tan(nab));

        longitude = ((delt * (180.0 / Math.PI)) + s) + diflon;
        latitude = ((lat + (1 + e2cuadrada * Math.Pow(Math.Cos(lat), 2) - (3.0 / 2.0) * e2cuadrada * Math.Sin(lat) * Math.Cos(lat) * (tao - lat)) * (tao - lat)) * (180.0 / Math.PI)) + diflat;
    }
playful
  • 1,634
  • 15
  • 14
  • 3
    Thanks Playful! I just change this lines for me, because i am udng in Brazil. bool isNorthHemisphere = utmZone.Last() == 'N' ? true : false; var diflat = 0.00006286966871111111111111111111111111; //-0.00066286966871111111111111111111111111; var diflon = -0.0003868060578; – Jonathan Molina Jul 24 '15 at 12:32
  • 1
    i am having diff of 1.6+ in long. can you explain variables such as s, v, a, a1, a2, j2, j4 etc? i might have different values for my location as following: Angular unit: Degree (0.017453292519943299) Central_Meridian: 55.333333 Inverse Flattening: 298.257223563 – Adeem Jul 17 '19 at 07:02
12

Take a look at this .NET library http://projnet.codeplex.com/ . This should help in your case

Gart
  • 2,247
  • 1
  • 26
  • 35
4

There is c++ code available on this website: http://www.gpsy.com/gpsinfo/geotoutm/

Go down the page a bit to the "Source Code" heading, and look for these files at the bottom:

Chuck Gantz

Enclosures: LatLong-UTMconversion.cpp (view online as text file) LatLong-UTMconversion.h (view online as text file) UTMConversions.cpp (view online as text file) SwissGrid.cpp (view online as text file) constants.h (view online as text file)

e.g. the first file links to: www.gpsy.com/gpsinfo/geotoutm/gantz/LatLong-UTMconversion.cpp etc

There are functions here for going both ways: UTM to Lat Long, and vice versa. If you look elsewhere, there are python versions of this code. e.g. at code.google.com/p/pys60gps/source/browse/trunk/lib/LatLongUTMconversion.py?r=246

There are also c# versions of some of it: at mediakey.dk/~cc/convert-northing-and-easting-utm-to-longitude-and-latitude/

Good luck.

Nick
  • 39
  • 2
4

I made a port from a javascript library to C#, I have tested it and works perfectly, you can take a look at it here.

oware
  • 447
  • 7
  • 13
  • Warning: There are errors in your port; I've tested against different online converters. – John Silence Feb 08 '19 at 11:43
  • sorry, I have not had time to correct it, as far as i know, the latlng to utm works fine, can you help to make it work correctly? – oware Feb 08 '19 at 16:37
1

If you want to roll your own functions, you can find a lot of useful information in this page:

http://www.colorado.edu/geography/gcraft/notes/coordsys/coordsys.html

I have a couple of functions to convert between lat-lon and UTM (both ways), but they are a bit long to write here.

Gorpik
  • 10,360
  • 3
  • 32
  • 53
1

Checkout CoordinateSharp on NuGet. It's really easy to do this with it.

 //Example
 UniversalTransverseMercator utm = new UniversalTransverseMercator("Q", 14, 581943.5, 2111989.8);
 Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm);
Tronald
  • 1,524
  • 1
  • 13
  • 28
0

Use this code:

     public static void UTMToLatLon(double Easting, double Northing, double Zone, double Hemi, out double latitude, out double longitude)
    {
        double DtoR = Math.PI / 180, RtoD = 180 / Math.PI;
        double a = 6378137, f = 0.00335281066474748071984552861852, northernN0 = 0, southernN0 = 10000000, E0 = 500000, 
            n = f / (2 - f), k0 = 0.9996,
            A = a * (1 + (1 / 4) * Math.Pow(n, 2) + (1 / 64) * Math.Pow(n, 4) + (1 / 256) * Math.Pow(n, 6) + (25 / 16384) * Math.Pow(n, 8) + (49 / 65536) * Math.Pow(n, 10)) / (1 + n),             
            beta1 = n / 2 - (2 / 3) * Math.Pow(n, 2) + (37 / 96) * Math.Pow(n, 3) - (1 / 360) * Math.Pow(n, 4) - (81 / 512) * Math.Pow(n, 5) + (96199 / 604800) * Math.Pow(n, 6) - (5406467 / 38707200) * Math.Pow(n, 7) + (7944359 / 67737600) * Math.Pow(n, 8) - (7378753979 / 97542144000) * Math.Pow(n, 9) + (25123531261 / 804722688000) * Math.Pow(n, 10), 
            beta2 = (1 / 48) * Math.Pow(n, 2) + (1 / 15) * Math.Pow(n, 3) - (437 / 1440) * Math.Pow(n, 4) + (46 / 105) * Math.Pow(n, 5) - (1118711 / 3870720) * Math.Pow(n, 6) + (51841 / 1209600) * Math.Pow(n, 7) + (24749483 / 348364800) * Math.Pow(n, 8) - (115295683 / 1397088000) * Math.Pow(n, 9) + (5487737251099 / 51502252032000) * Math.Pow(n, 10), 
            beta3 = (17 / 480) * Math.Pow(n, 3) - (37 / 840) * Math.Pow(n, 4) - (209 / 4480) * Math.Pow(n, 5) + (5569 / 90720) * Math.Pow(n, 6) + (9261899 / 58060800) * Math.Pow(n, 7) - (6457463 / 17740800) * Math.Pow(n, 8) + (2473691167 / 9289728000) * Math.Pow(n, 9) - (852549456029 / 20922789888000) * Math.Pow(n, 10), 
            beta4 = (4397 / 161280) * Math.Pow(n, 4) - (11 / 504) * Math.Pow(n, 5) - (830251 / 7257600) * Math.Pow(n, 6) + (466511 / 2494800) * Math.Pow(n, 7) + (324154477 / 7664025600) * Math.Pow(n, 8) - (937932223 / 3891888000) * Math.Pow(n, 9) - (89112264211 / 5230697472000) * Math.Pow(n, 10),
            beta5 = (4583 / 161280) * Math.Pow(n, 5) - (108847 / 3991680) * Math.Pow(n, 6) - (8005831 / 63866880) * Math.Pow(n, 7) + (22894433 / 124540416) * Math.Pow(n, 8) + (112731569449 / 557941063680) * Math.Pow(n, 9) - (5391039814733 / 10461394944000) * Math.Pow(n, 10),
            beta6 = (20648693 / 638668800) * Math.Pow(n, 6) - (16363163 / 518918400) * Math.Pow(n, 7) - (2204645983 / 12915302400) * Math.Pow(n, 8) + (4543317553 / 18162144000) * Math.Pow(n, 9) + (54894890298749 / 167382319104000) * Math.Pow(n, 10),
            beta7 = (219941297 / 5535129600) * Math.Pow(n, 7) - (497323811 / 12454041600) * Math.Pow(n, 8) - (79431132943 / 332107776000) * Math.Pow(n, 9) + (4346429528407 / 12703122432000) * Math.Pow(n, 10),
            beta8 = (191773887257 / 3719607091200) * Math.Pow(n, 8) - (17822319343 / 336825216000) * Math.Pow(n, 9) - (497155444501631 / 1422749712384000) * Math.Pow(n, 10),
            beta9 = (11025641854267 / 158083301376000) * Math.Pow(n, 9) - (492293158444691 / 6758061133824000) * Math.Pow(n, 10),
            beta10 = (7028504530429621 / 72085985427456000) * Math.Pow(n, 10),
            delta1 = 2 * n - (2 / 3) * Math.Pow(n, 2) - 2 * Math.Pow(n, 3), 
            delta2 = (7 / 3) * Math.Pow(n, 2) - (8 / 5) * Math.Pow(n, 3), 
            delta3 = (56 / 15) * Math.Pow(n, 3),
            ksi = (Northing / 100 - northernN0) / (k0 * A), eta = (Easting / 100 - E0) / (k0 * A),
            ksi_prime = ksi - (beta1 * Math.Sin(2 * ksi) * Math.Cosh(2 * eta) + beta2 * Math.Sin(4 * ksi) * Math.Cosh(4 * eta) + beta3 * Math.Sin(6 * ksi) * Math.Cosh(6 * eta) + beta4 * Math.Sin(8 * ksi) * Math.Cosh(8 * eta) + beta5 * Math.Sin(10 * ksi) * Math.Cosh(10 * eta) + 
                        beta6 * Math.Sin(12 * ksi) * Math.Cosh(12 * eta) + beta7 * Math.Sin(14 * ksi) * Math.Cosh(14 * eta) + beta8 * Math.Sin(16 * ksi) * Math.Cosh(16 * eta) + beta9 * Math.Sin(18 * ksi) * Math.Cosh(18 * eta) + beta10 * Math.Sin(20 * ksi) * Math.Cosh(20 * eta)),
            eta_prime = eta - (beta1 * Math.Cos(2 * ksi) * Math.Sinh(2 * eta) + beta2 * Math.Cos(4 * ksi) * Math.Sinh(4 * eta) + beta3 * Math.Cos(6 * ksi) * Math.Sinh(6 * eta)),
            sigma_prime = 1 - (2 * beta1 * Math.Cos(2 * ksi) * Math.Cosh(2 * eta) + 2 * beta2 * Math.Cos(4 * ksi) * Math.Cosh(4 * eta) + 2 * beta3 * Math.Cos(6 * ksi) * Math.Cosh(6 * eta)),
            taw_prime = 2 * beta1 * Math.Sin(2 * ksi) * Math.Sinh(2 * eta) + 2 * beta2 * Math.Sin(4 * ksi) * Math.Sinh(4 * eta) + 2 * beta3 * Math.Sin(6 * ksi) * Math.Sinh(6 * eta),
            ki = Math.Asin(Math.Sin(ksi_prime) / Math.Cosh(eta_prime));

        latitude = (ki + delta1 * Math.Sin(2 * ki) + delta2 * Math.Sin(4 * ki) + delta3 * Math.Sin(6 * ki)) * RtoD;
        double longitude0 = Zone * 6 * DtoR  - 183 * DtoR ;
        longitude = (longitude0 + Math.Atan(Math.Sinh(eta_prime) / Math.Cos(ksi_prime))) * RtoD;
    }

This code is far more Accurate than others.

  • 6
    You would need to explain the code and may be the source. At least justify the "far more Accurate" than others part of your answer. – Ravi Y Mar 28 '17 at 22:07
  • sources that I use to obtain these equations are: [link](https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) [link](https://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.HTM) I compared this code with some headers which are prepared for C#, and I found that these are more accurately. I also compared it with other answers in the page. – Mohammed Sadeq Ale.Isaac Apr 05 '17 at 19:06
  • 1
    Re *"I also compared it with other answers in the page."* Compared how? Do you have any specific test results that demonstrate this is more accurate? – ToolmakerSteve Nov 24 '18 at 19:01