2008-12-05 313 views
23

Tengo un montón de archivos con coordenadas en forma UTM. Para cada coordenada tengo easting, northing y zone. Necesito convertir esto a LatLng para utilizarlo con Google Map API para mostrar la información en un mapa.Cómo convertir de UTM a LatLng en python o Javascript

He encontrado algunas calculadoras en línea que hacen esto, pero no hay códigos reales o bibliotecas. http://trac.osgeo.org/proj4js/ es una biblioteca de proyección para Javascript, pero al mirar la demostración no incluye proyección UTM.

todavía estoy bastante fresco a todo el dominio SIG, así que lo que quiero es algo Ala:

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

Respuesta

34

que acabamos encontrando el código de Java de IBM que lo resolvió: http://www.ibm.com/developerworks/java/library/j-coordconvert/index.html

Sólo como referencia, aquí está mi aplicación pitón del método que necesitaba:

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) 

Y yo que pensaba que era algo simple como easting x + zona y o algo.

+3

No te culpo por pensar que fue algo simple. Me convertí la semana pasada de Lat/Lon a Easting/Northing para Miller Projection y todavía estoy celebrando dentro. – wonderchook

+0

¿Por qué su función requiere zona? ¿No deberías solo necesitar el este, el hemisferio norte? –

+1

@Franki: Porque las coordenadas UTM son relativas a las zonas predefinidas. [UTM en Wikipedia] (http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system). – Hubro

10

Lo que encontré es el sitio siguiente: http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html Tiene un conversor javascript, usted debe comprobar la algoritmo allí. De la página:

Programadores: El código fuente de JavaScript en este documento se puede copiar y reutilizar sin restricción.

+1

Esta es la versión más limpio que he visto Javascript. –

+0

Como se menciona en la respuesta de @monkut, python.org incluye las vinculaciones Swig de GDAL de python: https://pypi.python.org/pypi/GDAL – ToolmakerSteve

8

De acuerdo con esta página, UTM es compatible con proj4js.

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

También es posible que desee echar un vistazo a GDAL. La biblioteca de gdal tiene una excelente compatibilidad con Python, aunque puede ser un poco exagerado si solo realizas una conversión de proyección.

+0

+1 PROJ4 puede hacer casi cualquier cosa que haya soñado, así que si proj4js es un verdadero puerto, también podrá hacerlo. – MarkJ

+0

+1 proj4s es el camino a seguir. no hay punto para reinventar la rueda ... el proj4s lee desde un archivo de configuración que puede tener cualquier proyección añadida - escriba la referencia en http://www.spatialreference.org/ para obtener una cadena proj4js, p. http://www.spatialreference.org/ref/epsg/4326/proj4js/ – geographika

0

Hay un módulo perl a través de CPAN llamado Geography :: NationalGrid que puede convertir easting/northing a lat/longs. Eso puede ayudar.

Alternativamente, hay muchas secuencias de comandos en el movable-type site que le permiten convertir lat/long y 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 
} 
+0

Falta el método DegToRad – NSCoder

6

Soy nuevo en esto también y he estado estudiando sobre el tema recientemente.

Aquí hay un método que encontré usando el paquete python gdal (el paquete osr está incluido en gdal). El paquete de gdal es bastante poderoso, pero la documentación podría ser mejor.

Esto se deriva de una discusión aquí: 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 

Y aquí está el método para la conversión de un lat, lon en WGS84 (lo más informe de las unidades de GPS) a 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  

También encontré que si ya tiene instalado django/gdal y conoce el código EPSG para la zona UTM en la que está trabajando, puede usar la transformada Point()() método.

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

Puede usar Proj4js, como se indica a continuación.

Descargue Proj4JS desde GitHub, usando el enlace this.

El siguiente código convertir de UTM a latitud longitud

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

En este código, la zona UTM es 32, como debería ser evidente. El Easting es 539884, y la Coordenada Y es 4942158. El resultado es:

[9.502832656648073, 44.631671014204365] 

es decir 44.631671014204365N, 9.502832656648073E. Que tengo verified es correcto.

Si necesita otras proyecciones, puede encontrar sus cadenas here.

+0

¿Qué pasa con South of Equator o no? –

3

Una versión de Javascript Staale responder

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

Uno de los problemas que tuve con el uso de proj4js era que se necesitaba la zona exacta como señala @Richard. He encontrado un gran recurso here que puede convertir a WGS UTM y escribí un envoltorio más limpio en JavaScript:

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