文章目录
1. 屏幕坐标 ↔ 场景中的三维世界坐标
这是最常见的转换,用于处理鼠标点击、悬停等交互。
屏幕坐标 → 三维世界坐标(包括地形和模型表面)
// 假设 handler 是一个 Scene.ScreenSpaceEventHandler
handler.setInputAction(function (movement) {
// 1. 获取鼠标点击位置的二维像素坐标
const windowPosition = movement.position;
// 2. 发射一条射线,获取与三维场景(包括地形、模型)的交点
const ray = viewer.camera.getPickRay(windowPosition);
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (cartesian) {
// 3. 将 Cartesian3 转换为 Cartographic(弧度制的经纬高)
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// 4. 将弧度转换为度
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
console.log(`经度: ${longitude}, 纬度: ${latitude}, 高度: ${height}`);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
关键方法:
Camera.getPickRay(windowPosition):从相机通过屏幕点创建一条射线。Globe.pick(ray, scene):求射线与地形的交点。Scene.pickPosition(windowPosition)(更推荐,更精确):直接从屏幕位置拾取三维坐标。这是在新版本中更准确的方法,尤其在使用DepthPlane后处理阶段时。
// 更现代的写法(推荐)
const cartesian = viewer.scene.pickPosition(movement.position);
if (cartesian) {
// ... 后续转换
}
三维世界坐标 → 屏幕坐标
// 假设你有一个三维世界坐标 cartesian3
const cartesian3 = Cesium.Cartesian3.fromDegrees(lon, lat, height);
// 将其转换为屏幕上的二维坐标
const screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
cartesian3
);
if (screenPosition) {
console.log(`屏幕X: ${screenPosition.x}, 屏幕Y: ${screenPosition.y}`);
}
关键方法:
SceneTransforms.wgs84ToWindowCoordinates(scene, cartesian):将 WGS84 坐标系中的点转换到屏幕像素坐标。
2. 三维世界坐标 (Cartesian3) ↔ 地理坐标 (Cartographic)
Cartesian3 是 Cesium 中最常用的三维直角坐标系表示(基于 WGS84 参考椭球)。Cartographic 是弧度制的地理坐标(经度、纬度、高度)。
Cartesian3 → Cartographic
const cartesian = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 1000); // 从度创建 Cartesian3
// 转换到 Cartographic(弧度)
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// 如果需要度
const longitudeDeg = Cesium.Math.toDegrees(cartographic.longitude);
const latitudeDeg = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
关键方法:
Cartographic.fromCartesian(cartesian, ellipsoid, result):最常用的方法。Ellipsoid.WGS84.cartesianToCartographic(cartesian, result):功能同上。
Cartographic → Cartesian3
// 从弧度创建 Cartographic
const cartographic = new Cesium.Cartographic(
Cesium.Math.toRadians(longitudeDeg),
Cesium.Math.toRadians(latitudeDeg),
height
);
// 转换到 Cartesian3
const cartesian = Cesium.Cartographic.toCartesian(cartographic);
// 或者更常用的:直接从度创建 Cartesian3
const cartesianFromDegrees = Cesium.Cartesian3.fromDegrees(longitudeDeg, latitudeDeg, height);
关键方法:
Cartographic.toCartesian(cartographic, ellipsoid, result)Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)(最常用)Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result)
3. 地理坐标 (度、分、秒) ↔ 弧度 (Radians)
Cesium 的内部计算大多使用弧度,但人类通常使用度。
度 ↔ 弧度
// 度 -> 弧度
const radians = Cesium.Math.toRadians(degrees);
// 弧度 -> 度
const degrees = Cesium.Math.toDegrees(radians);
关键方法:
Cesium.Math.toRadians(degrees)Cesium.Math.toDegrees(radians)
4. 与其他坐标系转换(例如:WGS84 ↔ UTM)
Cesium 核心库不直接提供 UTM、MGRS 等投影坐标系的转换。你需要使用 proj4.js 或 geographiclib 等外部库。
示例:使用 proj4js 进行 WGS84 到 UTM 的转换
- 首先引入 proj4 库。
- 定义坐标系统。
// 假设已引入 proj4
// 定义 WGS84 和 UTM Zone 50N 投影
const wgs84 = '+proj=longlat +datum=WGS84 +no_defs';
const utm50n = '+proj=utm +zone=50 +datum=WGS84 +units=m +no_defs';
// 要转换的经纬度(WGS84)
const lon = 116.3912;
const lat = 39.9075;
// 使用 proj4 进行转换
// 注意:proj4 参数顺序是 [lon, lat]
const utmCoords = proj4(wgs84, utm50n, [lon, lat]);
console.log(`UTM Easting: ${utmCoords[0]}, Northing: ${utmCoords[1]}`);
// UTM 转回 WGS84
const wgs84Coords = proj4(utm50n, wgs84, [utmCoords[0], utmCoords[1]]);
console.log(`Longitude: ${wgs84Coords[0]}, Latitude: ${wgs84Coords[1]}`);
5. 变换(Transforms)
这类方法用于在不同的参考系之间转换坐标,例如从局部坐标系到世界坐标系。
东北天坐标系 (ENU) ↔ 固定坐标系 (ECEF)
// 定义一个原点(例如北京)
const origin = Cesium.Cartesian3.fromDegrees(116.3912, 39.9075, 0);
// 计算该原点处的东北天 (ENU) 变换矩阵
const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
// 现在,假设你在原点东边10米,北边5米,天上20米有一个点
const localEnu = new Cesium.Cartesian3(10, 5, 20);
// 将局部 ENU 坐标转换到世界坐标 (ECEF)
const worldCoord = Cesium.Matrix4.multiplyByPoint(
enuMatrix,
localEnu,
new Cesium.Cartesian3()
);
// 世界坐标转回局部 ENU 坐标
const inverseMatrix = Cesium.Matrix4.inverse(enuMatrix, new Cesium.Matrix4());
const localCoordAgain = Cesium.Matrix4.multiplyByPoint(
inverseMatrix,
worldCoord,
new Cesium.Cartesian3()
); // localCoordAgain 应该约等于 (10, 5, 20)
关键方法:
Transforms.eastNorthUpToFixedFrame(origin, ellipsoid, result):生成从局部 ENU 系到地固系 (ECEF) 的变换矩阵。Transforms.northEastDownToFixedFrame(origin, ellipsoid, result):生成北-东-地 (NED) 系的变换矩阵。Matrix4.multiplyByPoint(matrix, cartesian, result):应用变换矩阵。
总结表格
| 转换方向 | 关键方法/类 |
|---|---|
| 屏幕 → 三维场景 | Scene.pickPosition(windowPosition) (推荐), Camera.getPickRay + Globe.pick |
| 三维场景 → 屏幕 | SceneTransforms.wgs84ToWindowCoordinates(scene, cartesian) |
| Cartesian3 ↔ Cartographic | Cartographic.fromCartesian, Cartesian3.fromDegrees / fromRadians |
| 度 ↔ 弧度 | Cesium.Math.toRadians, Cesium.Math.toDegrees |
| WGS84 ↔ 其他投影 (如UTM) | 使用 proj4js 等外部库 |
| 局部坐标系 (如ENU) ↔ 世界坐标系 | Transforms.eastNorthUpToFixedFrame, Matrix4 操作 |

370

被折叠的 条评论
为什么被折叠?



