从经度\纬度转换为直角坐标


103

我有一些以地球为中心的坐标点,称为纬度和经度(WGS-84)。

如何将其转换为以地球中心为原点的笛卡尔坐标(x,y,z)?


1
您是否设法将WGS-84经度和纬度转换为笛卡尔坐标?我也有海拔。我在这里尝试了接受的答案,但是它给我的答案不正确。我将结果与以下网站进行了比较:apsalin.com/convert-geodetic-to-cartesian.aspx
Yasmin

Answers:


45

我最近在WGS-84数据上使用“ Haversine公式”进行了类似的操作,它是“ Haversines法”的派生词,具有非常令人满意的结果。

是的,WGS-84假定地球是一个椭球,但是我相信使用“ Haversine公式”之类的方法只能得到大约0.5%的平均误差,这在您的情况下可能是可接受的误差。除非您谈论的是几英尺的距离,否则理论上总是会有一些误差的,即使如此,理论上讲地球也会弯曲……如果您需要更严格地与WGS-84兼容的方法,请查看“ Vincenty公式”。

我了解starblue的来源,但是好的软件工程通常是要权衡取舍的,因此,这一切都取决于您执行工作所需的准确性。例如,从“曼哈顿距离公式”计算得出的结果与从“距离公式”得出的结果相比,在某些情况下可能会更好,因为它在计算上更便宜。认为“哪一点最接近?” 不需要精确距离测量的场景。

关于“ Haversine公式”,它易于实现并且很好,因为它使用的是“球面三角法”,而不是基于二维三角法的“余弦法”,因此您可以获得很好的精度平衡过于复杂。

一位名叫克里斯·韦尼斯Chris Veness)的先生们在http://www.movable-type.co.uk/scripts/latlong.html上有一个不错的网站,它解释了您感兴趣的一些概念并演示了各种程序实现。这也应该回答您的x / y转换问题。


1
0.5%的误差-0.5%的误差是多少?在这个问题的背景下,它可能是地球的半径,所以0.5%可能是30公里:)
MarkJ

2
查看了您的链接。0.5%的报价是因为两点之间的大圆距离存在误差,因此与该问题并不严格相关。我认为当将经纬度坐标转换为以地球中心为原点的笛卡尔坐标时,假设球形地球的误差可能会很大。尚不清楚提问者想对笛卡尔坐标什么。出于某些奇怪的原因,或者更方便地使用它们,还是对数据导出有一些要求?如果是后者,那么准确性将很重要。
MarkJ

129

这是我找到的答案:

为了使定义完整,在笛卡尔坐标系中:

  • 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 km)。

如果三角函数期望弧度(它们可能会这样做),则需要先将经度和纬度转换为弧度。显然,您需要用十进制表示,而不是度/分钟/秒(请参见此处有关转换的信息)。

反向转换的公式:

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

阿辛当然是反正弦的。在Wikipedia中阅读有关atan2的信息。不要忘记将弧度转换回度。

此页面为此提供了C#代码(请注意,它与公式大不相同),并提供了一些解释和很好的图表说明了为什么这样做是正确的,


17
-1这是错误的。您假设地球是一个球体,而WGS-84假定是一个椭球。
starblue

42
@starblue:我不确定您是否可以将给出的答案标记为“正确”或“错误”。使用可用纬度/经度(参考WGS-84)得到的球形近似值(以获得ECEF样式的x,y,z坐标)对于原始海报的需求而言“足够”,或者“不足”。对于距离和方位估计,我敢打赌这种简单的转换很好。如果他正在发射卫星,也许不会。毕竟,WGS-84本身是“错误的”……因为它不是地球表面的理想模型;所有椭球模型都是近似值。糟糕的是,OP没有告诉我们他想做什么。
丹·H

10
@Dan H该问题要求使用WGS-84,如果您要回答其他问题,则至少应讨论差异/错误,但此答案没有。
starblue'7

@ daphna-shezaf无法进行反向转换...我也做了从弧度到度的反向转换,但是结果不一样...

谢谢,花几个小时弄清楚为什么它不起作用,原来我交换了一些cos(lat)和sin(lat)
Aeroson 2015年

6

转换GPS(WGS84)笛卡尔坐标的 理论https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates

以下是我正在使用的:

  • GPS的经度(WGS84)和笛卡尔坐标相同。
  • 需要通过WGS 84椭球参数将半轴的纬度转换为6378137 m,并且
  • 展平的倒数是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通过使用位势模型EGM96勒蒙纳等人,1998)。
这是通过以15弧分的空间分辨率内插大地水准面高度文件的网格来完成的。

或者,如果您有某个级别的专业人员 GPS具有“海拔” Hmsl,高于平均海平面)和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的值是多少?
eych

4
我想这是地球的半径,即地球的6371公里。
马赛厄斯

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将执行转换而不必首先设置投影对象。


5

在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


2

为什么要实施已经实施并经过测试证明的东西?

C#具有一个NetTopologySuite,它是JTS拓扑套件的.NET端口。

具体来说,您的计算存在严重缺陷。地球不是一个完美的球体,近似于地球的半径可能无法精确测量。

如果在某些情况下使用自制功能是可以接受的,则GIS是该领域的一个很好的例子,在该领域中,更可取的是使用可靠的,经过验证的库。


1
+1。使用可靠的库比使用自制程序更准确,也更容易
MarkJ

5
NetTopologySuite如何从长/迟转换为直角坐标?
vinayan

1
NTS不包含坐标转换功能,也许您需要Proj.NET projnet.codeplex.com
D_Guidi 2014年

6
可笑,答案甚至不提供转换功能。
微粒

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

嗯...我看了一下JTS。直到并包括新LineString()的行看起来都像JTS。但是我在JTS中看不到CRS和Transform的内容。所以:他们在那里,我想念他们吗?在那里,并在1.12中删除了吗?或者:那是另一个图书馆吗?
Dan H'7

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.