2008-12-05 49 views
23

我有一堆UTM格式的座標文件。對於每個座標我有東,北和區。我需要將其轉換爲LatLng以與Google Map API一起使用,以便在地圖中顯示信息。如何使用python或Javascript從UTM轉換爲LatLng

我發現了一些在線計算器,但沒有實際的代碼或庫。 http://trac.osgeo.org/proj4js/是Javascript的投影庫,但在演示中不包括UTM投影。

我還是蠻新鮮的整個GIS領域,所以我要的是什麼ALA:

(lat,lng) = transform(easting, northing, zone) 

回答

34

我最終找到來自IBM的Java代碼,解決它:http://www.ibm.com/developerworks/java/library/j-coordconvert/index.html

僅供參考,這裏是我的Python實現我所需要的方法:

import math 

def utmToLatLng(zone, easting, northing, northernHemisphere=True): 
    if not northernHemisphere: 
     northing = 10000000 - northing 

    a = 6378137 
    e = 0.081819191 
    e1sq = 0.006739497 
    k0 = 0.9996 

    arc = northing/k0 
    mu = arc/(a * (1 - math.pow(e, 2)/4.0 - 3 * math.pow(e, 4)/64.0 - 5 * math.pow(e, 6)/256.0)) 

    ei = (1 - math.pow((1 - e * e), (1/2.0)))/(1 + math.pow((1 - e * e), (1/2.0))) 

    ca = 3 * ei/2 - 27 * math.pow(ei, 3)/32.0 

    cb = 21 * math.pow(ei, 2)/16 - 55 * math.pow(ei, 4)/32 
    cc = 151 * math.pow(ei, 3)/96 
    cd = 1097 * math.pow(ei, 4)/512 
    phi1 = mu + ca * math.sin(2 * mu) + cb * math.sin(4 * mu) + cc * math.sin(6 * mu) + cd * math.sin(8 * mu) 

    n0 = a/math.pow((1 - math.pow((e * math.sin(phi1)), 2)), (1/2.0)) 

    r0 = a * (1 - e * e)/math.pow((1 - math.pow((e * math.sin(phi1)), 2)), (3/2.0)) 
    fact1 = n0 * math.tan(phi1)/r0 

    _a1 = 500000 - easting 
    dd0 = _a1/(n0 * k0) 
    fact2 = dd0 * dd0/2 

    t0 = math.pow(math.tan(phi1), 2) 
    Q0 = e1sq * math.pow(math.cos(phi1), 2) 
    fact3 = (5 + 3 * t0 + 10 * Q0 - 4 * Q0 * Q0 - 9 * e1sq) * math.pow(dd0, 4)/24 

    fact4 = (61 + 90 * t0 + 298 * Q0 + 45 * t0 * t0 - 252 * e1sq - 3 * Q0 * Q0) * math.pow(dd0, 6)/720 

    lof1 = _a1/(n0 * k0) 
    lof2 = (1 + 2 * t0 + Q0) * math.pow(dd0, 3)/6.0 
    lof3 = (5 - 2 * Q0 + 28 * t0 - 3 * math.pow(Q0, 2) + 8 * e1sq + 24 * math.pow(t0, 2)) * math.pow(dd0, 5)/120 
    _a2 = (lof1 - lof2 + lof3)/math.cos(phi1) 
    _a3 = _a2 * 180/math.pi 

    latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4))/math.pi 

    if not northernHemisphere: 
     latitude = -latitude 

    longitude = ((zone > 0) and (6 * zone - 183.0) or 3.0) - _a3 

    return (latitude, longitude) 

在這裏,我還以爲是什麼簡單的東東x +區域Ÿ什麼的。

+3

我不會責怪你認爲這件事很簡單。我上週從Lat/Lon轉換爲Miller Projection的Easting/Northing,我仍然在裏面慶祝。 – wonderchook 2008-12-07 05:07:01

10

我發現什麼是以下站點:http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html 它有一個javascript轉換器,你應該檢查算法。來自頁面:

程序員:本文檔中的JavaScript源代碼可能會被無限制地複製和重複使用。

+1

這是最乾淨的Javascript版本我都看到了。 – 2012-06-28 17:56:27

