ENU、EPSG、ECEF坐标系科普(三维重建)

科普一

ENU和EPSG实际上代表了两个不同的概念,这两者并不是直接对比的。

1. ENU坐标系:ENU坐标系是一种本地切面坐标系,用于表示与地理位置相关的空间数据。在ENU坐标系中,E代表东(East),N代表北(North),U代表上(Up)。它是一个右手坐标系,经常用于地理信息系统(GIS)和导航中,其原点通常设在特定的地理位置(例如观测站),并以此位置的地方水平面作为基准平面。ENU坐标系与地理坐标系(例如WGS-84)不同,因为它是一个笛卡尔坐标系,而地理坐标系是一个球面坐标系。

左右手坐标系:左手坐标系 右手坐标系 区别 - 知乎 (zhihu.com)

更加通俗解释:

ENU坐标系:想象你在某个城市的某个位置,你面朝东,这个方向就是E(East),左手指向北方,这个方向就是N(North),而头顶的方向就是U(Up)。这就是ENU坐标系,它是一个本地坐标系,相对于你所在的位置而言。你可以用它来描述周围事物相对于你的位置。例如,你可以说:“那个邮筒在我东边3米、北边2米处”。

2. EPSG坐标系:EPSG并不是一个具体的坐标系,而是由国际石油工程师协会(European Petroleum Survey Group,EPSG)定义的一组坐标参考系统和相关的参数。在GIS中,EPSG代码通常用于唯一标识一个特定的坐标参考系统,例如EPSG:4326代表WGS-84地理坐标系。EPSG代码库中包括各种不同类型的坐标系,包括地理坐标系、投影坐标系和垂直坐标系等。

简单来说,ENU是一种特定类型的本地坐标系,而EPSG是一种坐标参考系统的编码标准。在实际应用中,ENU坐标系可以用EPSG代码来唯一标识。

更加通俗的解释:

EPSG坐标系:这更像是一个"地图语言"的代码。你知道有各种各样的地图,比如平面地图、球形地图(像我们常见的地球仪)、卫星地图等,每种地图都有自己的一套"语言"来描述地理位置。EPSG就是一种方式,给每种"地图语言"一个代码。例如,EPSG:4326这个代码就是代表了我们常用的GPS系统所使用的"WGS-84"坐标系。

所以,二者的主要区别在于:ENU坐标系是一种描述你周围环境的方式,而EPSG则是一种对全球地图或者说坐标系统的描述和编码方式。

补充3dtiles:

3dtiles是 Cesium 定义的三维模型渲染格式,但是 Cesium 是一个地球开发包,想当然的很多非业内人士说,地球坐标不就是经纬度吗,那么 3dtiles 就是经纬度了。但是事实上 3dtiles 坐标不能直接存储为经纬度方式。原因是现代图形学都是构建在直角坐标系上的,经纬度本质是球坐标,不适合做渲染。Cesium 引擎包括所有的地球开发包,对外可能提供了经纬度二次开发接口,但是其内部的渲染依然是直角坐标系,Cesium 采用了 WGS84 的地心坐标系作为世界坐标。地球质心为 0,0,0 点,地心和北极连线为正 z 轴,地心和 本初子午线(0°经线)与赤道交点连线为正 x 轴。正交得到 y 轴。 

 Wgs84 世界坐标

考虑到地球半径是 6378137 米,那么这个坐标系比较大,涉及另一个图形学古老问题,渲染都是单浮点精度表示的。为了避免渲染精度的问题,一般 3dtiles 里的坐标都是经过 tileset.json 里的transform 变换矩阵 变换的相对坐标,有如下等式。

3dtiles 里的坐标 * 3dtiles 里的 transform 矩阵 = wgs84 世界坐标

 

科普二

参考视频:《三维GIS开发Cesium学习教程》第12节:坐标转换_哔哩哔哩_bilibili 

ECEF坐标系

地心地固坐标系Earth-Centered, Earth-Fixed,简称ECEF)简称地心坐标系,是一种以地心为原点的地固坐标系(也称地球坐标系),是一种笛卡儿坐标系。原点 O (0,0,0)为地球质心,z 轴与地轴平行指向北极点,x 轴指向本初子午线与赤道的交点,y 轴垂直于xOz平面(即东经90度与赤道的交点)构成右手坐标系。

 

 常用的如WGS84坐标系

