การแปลงจากลองจิจูด \ ละติจูดเป็นพิกัดคาร์ทีเซียน


104

ฉันมีจุดพิกัดกลางโลกที่กำหนดให้เป็นละติจูดและลองจิจูด ( WGS-84 )

ฉันจะแปลงเป็นพิกัดคาร์ทีเซียน (x, y, z) โดยมีจุดเริ่มต้นอยู่ที่ใจกลางโลกได้อย่างไร


1
คุณได้จัดการแปลงลองจิจูด WGS-84 และละติจูดเป็นพิกัดคาร์ทีเซียนแล้วหรือยัง? ฉันยังมีระดับความสูง ฉันได้ลองใช้คำตอบที่ยอมรับแล้วที่นี่ แต่มันไม่ได้ให้คำตอบที่ถูกต้อง ผมเปรียบเทียบผลของฉันกับเว็บไซต์นี้: apsalin.com/convert-geodetic-to-cartesian.aspx
Yasmin

คำตอบ:


47

เมื่อเร็ว ๆ นี้ฉันได้ทำสิ่งที่คล้ายกับสิ่งนี้โดยใช้ "Haversine Formula" บนข้อมูล WGS-84 ซึ่งเป็นอนุพันธ์ของ "Law of Haversines" ซึ่งได้ผลลัพธ์ที่น่าพอใจมาก

ใช่ WGS-84 ถือว่าโลกเป็นทรงรี แต่ฉันเชื่อว่าคุณจะได้รับข้อผิดพลาดประมาณ 0.5% โดยเฉลี่ยโดยใช้วิธีการเช่น "Haversine Formula" ซึ่งอาจเป็นจำนวนข้อผิดพลาดที่ยอมรับได้ในกรณีของคุณ คุณจะมีข้อผิดพลาดอยู่เสมอเว้นแต่คุณจะพูดถึงระยะทางไม่กี่ฟุตและถึงแม้จะมีความโค้งของโลกในทางทฤษฎี ... หากคุณต้องการวิธีที่เข้ากันได้กับ WGS-84 ที่เข้มงวดมากขึ้นให้ชำระเงิน "Vincenty Formula"

ฉันเข้าใจว่าstarblueมาจากไหน แต่วิศวกรรมซอฟต์แวร์ที่ดีมักจะเกี่ยวกับการแลกเปลี่ยนดังนั้นทุกอย่างขึ้นอยู่กับความแม่นยำที่คุณต้องการสำหรับสิ่งที่คุณกำลังทำ ตัวอย่างเช่นผลลัพธ์ที่คำนวณจาก "สูตรระยะทางแมนฮัตตัน" เทียบกับผลลัพธ์จาก "สูตรระยะทาง" อาจดีกว่าสำหรับบางสถานการณ์เนื่องจากมีค่าใช้จ่ายในการคำนวณน้อยกว่า คิดว่า "จุดไหนใกล้ที่สุด" สถานการณ์ที่คุณไม่ต้องการการวัดระยะทางที่แม่นยำ

เกี่ยวกับ "Haversine Formula" เป็นเรื่องง่ายที่จะนำไปใช้และเป็นสิ่งที่ดีเพราะใช้ "Spherical Trigonometry" แทนที่จะใช้วิธีการตาม "Law of Cosines" ซึ่งเป็นไปตามตรีโกณมิติสองมิติดังนั้นคุณจึงมีความสมดุลที่ดี มากกว่าความซับซ้อน

สุภาพบุรุษที่ใช้ชื่อว่าChris Venessมีเว็บไซต์ที่ยอดเยี่ยมที่http://www.movable-type.co.uk/scripts/latlong.htmlซึ่งจะอธิบายแนวคิดบางอย่างที่คุณสนใจและแสดงให้เห็นถึงการใช้งานแบบเป็นโปรแกรมต่างๆ สิ่งนี้ควรตอบคำถามการแปลง x / y ของคุณเช่นกัน


1
0.5% error - 0.5% คืออะไร? ในบริบทของคำถามนี้อาจเป็นรัศมีของโลกดังนั้น 0.5% อาจเป็น 30 กม. :)
MarkJ

2
ตรวจสอบลิงก์ของคุณ ใบเสนอราคา 0.5% มีไว้สำหรับข้อผิดพลาดในระยะวงกลมใหญ่ระหว่างสองจุดดังนั้นจึงไม่เกี่ยวข้องกับคำถามนี้อย่างเคร่งครัด ฉันคิดว่าเมื่อแปลง lat-long เป็นพิกัดคาร์ทีเซียนกับจุดกำเนิดที่ใจกลางโลกข้อผิดพลาดจากการสมมติว่าโลกทรงกลมอาจมีนัยสำคัญ ยังไม่ชัดเจนว่าผู้ถามต้องการทำอะไรกับพิกัดคาร์ทีเซียน ไม่ว่าจะสะดวกกว่าในการทำงานด้วยเหตุผลแปลก ๆ บางอย่างหรืออาจเป็นข้อกำหนดบางประการสำหรับการส่งออกข้อมูล? หากเป็นอย่างหลังความถูกต้องจะเป็นสิ่งสำคัญ
MarkJ