+0

正如@monkut的回答中所提到的,python.org包含了來自python的GDAL的Swig綁定:https://pypi.python.org/pypi/GDAL – ToolmakerSteve 2014-03-10 18:18:05

8

根據此頁面,UTM由proj4js支持。

http://trac.osgeo.org/proj4js/wiki/UserGuide#Supportedprojectionclasses

您可能還需要看一看GDAL。 gdal庫具有出色的python支持,但如果您只進行投影轉換,它可能有點矯枉過正。

+0

+1 PROJ4幾乎可以做你夢寐以求的任何事情,所以如果proj4js是一個真正的港口,它也可以做到。 – MarkJ 2009-07-13 08:13:23

+0

+1 proj4s是要走的路。沒有重新發明輪子.. proj4s讀取配置文件,可以有任何投影添加 - 鍵入參考到http://www.spatialreference.org/獲得proj4js字符串例如http://www.spatialreference.org/ref/epsg/4326/proj4js/ – geographika 2010-02-17 02:31:07

0

有一個perl模塊可以通過CPAN調用Geography :: NationalGrid,它可以將easting/northing轉換爲lat/longs。這可能有幫助。

或者,movable-type site上有很多腳本可讓您將lat/long和easting/northings轉換。

1
//////////////////////////////////////////////////////////////////////////////////////////// 
// 
// ToLL - function to compute Latitude and Longitude given UTM Northing and Easting in meters 
// 
// Description: 
// This member function converts input north and east coordinates 
// to the corresponding Northing and Easting values relative to the defined 
// UTM zone. Refer to the reference in this file's header. 
// 
// Parameters: 
// north - (i) Northing (meters) 
// east - (i) Easting (meters) 
// utmZone - (i) UTM Zone of the North and East parameters 
// lat  - (o) Latitude in degrees 
// lon  - (o) Longitude in degrees 
// 
function ToLL(north,east,utmZone) 
{ 
    // This is the lambda knot value in the reference 
    var LngOrigin = DegToRad(utmZone * 6 - 183) 

    // The following set of class constants define characteristics of the 
    // ellipsoid, as defined my the WGS84 datum. These values need to be 
    // changed if a different dataum is used.  

    var FalseNorth = 0. // South or North? 
    //if (lat < 0.) FalseNorth = 10000000. // South or North? 
    //else   FalseNorth = 0. 

    var Ecc = 0.081819190842622  // Eccentricity 
    var EccSq = Ecc * Ecc 
    var Ecc2Sq = EccSq/(1. - EccSq) 
    var Ecc2 = Math.sqrt(Ecc2Sq)  // Secondary eccentricity 
    var E1 = (1 - Math.sqrt(1-EccSq))/(1 + Math.sqrt(1-EccSq)) 
    var E12 = E1 * E1 
    var E13 = E12 * E1 
    var E14 = E13 * E1 

    var SemiMajor = 6378137.0   // Ellipsoidal semi-major axis (Meters) 
    var FalseEast = 500000.0   // UTM East bias (Meters) 
    var ScaleFactor = 0.9996   // Scale at natural origin 

    // Calculate the Cassini projection parameters 

    var M1 = (north - FalseNorth)/ScaleFactor 
    var Mu1 = M1/(SemiMajor * (1 - EccSq/4.0 - 3.0*EccSq*EccSq/64.0 - 
    5.0*EccSq*EccSq*EccSq/256.0)) 

    var Phi1 = Mu1 + (3.0*E1/2.0 - 27.0*E13/32.0) * Math.sin(2.0*Mu1) 
    + (21.0*E12/16.0 - 55.0*E14/32.0)   * Math.sin(4.0*Mu1) 
    + (151.0*E13/96.0)       * Math.sin(6.0*Mu1) 
    + (1097.0*E14/512.0)      * Math.sin(8.0*Mu1) 

    var sin2phi1 = Math.sin(Phi1) * Math.sin(Phi1) 
    var Rho1 = (SemiMajor * (1.0-EccSq))/Math.pow(1.0-EccSq*sin2phi1,1.5) 
    var Nu1 = SemiMajor/Math.sqrt(1.0-EccSq*sin2phi1) 

    // Compute parameters as defined in the POSC specification. T, C and D 

    var T1 = Math.tan(Phi1) * Math.tan(Phi1) 
    var T12 = T1 * T1 
    var C1 = Ecc2Sq * Math.cos(Phi1) * Math.cos(Phi1) 
    var C12 = C1 * C1 
    var D = (east - FalseEast)/(ScaleFactor * Nu1) 
    var D2 = D * D 
    var D3 = D2 * D 
    var D4 = D3 * D 
    var D5 = D4 * D 
    var D6 = D5 * D 

    // Compute the Latitude and Longitude and convert to degrees 
    var lat = Phi1 - Nu1*Math.tan(Phi1)/Rho1 * 
    (D2/2.0 - (5.0 + 3.0*T1 + 10.0*C1 - 4.0*C12 - 9.0*Ecc2Sq)*D4/24.0 
    + (61.0 + 90.0*T1 + 298.0*C1 + 45.0*T12 - 252.0*Ecc2Sq - 3.0*C12)*D6/720.0) 

    lat = RadToDeg(lat) 

    var lon = LngOrigin + 
    (D - (1.0 + 2.0*T1 + C1)*D3/6.0 
     + (5.0 - 2.0*C1 + 28.0*T1 - 3.0*C12 + 8.0*Ecc2Sq + 24.0*T12)*D5/120.0)/Math.cos(Phi1) 

    lon = RadToDeg(lon) 

    // Create a object to store the calculated Latitude and Longitude values 
    var sendLatLon = new PC_LatLon(lat,lon) 

    // Returns a PC_LatLon object 
    return sendLatLon 
} 

