Conversione da longitudine \ latitudine a coordinate cartesiane


103

Ho alcuni punti di coordinate centrati sulla terra dati come latitudine e longitudine ( WGS-84 ).

Come posso convertirli in coordinate cartesiane (x, y, z) con l'origine al centro della terra?


1
Sei riuscito a convertire la longitudine e la latitudine di WGS-84 in coordinate cartesiane? Ho anche l'elevazione. Ho provato la risposta accettata qui, ma non mi dà la risposta giusta. Ho confrontato i miei risultati con questo sito web: apsalin.com/convert-geodetic-to-cartesian.aspx .
Yasmin

Risposte:


46

Recentemente ho fatto qualcosa di simile a questo utilizzando la "Formula Haversine" sui dati WGS-84, che è un derivato della "Legge di Haversines" con risultati molto soddisfacenti.

Sì, WGS-84 presume che la Terra sia un ellissoide, ma credo che si ottenga solo un errore medio dello 0,5% circa usando un approccio come la "Formula di Haversine", che potrebbe essere una quantità di errore accettabile nel tuo caso. Avrai sempre una certa quantità di errore a meno che tu non stia parlando di una distanza di pochi piedi e anche allora teoricamente c'è una curvatura della Terra ... Se hai bisogno di un approccio più rigido compatibile con WGS-84 controlla la "Formula Vincenty".

Capisco da dove viene starblue , ma una buona ingegneria del software è spesso una questione di compromessi, quindi tutto dipende dalla precisione richiesta per ciò che stai facendo. Ad esempio, il risultato calcolato dalla "Formula della distanza di Manhattan" rispetto al risultato della "Formula della distanza" può essere migliore per determinate situazioni in quanto è meno costoso dal punto di vista del calcolo. Pensa "qual è il punto più vicino?" scenari in cui non è necessaria una misurazione precisa della distanza.

Per quanto riguarda la "Formula Haversine" è facile da implementare ed è piacevole perché utilizza la "Trigonometria Sferica" ​​invece di un approccio basato sulla "Legge dei Coseni" che si basa sulla trigonometria bidimensionale, quindi si ottiene un buon equilibrio di accuratezza oltre la complessità.

Un gentiluomo di nome Chris Veness ha un ottimo sito web all'indirizzo http://www.mohable-type.co.uk/scripts/latlong.html che spiega alcuni dei concetti che ti interessano e mostra varie implementazioni programmatiche; questo dovrebbe rispondere anche alla tua domanda di conversione x / y.


1
Errore dello 0,5% - 0,5% di cosa? Nel contesto di questa domanda potrebbe essere il raggio della terra, quindi lo 0,5% potrebbe essere 30 km :)
MarkJ

2
Ho controllato il tuo collegamento. La quota dello 0,5% è per l'errore nella distanza del cerchio grande tra due punti, quindi non strettamente pertinente a questa domanda. Quando si converte lat-long in coordinate cartesiane con l'origine al centro della terra, gli errori derivanti dall'assunzione di una terra sferica potrebbero essere significativi. Non è chiaro cosa voglia fare l'interrogante con le coordinate cartesiane. O è solo più comodo lavorarci per qualche motivo bizzarro, o forse è un requisito per l'esportazione dei dati? In quest'ultimo caso, la precisione sarebbe importante.
MarkJ

130

Ecco la risposta che ho trovato:

Giusto per completare la definizione, nel sistema di coordinate cartesiane:

  • l'asse x passa per long, lat (0,0), quindi la longitudine 0 incontra l'equatore;
  • l'asse y passa per (0,90);
  • e l'asse z passa attraverso i poli.

La conversione è:

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)

Dove R è il raggio approssimativo della terra (ad esempio 6371 km).

Se le tue funzioni trigonometriche si aspettano i radianti (cosa che probabilmente fanno), dovrai prima convertire la tua longitudine e latitudine in radianti. Ovviamente hai bisogno di una rappresentazione decimale, non di gradi \ minuti \ secondi (vedi ad esempio qui sulla conversione).

La formula per la conversione all'indietro:

   lat = asin(z / R)
   lon = atan2(y, x)

