我有一些以地球为中心的坐标点,以纬度和经度(WGS-84)给出。
如何将它们转换为笛卡尔坐标(x,y,z),原点位于地球的中心?
答案 0 :(得分:114)
以下是我找到的答案:
只是为了在笛卡尔坐标系中完成定义:
转换是:
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
其中R为the approximate radius of earth(例如6371KM)。
如果您的三角函数需要弧度(他们可能会这样做),您需要先将经度和纬度转换为弧度。你显然需要十进制表示,而不是度数\分钟\秒(关于转换,请参阅e.g. here。)
反向转换公式:
lat = asin(z / R)
lon = atan2(y, x)
asin当然是正弦曲线。 read about atan2 in wikipedia。不要忘记从弧度转换回度数。
This page给出了c#代码(注意它与公式非常不同),还有一些解释和很好的图表,说明为什么这是正确的,
答案 1 :(得分:41)
我最近做过类似的事情 关于WGS-84数据的“Haversine Formula”,它是“Haversines法则”的衍生物,具有非常令人满意的结果。
是的,WGS-84假设地球是一个椭圆体,但我相信你只能使用像“Haversine Formula”这样的方法得到大约0.5%的平均误差,在你的情况下这可能是一个可接受的误差量。你总是会有一些错误,除非你说的是几英尺的距离,甚至理论上地球的曲率......如果你需要更严格的WGS-84兼容方法,请查看“Vincenty公式”。
我理解 starblue 的来源,但良好的软件工程往往是权衡取舍,所以这一切都取决于您所做的准确性。例如,从“曼哈顿距离公式”计算的结果与“距离公式”的结果相比,对于某些情况可能更好,因为它在计算上更便宜。想想“哪一点最接近?”您不需要精确距离测量的场景。
关于,“Haversine公式”很容易实现并且很好,因为它使用“球形三角法”而不是基于二维三角法的“余弦定律”方法,因此你得到了一个很好的准确性与复杂性之间的平衡。
名为 Chris Veness 的绅士在http://www.movable-type.co.uk/scripts/latlong.html有一个很棒的网站,它解释了您感兴趣的一些概念并演示了各种程序化实现;这也应该回答你的x / y转换问题。
答案 2 :(得分:6)
将GPS(WGS84)
转换为 笛卡尔坐标的理论
https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
以下是我正在使用的内容:
我附上了 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
高度必须使用 locationotential 模型h
转换为WGS 84 ellipsoid
上方的EGM96
高度( Lemoine等, 1998年)。
这是通过插入大地水准面高度文件的网格来实现的,空间分辨率为15弧分。
或者,如果您有某种级别专业 GPS
具有海拔高度H
( msl,高于平均海平面)和{{1} },来自内部表的所选基准输出的UNDULATION
和geoid
之间的关系。你可以得到ellipsoid (m)
通过笛卡尔坐标到XYZ:
h = H(msl) + undulation
答案 3 :(得分:5)
为什么要实施已经实施并经过测试验证的内容?
例如,C#具有NetTopologySuite,它是JTS拓扑套件的.NET端口。
具体来说,您的计算存在严重缺陷。地球不是一个完美的球体,地球半径的近似可能无法切割它以进行精确测量。
如果在某些情况下使用自制函数是可以接受的,那么GIS就是一个很好的例子,在这个领域中,最好使用经过测试验证的可靠库。
答案 4 :(得分: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 :(得分:3)
如果您想要根据椭球而不是球体来获取坐标,请查看http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - 它会给出公式以及转换所需的WGS84常量。
那里的公式还考虑了相对于参考椭球表面的高度(如果您从GPS设备获取高度数据,则非常有用)。
答案 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);
答案 7 :(得分:1)
在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
答案 8 :(得分:0)
您可以在Java上通过这种方式完成
。print(True + True)
print(False * 123)
print(True == 1)
print(False == 0)