//////////////////////////////////////////////////////////////////////////////////////////// 
// 
// RadToDeg - function that inputs a value in radians and returns a value in degrees 
// 
function RadToDeg(value) 
{ 
    return (value * 180.0/Math.PI) 
} 

//////////////////////////////////////////////////////////////////////////////////////////// 
// 
// PC_LatLon - this psuedo class is used to store lat/lon values computed by the ToLL 
// function. 
// 
function PC_LatLon(inLat,inLon) 
{ 
    this.lat  = inLat  // Store Latitude in decimal degrees 
    this.lon  = inLon  // Store Longitude in decimal degrees 
} 
6

我對此也很陌生,最近一直在研究這個問題。

這是我發現使用python gdal pacakge(osr軟件包包含在gdal中)的方法。 gdal包非常強大,但文檔可能會更好。

這是從這裏的討論得出: http://www.mail-archive.com/[email protected]/msg12398.html

import osr 

def transform_utm_to_wgs84(easting, northing, zone): 
    utm_coordinate_system = osr.SpatialReference() 
    utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon 
    is_northern = northing > 0  
    utm_coordinate_system.SetUTM(zone, is_northern) 

    wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system 

    # create transform component 
    utm_to_wgs84_transform = osr.CoordinateTransformation(utm_coordinate_system, wgs84_coordinate_system) # (<from>, <to>) 
    return utm_to_wgs84_transform.TransformPoint(easting, northing, 0) # returns lon, lat, altitude 

下面是從經緯度轉換,經度WGS84座標(大多數GPS單位報告)爲UTM的方法:

def transform_wgs84_to_utm(lon, lat):  
    def get_utm_zone(longitude): 
     return (int(1+(longitude+180.0)/6.0)) 

    def is_northern(latitude): 
     """ 
     Determines if given latitude is a northern for UTM 
     """ 
     if (latitude < 0.0): 
      return 0 
     else: 
      return 1 

    utm_coordinate_system = osr.SpatialReference() 
    utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon 
    utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat)) 

    wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system 

    # create transform component 
    wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>) 
    return wgs84_to_utm_transform.TransformPoint(lon, lat, 0) # returns easting, northing, altitude  

我還發現,如果您已經安裝了django/gdal,並且您知道正在處理的UTM區域的EPSG代碼,則可以使用Point()transform()方法。

from django.contrib.gis.geos import Point 
utm2epsg = {"54N": 3185, ...} 
p = Point(lon, lat, srid=4326) # 4326 = WGS84 epsg code 
p.transform(utm2epsg["54N"]) 
4