asin è ovviamente arco seno. leggi di atan2 su wikipedia . Non dimenticare di riconvertire da radianti a gradi.

Questa pagina fornisce il codice c # per questo (nota che è molto diverso dalle formule), e anche alcune spiegazioni e un bel diagramma del perché questo è corretto,


17
-1 Questo è sbagliato. Stai assumendo che la Terra sia una sfera, mentre WGS-84 assume un ellissoide.
starblue

42
@starblue: non sono sicuro che tu sia in grado di etichettare la risposta data "giusta" o "sbagliata". L'approssimazione sferica (per ottenere coordinate x, y, z in stile ECEF) utilizzando lat / lng disponibili (che fanno riferimento a WGS-84) è "adeguata" per le esigenze del poster originale o "non adeguata". Per le stime di distanza e rilevamento, scommetto che questa semplice conversione va bene. Se sta lanciando satelliti, forse no. Dopotutto, lo stesso WGS-84 è "sbagliato" ... in quanto non è un modello perfetto della superficie terrestre; tutti i modelli ellissoidali sono approssimazioni. Peccato che l'OP non ci abbia detto cosa stava cercando di fare.
Dan H

11
@ Dan H La domanda chiede WGS-84, e se rispondi a qualcos'altro dovresti almeno discutere le differenze / errori, cosa che questa risposta non fa.
starblue

@ daphna-shezaf non posso fare una conversione all'indietro ... ho fatto anche il retro da radianti a gradi, ma il risultato non è lo stesso ...

grazie, passa ore a capire perché non funziona, risulta che ho scambiato un po 'di cos (lat) e sin (lat)
aeroson

6

Teoria per la conversione GPS(WGS84)in coordinate cartesiane https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates

Quanto segue è quello che sto usando:

  • La longitudine in GPS (WGS84) e le coordinate cartesiane sono le stesse.
  • La latitudine deve essere convertita dai parametri ellissoidi WGS 84 semiasse maggiore è 6378137 m, e
  • Il reciproco dell'appiattimento è 298.257223563.

Ho allegato un codice VB che ho scritto:

Imports System.Math

'Input GPSLatitude is WGS84 Latitude,h is altitude above the WGS 84 ellipsoid

Public Function GetSphericalLatitude(ByVal GPSLatitude As Double, ByVal h As Double) As Double

        Dim A As Double = 6378137 'semi-major axis 
        Dim f As Double = 1 / 298.257223563  '1/f Reciprocal of flattening
        Dim e2 As Double = f * (2 - f)
        Dim Rc As Double = A / (Sqrt(1 - e2 * (Sin(GPSLatitude * PI / 180) ^ 2)))
        Dim p As Double = (Rc + h) * Cos(GPSLatitude * PI / 180)
        Dim z As Double = (Rc * (1 - e2) + h) * Sin(GPSLatitude * PI / 180)
        Dim r As Double = Sqrt(p ^ 2 + z ^ 2)
        Dim SphericalLatitude As Double =  Asin(z / r) * 180 / PI
        Return SphericalLatitude
End Function

Si prega di notare che l' haltitudine è superiore a WGS 84 ellipsoid.

Di solito GPSci darà un'altezza Hsuperiore MSL. L' MSLaltezza deve essere convertita in altezza hsopra il WGS 84 ellipsoidutilizzando il modello geopotenzialeEGM96 ( Lemoine et al, 1998 ).
Ciò viene fatto interpolando una griglia del file di altezza del geoide con una risoluzione spaziale di 15 minuti d'arco.

Oppure se hai qualche livello professionale GPS ha Altitudine H( msl, altezza sopra il livello medio del mare ) e UNDULATION, il rapporto tra il geoide il ellipsoid (m)del dato scelto in uscita dalla tabella interna. Puoi prendereh = H(msl) + undulation

A XYZ per coordinate cartesiane:

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)

Qual è il valore di R?
eych

4
Immagino sia il raggio della sfera, che è 6371 km per la terra.
Matthias

5

Il software proj.4 fornisce un programma a riga di comando che può eseguire la conversione, ad es

LAT=40
LON=-110
echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84

