Cesium 提供了丰富的坐标转换方法,用于在不同坐标系之间进行转换。以下是 Cesium 中常用的坐标系统及其转换方法:
一、Cesium 常用坐标系
-
WGS84坐标系 (经纬度高程)
- 标准地理坐标系
- 格式: [经度, 纬度, 高度] (单位: 度, 度, 米)
-
笛卡尔空间直角坐标系 (Cartesian3)
- Cesium 内部使用的三维直角坐标系
- 原点在地球中心
- 格式: new Cartesian3(x, y, z)
-
场景坐标 (屏幕像素坐标)
- 二维屏幕坐标系
- 格式: [x, y] (单位: 像素)
二、基本坐标转换方法
1. WGS84 ↔ Cartesian3
// 经纬度高程 → 笛卡尔坐标
const cartesian = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
// 笛卡尔坐标 → 经纬度高程
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
2. WGS84弧度 ↔ WGS84角度
// 角度转弧度
const radians = Cesium.Math.toRadians(degrees);
// 弧度转角度
const degrees = Cesium.Math.toDegrees(radians);
3. 屏幕坐标 ↔ 场景坐标
// 屏幕坐标 → 场景坐标(世界坐标)
const pickedObject = viewer.scene.pick(windowPosition);
if (Cesium.defined(pickedObject)) {
const cartesian = viewer.scene.pickPosition(windowPosition);
}
// 场景坐标 → 屏幕坐标
const screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian);
三、高级坐标转换
1. 坐标系转换(不同参考系)
固定坐标系 :与地球固连的坐标系,随地球一起旋转
惯性坐标系:不随地球旋转的宇宙空间参考系(卫星轨道计算)
// 固定坐标系 → 惯性坐标系
const fixedToInertial = Cesium.Matrix4.fromRotationTranslation(
Cesium.Quaternion.fromHeadingPitchRoll(heading, pitch, roll),
position
);
// 惯性坐标系 → 固定坐标系
const inertialToFixed = Cesium.Matrix4.inverse(fixedToInertial, new Cesium.Matrix4());
2. 坐标变换(平移旋转缩放)
// 创建变换矩阵
const transform = Cesium.Matrix4.fromTranslationRotationScale({
translation: Cesium.Cartesian3.fromElements(x, y, z),
rotation: Cesium.Quaternion.fromHeadingPitchRoll(heading, pitch, roll),
scale: new Cesium.Cartesian3(1.0, 1.0, 1.0)
});
// 变换后的位置
const transformedPosition = Cesium.Matrix4.multiplyByPoint(
transform,
originalPosition,
new Cesium.Cartesian3()
);
3. 地形高度采样
// 获取某点的地形高度
const position = Cesium.Cartesian3.fromDegrees(longitude, latitude);
const height = viewer.scene.globe.getHeight(Cesium.Cartographic.fromCartesian(position));
// 或者使用采样方法
const promise = Cesium.sampleTerrain(viewer.terrainProvider, 11, [
Cesium.Cartographic.fromDegrees(longitude, latitude)
]);
Cesium.when(promise, function(updatedPositions) {
const height = updatedPositions[0].height;
});
四、实用工具函数
1. 计算两点间距离
const distance = Cesium.Cartesian3.distance(position1, position2);
// 或者计算地表距离
const geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(
Cesium.Cartographic.fromCartesian(position1),
Cesium.Cartographic.fromCartesian(position2)
);
const surfaceDistance = geodesic.surfaceDistance;
2. 计算方位角(Heading)
const heading = Cesium.Math.toDegrees(
Cesium.Cartesian3.angleBetween(
Cesium.Cartesian3.UNIT_X,
Cesium.Cartesian3.normalize(position, new Cesium.Cartesian3())
)
);
3. 坐标插值
// 线性插值
const interpolated = Cesium.Cartesian3.lerp(
startPosition,
endPosition,
t, // 插值系数 [0,1]
new Cesium.Cartesian3()
);
// 球面线性插值
const interpolated = Cesium.Cartesian3.slerp(
startPosition,
endPosition,
t,
new Cesium.Cartesian3()
);
五、常见问题解决方案
问题1:pickPosition获取的坐标不准确
// 解决方法1: 开启深度测试
viewer.scene.globe.depthTestAgainstTerrain = true;
// 解决方法2: 使用更精确的pick方法
const ray = viewer.camera.getPickRay(windowPosition);
const position = viewer.scene.globe.pick(ray, viewer.scene);
问题2:坐标转换精度问题
// 使用高精度计算方法
const cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(
cartesian,
new Cesium.Cartographic()
);
问题3:大量坐标转换性能优化
// 重用对象减少内存分配
const scratchCartographic = new Cesium.Cartographic();
const result = new Cesium.Cartesian3();
function convert(cartesian) {
return Cesium.Ellipsoid.WGS84.cartesianToCartographic(
cartesian,
scratchCartographic
);
}