132

นี่คือคำตอบที่ฉันพบ:

เพียงเพื่อให้คำจำกัดความสมบูรณ์ในระบบพิกัดคาร์ทีเซียน:

  • แกน x ผ่านทางยาวละติจูด (0,0) ดังนั้นลองจิจูด 0 จึงตรงกับเส้นศูนย์สูตร
  • แกน y ผ่าน (0,90);
  • และแกน z เคลื่อนผ่านเสา

การแปลงคือ:

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

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

z = R *sin(lat)

โดย R คือรัศมีโดยประมาณของโลก (เช่น 6371 กม.)

หากฟังก์ชันตรีโกณมิติของคุณคาดว่าจะเป็นเรเดียน (ซึ่งน่าจะทำได้) คุณจะต้องแปลงลองจิจูดและละติจูดเป็นเรเดียนก่อน เห็นได้ชัดว่าคุณต้องมีการแทนค่าทศนิยมไม่ใช่องศา \ นาที \ วินาที (ดูเช่นที่นี่เกี่ยวกับการแปลง)

สูตรสำหรับการแปลงกลับ:

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

asin เป็นอาร์คไซน์แน่นอน อ่านเกี่ยวกับ atan2 ในวิกิพีเดีย อย่าลืมแปลงกลับจากเรเดียนเป็นองศา

หน้านี้ให้รหัส c # สำหรับสิ่งนี้ (โปรดทราบว่ามันแตกต่างจากสูตรมาก) และยังมีคำอธิบายและแผนภาพที่ดีว่าเหตุใดจึงถูกต้อง


19
-1 สิ่งนี้ผิด คุณสมมติว่าโลกเป็นทรงกลมในขณะที่ WGS-84 ถือว่าเป็นทรงรี
starblue

43
@starblue: ฉันไม่แน่ใจว่าคุณอยู่ในตำแหน่งที่จะติดป้ายกำกับคำตอบที่ระบุว่า "ถูก" หรือ "ผิด" การประมาณแบบทรงกลม (เพื่อให้ได้ Coords x, y, z สไตล์ ECEF) โดยใช้ lat / lngs ที่มีอยู่ (ซึ่งอ้างอิงถึง WGS-84) นั้น "เพียงพอ" สำหรับความต้องการของผู้โพสต์ต้นฉบับหรือ "ไม่เพียงพอ" สำหรับการประมาณระยะทางและแบริ่งฉันพนันได้เลยว่าการแปลงแบบธรรมดานี้ใช้ได้ ถ้าเขากำลังปล่อยดาวเทียมอาจจะไม่ ท้ายที่สุด WGS-84 เองก็ "ผิด" ... เพราะมันไม่ใช่แบบจำลองที่สมบูรณ์แบบของพื้นผิวโลก แบบจำลองทรงรีทั้งหมดเป็นค่าประมาณ เสียดายที่ OP ไม่ได้บอกเราว่าเขาพยายามทำอะไร
Dan H

11
@ Dan H คำถามถามหา WGS-84 และถ้าคุณตอบอย่างอื่นอย่างน้อยคุณควรพูดถึงความแตกต่าง / ข้อผิดพลาดซึ่งคำตอบนี้ไม่ได้
starblue

@ daphna-shezaf ไม่สามารถแปลงกลับได้ ... ฉันทำด้านหลังจากเรเดียนเป็นองศาด้วย แต่ผลลัพธ์ไม่เหมือนกัน ...

ขอบคุณใช้เวลาหลายชั่วโมงในการหาสาเหตุว่าทำไมมันถึงใช้ไม่ได้ปรากฎว่าฉันเปลี่ยน cos (lat) และ sin (lat)
aeroson

6

ทฤษฎีการแปลงGPS(WGS84)เป็นพิกัดคาร์ทีเซียน https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates

ต่อไปนี้คือสิ่งที่ฉันใช้:

  • ลองจิจูดใน GPS (WGS84) และพิกัดคาร์ทีเซียนเหมือนกัน
  • ต้องมีการแปลงละติจูดโดย WGS 84 พารามิเตอร์ทรงรีแกนกึ่งหลักคือ 6378137 ม. และ
  • ซึ่งกันและกันของการแบนคือ 298.257223563

ฉันแนบรหัส VB ​​ที่ฉันเขียน:

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

โปรดสังเกตว่าhระดับความสูงเหนือWGS 84 ellipsoid.

