Cesium 中常用的坐标转换方法

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.jsgeographiclib 等外部库。

示例:使用 proj4js 进行 WGS84 到 UTM 的转换
  1. 首先引入 proj4 库。
  2. 定义坐标系统。
// 假设已引入 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 ↔ CartographicCartographic.fromCartesian, Cartesian3.fromDegrees / fromRadians
度 ↔ 弧度Cesium.Math.toRadians, Cesium.Math.toDegrees
WGS84 ↔ 其他投影 (如UTM)使用 proj4js 等外部库
局部坐标系 (如ENU) ↔ 世界坐标系Transforms.eastNorthUpToFixedFrame, Matrix4 操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值