将UTM(wsg84)坐标转换为纬度和经度

18

我已经搜索了一段时间(在这里和Google上),想找一个简单的方法将一组UTM坐标转换为纬度和经度。我有这些坐标,也知道它们所在的区域,但是如何将其转换为纬度和经度呢?我希望有某种类可以至少帮助我完成部分工作,但似乎并没有 :(

对此有什么建议吗?

我知道这是可行的,因为这个转换器看起来很好用 地理/UTM坐标转换器

非常感谢您的任何意见!:)

谢谢!


两个都是好答案!:) 非常感谢。我通过查找给定地址的纬度和经度来稍微修改了它。虽然这不是最整洁的编程方式,但它可以完成工作。不过我打算探索一下ProjNet库。再次感谢 :) - bomortensen
6个回答

22

这里是:

 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;
    }

3
谢谢 Playful! 我只是为了在巴西使用而更改这些行。bool isNorthHemisphere = utmZone.Last() == 'N' ? true : false;var diflat = 0.00006286966871111111111111111111111111; //-0.00066286966871111111111111111111111111; var diflon = -0.0003868060578; - Jonathan Molina
1
我在long变量中有1.6+的差异。你能解释一下s、v、a、a1、a2、j2、j4等变量吗?根据我的位置,可能会有不同的值,如下所示: 角度单位:度(0.017453292519943299) 中央经线:55.333333 反扁率:298.257223563 - Adeem

13

3
请问您指的转换器属于哪个类别?请帮忙。 - Vahid Akbari
ProjNet已从Codeplex迁移到GitHub: https://github.com/dotMorten/ProjNET 也许 https://github.com/NetTopologySuite/ProjNet4GeoAPI 会更加有趣。 - DrMarbuse

4
该网站上有C++代码可用: http://www.gpsy.com/gpsinfo/geotoutm/ 向下滚动页面到“源代码”标题,并在底部查找这些文件: Chuck Gantz
附件:LatLong-UTMconversion.cpp(作为文本文件在线查看) LatLong-UTMconversion.h(作为文本文件在线查看) UTMConversions.cpp(作为文本文件在线查看) SwissGrid.cpp(作为文本文件在线查看) constants.h(作为文本文件在线查看)
例如,第一个文件链接至: www.gpsy.com/gpsinfo/geotoutm/gantz/LatLong-UTMconversion.cpp 等等。
这里有函数可以实现双向转换:UTM到Lat Long,反之亦然。如果您在其他地方查看,还有该代码的Python版本,例如: at code.google.com/p/pys60gps/source/browse/trunk/lib/LatLongUTMconversion.py?r=246
此外,还有一些C#版本: at mediakey.dk/~cc/convert-northing-and-easting-utm-to-longitude-and-latitude/
祝好运。

4

我把一个JavaScript库移植到了C#,已经测试过并且完美运行。你可以在这里查看。


警告:您的端口存在错误;我已经使用不同的在线转换器进行了测试。 - John Silence
抱歉,我还没有时间来纠正它,据我所知,latlng转utm的功能是正常的,你能帮忙让它正确地工作吗? - oware

1

在NuGet上查看CoordinateSharp。使用它非常容易。

 //Example
 UniversalTransverseMercator utm = new UniversalTransverseMercator("Q", 14, 581943.5, 2111989.8);
 Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm);

请注意,此内容为付费商业使用。 - Harison Silva
只有商业软件是闭源的情况下才需要付费。如果不是,那么只需支付一次小费即可终身使用并进行无限分发。 - Tronald

0
请使用以下代码:
     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;
    }

这段代码比其他代码更准确。


7
您需要解释代码并可能提供源代码。至少要证明您回答中的“比其他方法更准确”这部分是合理的。 - Ravi Y
我用来获得这些方程式的来源是: 链接 链接 我将此代码与为C#准备的某些头文件进行了比较,发现这些更为精确。我还将其与页面上其他答案进行了比较。 - Mohammed Sadeq Ale.Isaac
2
我也与页面上的其他答案进行了比较。你是如何进行比较的?你有任何具体的测试结果可以证明这更准确吗? - ToolmakerSteve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接