特点:与地球固定在一起,随地球一起转动。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是ENU坐标系ECEF坐标系的转换代码: ```c #include <math.h> // WGS84椭球体参数 const double a = 6378137.0; // 地球长半轴 const double b = 6356752.314245; // 地球短半轴 const double f = 1 / 298.257223563; // 地球扁率 const double e = sqrt(2 * f - f * f); // 地球第一偏心率 const double e2 = e * e; // 地球第二偏心率 // ENU坐标系ECEF坐标系的转换函数 void enu2ecef(double enu[3], double lat, double lon, double alt, double ecef[3]) { // 计算ENU坐标系到NED坐标系的转换矩阵 double cosLat = cos(lat); double sinLat = sin(lat); double cosLon = cos(lon); double sinLon = sin(lon); double R_ENU2NED[3][3] = { {-sinLon, cosLon, 0}, {-sinLat * cosLon, -sinLat * sinLon, cosLat}, {cosLat * cosLon, cosLat * sinLon, sinLat} }; // 计算ENU坐标系ECEF坐标系的转换矩阵 double R_NED2ECEF[3][3] = { {-sinLon, -sinLat * cosLon, cosLat * cosLon}, {cosLon, -sinLat * sinLon, cosLat * sinLon}, {0, cosLat, sinLat} }; // 计算ENU坐标系ECEF坐标系的转换矩阵 double R_ENU2ECEF[3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { R_ENU2ECEF[i][j] = 0; for (int k = 0; k < 3; k++) { R_ENU2ECEF[i][j] += R_NED2ECEF[i][k] * R_ENU2NED[k][j]; } } } // 计算ENU坐标系ECEF坐标系的转换向量 double ECEF_Origin[3], NED_Origin[3]; llh2ecef(lat, lon, alt, ECEF_Origin); llh2ned(lat, lon, alt, enu[0], enu[1], enu[2], NED_Origin); double ENU_Origin[3] = {NED_Origin[1], NED_Origin[0], -NED_Origin[2]}; double ECEF_enu[3]; for (int i = 0; i < 3; i++) { ECEF_enu[i] = 0; for (int j = 0; j < 3; j++) { ECEF_enu[i] += R_ENU2ECEF[i][j] * ENU_Origin[j]; } } // 计算ENU坐标点在ECEF坐标系中的位置 for (int i = 0; i < 3; i++) { ecef[i] = ECEF_Origin[i] + ECEF_enu[i]; } } // 经纬高坐标系ECEF坐标系的转换函数 void llh2ecef(double lat, double lon, double alt, double ecef[3]) { double N = a / sqrt(1 - e2 * sin(lat) * sin(lat)); ecef[0] = (N + alt) * cos(lat) * cos(lon); ecef[1] = (N + alt) * cos(lat) * sin(lon); ecef[2] = (N * (1 - e2) + alt) * sin(lat); } // 经纬高坐标系到NED坐标系的转换函数 void llh2ned(double lat, double lon, double alt, double lat0, double lon0, double alt0, double ned[3]) { double cosLat = cos(lat); double sinLat = sin(lat); double cosLon = cos(lon); double sinLon = sin(lon); double cosLat0 = cos(lat0); double sinLat0 = sin(lat0); double cosLon0 = cos(lon0); double sinLon0 = sin(lon0); double R_ENU2NED[3][3] = { {-sinLon0 * cosLat0, -sinLat0 * cosLon0, cosLat0}, {-sinLon0 * sinLat0, cosLat0 * cosLon0, sinLat0}, {cosLon0, sinLon0, 0} }; double ecef[3], ecef0[3]; llh2ecef(lat, lon, alt, ecef); llh2ecef(lat0, lon0, alt0, ecef0); for (int i = 0; i < 3; i++) { ned[i] = 0; for (int j = 0; j < 3; j++) { ned[i] += R_ENU2NED[i][j] * (ecef[i] - ecef0[j]); } } } ``` 以上是ENU坐标系ECEF坐标系的转换代码,其中 `enu` 表示ENU坐标系下的坐标,`lat`、`lon`、`alt` 分别表示参考点的纬度、经度和高度,`ecef` 表示转换后的ECEF坐标系下的坐标。 如果需要进行其他坐标系之间的转换,可以根据上面的代码进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江河地笑

实践是检验真理的唯一标准

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值