Ich habe einige erdzentrierte Koordinatenpunkte als Breiten- und Längengrad ( WGS-84 ).
Wie kann ich sie in kartesische Koordinaten (x, y, z) mit dem Ursprung im Erdmittelpunkt umwandeln?
Ich habe einige erdzentrierte Koordinatenpunkte als Breiten- und Längengrad ( WGS-84 ).
Wie kann ich sie in kartesische Koordinaten (x, y, z) mit dem Ursprung im Erdmittelpunkt umwandeln?
Antworten:
Ich habe kürzlich etwas Ähnliches mit der "Haversine-Formel" für WGS-84-Daten gemacht, die eine Ableitung des "Gesetzes der Haversine" mit sehr zufriedenstellenden Ergebnissen ist.
Ja, WGS-84 geht davon aus, dass die Erde ein Ellipsoid ist, aber ich glaube, dass Sie mit einem Ansatz wie der "Haversine-Formel" nur einen durchschnittlichen Fehler von etwa 0,5% erhalten, was in Ihrem Fall eine akzeptable Fehlermenge sein kann. Sie werden immer eine gewisse Fehlerquote haben, es sei denn, Sie sprechen von einer Entfernung von einigen Fuß und selbst dann gibt es theoretisch eine Krümmung der Erde ... Wenn Sie einen strengeren WGS-84-kompatiblen Ansatz benötigen, lesen Sie die "Vincenty-Formel".
Ich verstehe, woher Starblue kommt, aber bei guter Softwareentwicklung geht es oft um Kompromisse. Daher hängt alles von der Genauigkeit ab, die Sie für Ihre Arbeit benötigen. Beispielsweise kann das aus der "Manhattan Distance Formula" berechnete Ergebnis gegenüber dem Ergebnis aus der "Distance Formula" für bestimmte Situationen besser sein, da es rechnerisch kostengünstiger ist. Überlegen Sie: "Welcher Punkt ist am nächsten?" Szenarien, in denen Sie keine genaue Entfernungsmessung benötigen.
In Bezug auf die "Haversine-Formel" ist sie einfach zu implementieren und gut, da sie "sphärische Trigonometrie" anstelle eines "Law of Cosines" -basierten Ansatzes verwendet, der auf zweidimensionaler Trigonometrie basiert. Daher erhalten Sie ein gutes Gleichgewicht der Genauigkeit über Komplexität.
Ein Gentlemen namens Chris Veness hat eine großartige Website unter http://www.movable-type.co.uk/scripts/latlong.html , die einige der Konzepte erklärt, an denen Sie interessiert sind, und verschiedene programmatische Implementierungen demonstriert. Dies sollte auch Ihre X / Y-Konvertierungsfrage beantworten.
Hier ist die Antwort, die ich gefunden habe:
Nur um die Definition im kartesischen Koordinatensystem zu vervollständigen:
Die Konvertierung ist:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
Wobei R der ungefähre Erdradius ist (z. B. 6371 km).
Wenn Ihre trigonometrischen Funktionen Bogenmaß erwarten (was sie wahrscheinlich tun), müssen Sie zuerst Ihren Längen- und Breitengrad in Bogenmaß umrechnen. Sie benötigen offensichtlich eine Dezimaldarstellung, nicht Grad \ Minuten \ Sekunden (siehe z. B. hier zur Konvertierung).
Die Formel für die Rückkonvertierung:
lat = asin(z / R)
lon = atan2(y, x)
asin ist natürlich arc sinus. Lesen Sie über atan2 in Wikipedia . Vergessen Sie nicht, vom Bogenmaß in Grad zurückzurechnen.
Diese Seite enthält C # -Code dafür (beachten Sie, dass er sich stark von den Formeln unterscheidet) sowie eine Erklärung und ein schönes Diagramm, warum dies korrekt ist.
Theorie für die Konvertierung GPS(WGS84)
in kartesische Koordinaten
https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
Folgendes verwende ich:
Ich habe einen VB-Code angehängt , den ich geschrieben habe:
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
Bitte beachten Sie, dass die h
Höhe über dem liegt WGS 84 ellipsoid
.
Normalerweise GPS
geben wir H
von oben MSL
Höhe. Die MSL
Höhe hat , um zu Höhe umgewandelt werden , h
über die WGS 84 ellipsoid
unter Verwendung des geopotentielle Modell EGM96
( Lemoine et al 1998 ).
Dazu wird ein Raster der Geoidhöhendatei mit einer räumlichen Auflösung von 15 Bogenminuten interpoliert.
Oder wenn Sie ein gewisses Maß haben professionelles GPS
hat Altitude H
( msl, heigh über NHN ) und UNDULATION
die Beziehung zwischen dem geoid
und dem ellipsoid (m)
von dem gewählten Bezugspunkt Ausgang aus dem internen Tabelle. du kannst bekommenh = H(msl) + undulation
Zu XYZ durch kartesische Koordinaten:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
Die proj.4- Software bietet ein Befehlszeilenprogramm, das die Konvertierung durchführen kann, z
LAT=40
LON=-110
echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84
Es bietet auch eine C-API . Insbesondere führt die Funktion pj_geodetic_to_geocentric
die Konvertierung durch, ohne zuerst ein Projektionsobjekt einrichten zu müssen.
In python3.x kann Folgendes ausgeführt werden:
# 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
Wenn Sie Koordinaten basierend auf einem Ellipsoid und nicht auf einer Kugel erhalten möchten, besuchen Sie http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF. Dort finden Sie die Formeln sowie die WGS84-Konstanten, die Sie für die Konvertierung benötigen .
Die dortigen Formeln berücksichtigen auch die Höhe relativ zur Referenzellipsoidoberfläche (nützlich, wenn Sie Höhendaten von einem GPS-Gerät erhalten).
Warum etwas implementieren, das bereits implementiert und getestet wurde?
Zum einen verfügt C # über die NetTopologySuite , den .NET-Port der JTS Topology Suite.
Insbesondere haben Sie einen schwerwiegenden Fehler in Ihrer Berechnung. Die Erde ist keine perfekte Kugel, und die Annäherung des Erdradius schneidet sie möglicherweise nicht für genaue Messungen.
Wenn es in einigen Fällen akzeptabel ist, Homebrew-Funktionen zu verwenden, ist GIS ein gutes Beispiel für ein Gebiet, in dem die Verwendung einer zuverlässigen, testgeprüften Bibliothek sehr bevorzugt wird.
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);
java.lang.IllegalArgumentException: dimension must be <= 3
Sie können dies auf Java auf diese Weise tun.
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;
}