Saya memiliki beberapa titik koordinat pusat bumi yang diberikan sebagai garis lintang dan garis bujur ( WGS-84 ).
Bagaimana cara mengubahnya menjadi koordinat Kartesius (x, y, z) dengan titik asal di pusat bumi?
Saya memiliki beberapa titik koordinat pusat bumi yang diberikan sebagai garis lintang dan garis bujur ( WGS-84 ).
Bagaimana cara mengubahnya menjadi koordinat Kartesius (x, y, z) dengan titik asal di pusat bumi?
Jawaban:
Saya baru-baru ini melakukan sesuatu yang mirip dengan ini menggunakan "Haversine Formula" pada data WGS-84, yang merupakan turunan dari "Law of Haversines" dengan hasil yang sangat memuaskan.
Ya, WGS-84 mengasumsikan Bumi adalah elipsoid, tetapi saya yakin Anda hanya mendapatkan kesalahan rata-rata 0,5% menggunakan pendekatan seperti "Formula Haversine", yang mungkin merupakan jumlah kesalahan yang dapat diterima dalam kasus Anda. Anda akan selalu mendapatkan sejumlah kesalahan kecuali jika Anda berbicara tentang jarak beberapa kaki dan bahkan kemudian ada kelengkungan secara teoritis dari Bumi ... Jika Anda memerlukan pendekatan yang lebih kompatibel dengan WGS-84, periksa "Formula Vincenty".
Saya mengerti dari mana starblue berasal, tetapi rekayasa perangkat lunak yang baik sering kali tentang kompromi, jadi semuanya tergantung pada keakuratan yang Anda perlukan untuk apa yang Anda lakukan. Misalnya, hasil yang dihitung dari "Rumus Jarak Manhattan" versus hasil dari "Rumus Jarak" bisa lebih baik untuk situasi tertentu karena secara komputasi lebih murah. Pikirkan "titik mana yang paling dekat?" skenario di mana Anda tidak memerlukan pengukuran jarak yang tepat.
Mengenai, "Formula Haversine" mudah diterapkan dan bagus karena menggunakan "Trigonometri Bulat" bukan pendekatan berbasis "Hukum Kosinus" yang didasarkan pada trigonometri dua dimensi, oleh karena itu Anda mendapatkan keseimbangan akurasi yang bagus lebih dari kompleksitas.
Seorang pria bernama Chris Veness memiliki situs web yang bagus di http://www.movable-type.co.uk/scripts/latlong.html yang menjelaskan beberapa konsep yang Anda minati dan mendemonstrasikan berbagai implementasi programatik; ini harus menjawab pertanyaan konversi x / y Anda juga.
Inilah jawaban yang saya temukan:
Hanya untuk membuat definisi lengkap, dalam sistem koordinat Kartesius:
Konversinya adalah:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
Dimana R adalah radius perkiraan bumi (misalnya 6371 km).
Jika fungsi trigonometri Anda mengharapkan radian (yang mungkin bisa terjadi), Anda perlu mengonversi bujur dan lintang ke radian terlebih dahulu. Anda jelas membutuhkan representasi desimal, bukan derajat \ menit \ detik (lihat misalnya di sini tentang konversi).
Rumus konversi balik:
lat = asin(z / R)
lon = atan2(y, x)
asin tentu saja arc sinus. baca tentang atan2 di wikipedia . Jangan lupa untuk mengubah kembali dari radian ke derajat.
Halaman ini memberikan kode c # untuk ini (perhatikan bahwa ini sangat berbeda dari rumus), dan juga beberapa penjelasan dan diagram yang bagus mengapa ini benar,
Teori untuk mengonversi GPS(WGS84)
ke koordinat Cartesian
https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
Berikut ini yang saya gunakan:
Saya melampirkan kode VB yang saya tulis:
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
Harap perhatikan bahwa h
adalah ketinggian di atas WGS 84 ellipsoid
.
Biasanya GPS
akan memberi kita ketinggian di H
atas MSL
. The MSL
tinggi harus dikonversi ke ketinggian h
di atas WGS 84 ellipsoid
dengan menggunakan geopotential Model EGM96
( Lemoine et al, 1998 ).
Ini dilakukan dengan menginterpolasi grid file ketinggian geoid dengan resolusi spasial 15 arc-menit.
Atau jika Anda memiliki beberapa level profesional GPS
memiliki Ketinggian H
( msl, tinggi di atas permukaan laut rata-rata ) dan UNDULATION
, hubungan antara geoid
dan ellipsoid (m)
dari keluaran datum yang dipilih dari tabel internal. Anda bisa mendapatkanh = H(msl) + undulation
Ke XYZ dengan koordinat Cartesian:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
Perangkat lunak proj.4 menyediakan program baris perintah yang dapat melakukan konversi, misalnya
LAT=40
LON=-110
echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84
Ini juga menyediakan C API . Secara khusus, fungsi tersebut pj_geodetic_to_geocentric
akan melakukan konversi tanpa harus menyiapkan objek proyeksi terlebih dahulu.
Di python3.x itu bisa dilakukan dengan menggunakan:
# 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
Jika Anda ingin mendapatkan koordinat berdasarkan elipsoid daripada bola, lihat http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - ini memberikan rumus serta konstanta WGS84 yang Anda butuhkan untuk konversi .
Rumusnya juga memperhitungkan ketinggian relatif terhadap permukaan elipsoid referensi (berguna jika Anda mendapatkan data ketinggian dari perangkat GPS).
Mengapa menerapkan sesuatu yang telah diterapkan dan diuji-terbukti?
C #, misalnya, memiliki NetTopologySuite yang merupakan port .NET dari JTS Topology Suite.
Secara khusus, Anda memiliki kesalahan yang parah dalam perhitungan Anda. Bumi bukanlah bola yang sempurna, dan perkiraan jari-jari bumi mungkin tidak tepat untuk pengukuran yang tepat.
Jika dalam beberapa kasus dapat diterima untuk menggunakan fungsi homebrew, GIS adalah contoh yang baik dari bidang yang lebih disukai untuk menggunakan pustaka yang andal dan terbukti uji.
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
Anda dapat melakukannya dengan cara ini di 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;
}