您可以使用Proj4js,如下所示。

從GitHub下載Proj4JS,使用this鏈接。

下面的代碼將從UTM轉換爲經度緯度

<html> 
<head> 
    <script src="proj4.js"></script> 

    <script> 
    var utm = "+proj=utm +zone=32"; 
    var wgs84 = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; 
    console.log(proj4(utm,wgs84,[539884, 4942158])); 
    </script> 
</head> 
<body> 

</body> 
</html> 

在該代碼中,UTM區是32,如應該是顯而易見的。東距是539884,而北向爲4942158.其結果是:

[9.502832656648073, 44.631671014204365] 

這就是說44.631671014204365N,9.502832656648073E。我有verified是正確的。

如果您需要其他投影,您可以找到他們的字符串here。 Staale的

3

JavaScript版本回答

function utmToLatLng(zone, easting, northing, northernHemisphere){ 
     if (!northernHemisphere){ 
      northing = 10000000 - northing; 
     } 

     var a = 6378137; 
     var e = 0.081819191; 
     var e1sq = 0.006739497; 
     var k0 = 0.9996; 

     var arc = northing/k0; 
     var mu = arc/(a * (1 - Math.pow(e, 2)/4.0 - 3 * Math.pow(e, 4)/64.0 - 5 * Math.pow(e, 6)/256.0)); 

     var ei = (1 - Math.pow((1 - e * e), (1/2.0)))/(1 + Math.pow((1 - e * e), (1/2.0))); 

     var ca = 3 * ei/2 - 27 * Math.pow(ei, 3)/32.0; 

     var cb = 21 * Math.pow(ei, 2)/16 - 55 * Math.pow(ei, 4)/32; 
     var cc = 151 * Math.pow(ei, 3)/96; 
     var cd = 1097 * Math.pow(ei, 4)/512; 
     var phi1 = mu + ca * Math.sin(2 * mu) + cb * Math.sin(4 * mu) + cc * Math.sin(6 * mu) + cd * Math.sin(8 * mu); 

     var n0 = a/Math.pow((1 - Math.pow((e * Math.sin(phi1)), 2)), (1/2.0)); 

     var r0 = a * (1 - e * e)/Math.pow((1 - Math.pow((e * Math.sin(phi1)), 2)), (3/2.0)); 
     var fact1 = n0 * Math.tan(phi1)/r0; 

     var _a1 = 500000 - easting; 
     var dd0 = _a1/(n0 * k0); 
     var fact2 = dd0 * dd0/2; 

     var t0 = Math.pow(Math.tan(phi1), 2); 
     var Q0 = e1sq * Math.pow(Math.cos(phi1), 2); 
     var fact3 = (5 + 3 * t0 + 10 * Q0 - 4 * Q0 * Q0 - 9 * e1sq) * Math.pow(dd0, 4)/24; 

     var fact4 = (61 + 90 * t0 + 298 * Q0 + 45 * t0 * t0 - 252 * e1sq - 3 * Q0 * Q0) * Math.pow(dd0, 6)/720; 

     var lof1 = _a1/(n0 * k0); 
     var lof2 = (1 + 2 * t0 + Q0) * Math.pow(dd0, 3)/6.0; 
     var lof3 = (5 - 2 * Q0 + 28 * t0 - 3 * Math.pow(Q0, 2) + 8 * e1sq + 24 * Math.pow(t0, 2)) * Math.pow(dd0, 5)/120; 
     var _a2 = (lof1 - lof2 + lof3)/Math.cos(phi1); 
     var _a3 = _a2 * 180/Math.PI; 

     var latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4))/Math.PI; 

     if (!northernHemisphere){ 
      latitude = -latitude; 
     } 

     var longitude = ((zone > 0) && (6 * zone - 183.0) || 3.0) - _a3; 

     var obj = { 
       latitude : latitude, 
       longitude: longitude 
     }; 


     return obj; 
     } 
0

一個問題,我與使用proj4js是,它所需的確切區域作爲@Richard指出。我發現了一個巨大的資源here可以WGS轉換爲UTM和寫在JavaScript中一個更清潔的包裝:

https://github.com/urbanetic/utm-converter