[Cesium好好学习]坐标系统

Cesium 中存在多种类型的坐标系统, 其中日常会用到两种坐标系, 并且数据会在其之间进行频繁的相互转换.

经纬度坐标系WGS84 (Cartographic)

经纬度坐标系的原点在大地椭球体的几何中心. 根据不同的椭球体标准, 衍生出很多不同的坐标系. 其中, 我们最常用的坐标系就是WGS84.

WGS84 是一个通用标准, 也是 GPS 所使用的标准坐标系. 我国有一套自己的坐标系统 CGC-2000, 其坐标值是兼容 WGS84 的. (定义不同, 最终值近乎一致)

地理坐标系统WGS84

在 Cesium 中使用构造函数

 const pCartographic = new Cesium.Cartographic(lng, lat, height);

其中:

  1. longitude 和 latitude 各自都是使用的 弧度制 .
  2. height 是指基于大地椭球体的海拔高程 (In meters, above the ellipsoid).

如果在代码逻辑中需要用到一个初始化的经纬度坐标实例结构, 应当使用 Cartographic 类提供的取值器.

const pZero = Cesium.Cartographic.ZERO;

另外, Cartographic 类有如下几种常用静态方法:

// 克隆
Cesium.Cartographic.clone(cartographic, result);

// 值相等比较
Cesium.Cartographic.equals(left, right);

// 带容差值比较
Cesium.Cartographic.equalsEpsilon(left, right, epsilon);

// 从一个笛卡尔直角坐标系转换构造
Cesium.Cartographic.fromCartesian(cartesian, ellipsoid, result);

// 从一个经纬度数据构造
Cesium.Cartographic.fromDegrees(longitude, latitude, height, result);

// 从一个经纬度(弧度制)构造
Cesium.Cartographic.fromRadians(longitude, latitude, height, result);

// 将一个经纬度坐标实例转换为笛卡尔空间直角坐标系
Cesium.Cartographic.toCartesian(Cartographic, ellipsoid, result);

笛卡尔空间直角坐标系 (Cartesian3)

其正式名称为: 地心固定直角坐标系 (ECF) .

Cesium 的地球是绘制在 ECF 直角坐标系中的一个球.

刚开始认识到这一坐标系定义的时候, 会觉得它是反直觉的, 因为我们平日里从事地图相关工作时基本接触到的都是地理坐标系统 (GeoCoordination) , 和投影坐标系统 (PrjCoordination) . 这两者都是在描述地球表面曲面上的点. 下意识的, 我们容易把 Cartesian3 里定义的直角坐标系误读为一种投影方式.

其实两者没有关系, 笛卡尔空间直角坐标系是一个单独的坐标系统. 它建立在地球静止参考系上, 原点 (0, 0, 0) 在地球质心, X 轴 (1, 0, 0) 方向指向赤道与本初子午线 (0度经线) 的交点, Z 轴 (0, 0, 1) 方向指向北极点, Y 轴在赤道平面里与 XOZ 构成右手直角坐标系.

看了上图便知, (X, Y, Z) 三个坐标值都和高程没关系. 切忌将 Z 误作为高程相关的值.

在 Cesium 中, ECF 坐标实例有两种常见的构造方式.

// 从参数直接构造
const cartesian = Cesium.Cartesian3(x, y, z);

// 从一个地理坐标系转换而得
const cartesian = Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result);

和 Cartographic.ZERO 类似的, Cartesian3 也有几个内置常量:

Cesium.Cartesian3.ZERO;   // (0, 0, 0)
Cesium.Cartesian3.UNIT_X; // (1, 0, 0)
Cesium.Cartesian3.UNIT_Y; // (0, 1, 0)
Cesium.Cartesian3.UNIT_Z; // (0, 0, 1)

基于直角坐标系的特点(线性), Cartesian3 类实现了若干在数学上十分便利的工具方法, 以下列举几个可能常用的工具函数.

// 输出成基本类型. --> const {x, y, z} = cartesian; return [x, y, z];
Cesium.Cartesian3.pack(cartesian, array, startIndex);  // 存入已有的
Cesium.Cartesian3.packArray(cartesian, result);        // 创建新的

// 从基本类型导入
Cesium.Cartesian3.unpack(array, startingIndex, result);
Cesium.Cartesian3.unpackArray(array, result);

// 线性插值
Cesium.Cartesian3.lerp(start, end, t, result);

// 计算原点到坐标点的距离(magnitude)
Cesium.Cartesian3.magnitude(cartesian);

// 距离的平方
Cesium.Cartesian3.magnitudeSquared(cartesian);

// 向量相加
Cesium.Cartesian3.add(left, right, result);

// 求夹角 (单位化后, 点乘求cos, 叉乘求sin, 再atan求夹角)
Cesium.Cartesian3.angleBetween(left, right);

// 点乘 (数量积)
Cesium.Cartesian3.dot(left, right);

// 叉乘 (向量积)
Cesium.Cartesian3.cross(left, right, result);

// 等比缩放
Cesium.Cartesian3.multiplyByScalar(cartesian, divider, result);
Cesium.Cartesian3.divideByScalar(cartesian, divider, result);

// 自定义缩放
Cesium.Cartesian3.multiplyComponents(left, right, result);
Cesium.Cartesian3.divideComponents(left, right, result);

// 取最正交的坐标轴单位向量. 嘿这个很有意思诶.
Cesium.Cartesian3.mostOrthogonalAxis(cartesian, result);