从经度\纬度转换到笛卡尔坐标
我有一些以地球为中心的经度和纬度坐标点( WGS-84 )。
我如何将它们转换为原点在地球中心的笛卡尔坐标(x,y,z)?
我最近用WGS-84数据中的“Haversine公式”做了类似的事情,这是“Haversines定律”的衍生物,具有非常令人满意的结果。
是的,WGS-84假设地球是一个椭球体,但我相信你只能使用像“Haversine公式”这样的方法来获得大约0.5%的平均误差,在你的情况下这可能是一个可以接受的误差量。 除非你谈论的是几英尺的距离,否则你将总是会有一定的误差,即使如此,理论上地球的曲率也是如此。如果你需要更严格的WGS-84兼容的方法,结账“Vincenty公式”。
我明白starblue是从哪里来的,但好的软件工程经常是关于折衷的,所以这一切都取决于你所要做的准确性。 例如,从“曼哈顿距离公式”计算的结果与“距离公式”的结果相比,对于某些情况可能会更好,因为计算成本更低。 认为“哪一点最接近?” 您不需要精确的距离测量的场景。
关于“Haversine公式”很容易实现,因为它是使用“球面三angular”代替基于二维三angular法的“余弦定律”的方法,所以你可以很好的平衡精度过于复杂。
一位名叫Chris Veness的绅士在http://www.movable-type.co.uk/scripts/latlong.html有一个很棒的网站,它解释了你感兴趣的一些概念,并演示了各种程序化的实现;; 这也应该回答你的X / Y转换问题。
这是我发现的答案:
为了使定义完整,在笛卡尔坐标系中:
- x轴经过long,lat(0,0),所以经度0与赤道相交;
- y轴经过(0,90);
- 而z轴穿过两极。
转换是:
x = R * cos(lat) * cos(lon) y = R * cos(lat) * sin(lon) z = R *sin(lat)
其中R是地球的近似半径 (例如6371KM)。
如果你的三angular函数需要弧度(他们可能这样做),你需要首先将经度和纬度转换为弧度。 你显然需要一个十进制表示,而不是度\分钟\秒(见这里关于转换)。
返回公式:
lat = asin(z / R) lon = atan2(y, x)
asin当然是正弦的。 阅读维基百科的atan2 。 不要忘记从弧度转换回度数。
这个页面给出了这个c#代码(注意它与公式非常不同),还有一些解释和为什么这是正确的很好的图表,
将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
会给我们以上MSL
高度的H
通过使用位势模型EGM96
( Lemoine等人,1998 ) , MSL
高度必须被转换成高于WGS 84 ellipsoid
的高度h
。
这是通过以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)
为什么要实施已经实施并经过testingcertificate的东西?
举个例子 ,C#的NetTopologySuite是JTS Topology Suite的.NET端口。
具体来说,你的计算有一个严重的缺陷。 地球不是一个完美的球体,地球半径的近似值可能无法精确测量。
如果在某些情况下使用自制function是可以接受的,GIS就是一个很好的例子,在这个领域里使用可靠的,经过testingvalidation的库是最好的select。
如果您关心的是基于椭球体而不是球体获取坐标,请查看http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF – 它提供了公式以及转换所需的WGS84常量。
这里的公式还考虑了相对于参考椭球表面的高度(如果从GPS设备获取高度数据,则是有用的)。
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);
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
将进行转换,而不pj_geodetic_to_geocentric
设置投影对象。