Esso fornisce anche un'API C . In particolare, la funzione pj_geodetic_to_geocentriceseguirà la conversione senza dover prima impostare un oggetto di proiezione.


5

In python3.x può essere fatto usando:

# Converting lat/long to cartesian
import numpy as np

def get_cartesian(lat=None,lon=None):
    lat, lon = np.deg2rad(lat), np.deg2rad(lon)
    R = 6371 # radius of the earth
    x = R * np.cos(lat) * np.cos(lon)
    y = R * np.cos(lat) * np.sin(lon)
    z = R *np.sin(lat)
    return x,y,z

3

Se ti interessa ottenere coordinate basate su un ellissoide piuttosto che su una sfera, dai un'occhiata a http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - fornisce le formule e le costanti WGS84 necessarie per la conversione .

Le formule tengono anche conto dell'altitudine relativa alla superficie dell'ellissoide di riferimento (utile se si ottengono dati di altitudine da un dispositivo GPS).


Upvoting anche se non hai pubblicato il contenuto del collegamento qui.
Fisico pazzo

2

Perché implementare qualcosa che è già stato implementato e testato?

C #, per esempio, ha NetTopologySuite che è il port .NET di JTS Topology Suite.

Nello specifico, hai un grave difetto nel tuo calcolo. La terra non è una sfera perfetta e l' approssimazione del raggio terrestre potrebbe non tagliarla per misurazioni precise.

Se in alcuni casi è accettabile utilizzare le funzioni homebrew, GIS è un buon esempio di un campo in cui è di gran lunga preferito utilizzare una libreria affidabile e collaudata.


1
+1. L'uso di una libreria affidabile è più preciso di una funzione homebrew e anche più semplice .
MarkJ

5
In che modo NetTopologySuite converte da long / late a cartesion?
Vinayan

1
NTS non include funzionalità di conversione delle coordinate, forse è necessario Proj.NET projnet.codeplex.com
D_Guidi

6
Ridicolo, la risposta non fornisce nemmeno la capacità di conversione.
Motes

1
Coordinate[] coordinates = new Coordinate[3];
coordinates[0] = new Coordinate(102, 26);
coordinates[1] = new Coordinate(103, 25.12);
coordinates[2] = new Coordinate(104, 16.11);
CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates);

Geometry geo = new LineString(coordinateSequence, geometryFactory);

CoordinateReferenceSystem wgs84 = DefaultGeographicCRS.WGS84;
CoordinateReferenceSystem cartesinaCrs = DefaultGeocentricCRS.CARTESIAN;

MathTransform mathTransform = CRS.findMathTransform(wgs84, cartesinaCrs, true);

Geometry geo1 = JTS.transform(geo, mathTransform);

Saresti in grado di elaborare? Ho creato una semplice applicazione che consente di trasformare una singola coordinata utilizzando il tuo approccio. Tuttavia, fallisce sempre poiché le dimensioni della sorgente (2) e le dimensioni della destinazione (3) differiscono, risultando in un'eccezionejava.lang.IllegalArgumentException: dimension must be <= 3
oschrenk

Hmmm ... ho guardato JTS per un po '. Le righe fino al nuovo LineString () incluso sembrano JTS. Ma non vedo il CRS e il materiale Transform in JTS. Quindi: ci sono e mi mancano? C'erano e sono stati rimossi nella 1.12? Oppure: è una libreria diversa?
Dan H

0

Puoi farlo in questo modo su Java.

public List<Double> convertGpsToECEF(double lat, double longi, float alt) {

    double a=6378.1;
    double b=6356.8;
    double N;
    double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
    N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
    double cosLatRad=Math.cos(Math.toRadians(lat));
    double cosLongiRad=Math.cos(Math.toRadians(longi));
    double sinLatRad=Math.sin(Math.toRadians(lat));
    double sinLongiRad=Math.sin(Math.toRadians(longi));
    double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
    double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
    double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;

    List<Double> ecef= new ArrayList<>();
    ecef.add(x);
    ecef.add(y);
    ecef.add(z);

    return ecef;


}

cos'è il parametro alt?
baliman

altitudine, cosa ci fai qui se non sai come funziona il GPS;)
MushyPeas
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.