มักGPSจะทำให้เรามีHของดังกล่าวข้างต้นMSLมีความสูง MSLสูงจะต้องมีการแปลงเป็นความสูงhดังกล่าวข้างต้นWGS 84 ellipsoidโดยใช้geopotentialรุ่นEGM96( Lemoine et al, 1998 )
ทำได้โดยการแก้ไขตารางของไฟล์ geoid height ด้วยความละเอียดเชิงพื้นที่ 15 อาร์ก - นาที

หรือถ้าคุณมีระดับมืออาชีพ บางคนGPSมีระดับความสูงH( msl สูงกว่าระดับน้ำทะเลปานกลาง ) และUNDULATIONความสัมพันธ์ระหว่างgeoidและellipsoid (m)ของเอาต์พุตข้อมูลที่เลือกจากตารางภายใน คุณสามารถได้รับh = H(msl) + undulation

ถึง XYZ โดยพิกัดคาร์ทีเซียน:

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

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

z = R *sin(lat)

ค่า R คืออะไร?
ตา

4
ฉันเดาว่ามันคือรัศมีของทรงกลมซึ่งเป็น 6371 กม. สำหรับพื้นโลก
Matthias

6

ใน python3.x สามารถทำได้โดยใช้:

# 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

5

proj.4ซอฟแวร์ให้โปรแกรมบรรทัดคำสั่งที่สามารถทำแปลงเช่น

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

นอกจากนี้ยังมีC API โดยเฉพาะอย่างยิ่งฟังก์ชันpj_geodetic_to_geocentricจะทำการแปลงโดยไม่ต้องตั้งค่าวัตถุฉายก่อน


3

หากคุณสนใจเกี่ยวกับการหาพิกัดตามวงรีมากกว่าทรงกลมลองดูที่http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEFซึ่งจะให้สูตรรวมทั้งค่าคงที่ WGS84 ที่คุณต้องการสำหรับการแปลง .

นอกจากนี้สูตรยังคำนึงถึงระดับความสูงที่สัมพันธ์กับพื้นผิวทรงรีอ้างอิง (มีประโยชน์หากคุณได้รับข้อมูลระดับความสูงจากอุปกรณ์ GPS)


การโหวตแม้ว่าคุณจะไม่ได้โพสต์เนื้อหาของลิงก์ที่นี่
Mad Physicist

2

เหตุใดจึงต้องใช้สิ่งที่ได้ดำเนินการไปแล้วและผ่านการทดสอบแล้ว?

C # สำหรับหนึ่งมีNetTopologySuiteซึ่งเป็นพอร์ต. NET ของ JTS Topology Suite

คุณมีข้อบกพร่องอย่างรุนแรงในการคำนวณของคุณ โลกไม่ใช่ทรงกลมที่สมบูรณ์แบบและการประมาณรัศมีของโลกอาจไม่ได้ตัดมันเพื่อการวัดที่แม่นยำ

หากในบางกรณีสามารถใช้ฟังก์ชัน homebrew ได้ GIS เป็นตัวอย่างที่ดีของเขตข้อมูลที่ควรใช้ไลบรารีที่เชื่อถือได้และผ่านการทดสอบแล้ว


1
+1. การใช้ไลบรารีที่เชื่อถือได้นั้นแม่นยำกว่าฟังก์ชั่น homebrew และง่ายกว่าด้วย
MarkJ

5
NetTopologySuite แปลงจาก long / late เป็น cartesion ได้อย่างไร?
vinayan

1
NTS ไม่รวมความสามารถในการแปลงพิกัดบางทีคุณอาจต้องใช้ Proj.NET projnet.codeplex.com
D_Guidi

6
ไร้สาระคำตอบไม่ได้ให้ความสามารถในการแปลง
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);

คุณจะสามารถอธิบายได้หรือไม่? ฉันสร้างแอปพลิเคชันง่ายๆที่ระดับเพื่อเปลี่ยนพิกัดเดียวโดยใช้แนวทางของคุณ มันมักจะล้มเหลวแม้ว่าขนาดของแหล่งที่มา (2) และขนาดของเป้าหมาย (3) ต่างกันส่งผลให้เกิดข้อยกเว้นjava.lang.IllegalArgumentException: dimension must be <= 3
oschrenk

อืม ... เคยดู JTS มาหน่อย บรรทัดไม่เกินและรวมถึง LineString () ใหม่ดูเหมือน JTS แต่ฉันไม่เห็น CRS และเนื้อหา Transform ใน JTS พวกเขาอยู่ที่นั่นและฉันคิดถึงพวกเขาหรือไม่? อยู่ที่นั่นและนำออกใน 1.12 หรือไม่? หรือ: นั่นคือห้องสมุดอื่น?
Dan H

0

คุณสามารถทำได้ด้วยวิธีนี้บน 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;


}

พารามิเตอร์ alt คืออะไร?
baliman

ความสูงคุณมาทำอะไรที่นี่ถ้าคุณไม่รู้ว่า GPS ทำงานอย่างไร;)
MushyPeas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.