当我们在Cesium中想要根据当前地图(可能加载了地形或者三维模型等第五要素)通过鼠标点击获取点坐标的时候,我们这时候就要根据鼠标点击的是地形还是模型,动态识别获取对应目标上的经纬度和高程数据,window.mapViewer则是创建的Cesium地图对象;
-
pick1 = viewer.scene.pickPosition(clickEvent.position);
- 此方法返回的是点击位置在三维空间中的笛卡尔坐标,不受地形影响,也就是说即使点击的位置下方是建筑物或其他地形特征,也会得到一个基于绝对空间坐标的点。
- 如果点击的位置在地球之外,例如背景星空或大气层外,也能得到一个坐标。
-
pick2 = viewer.scene.camera.pickEllipsoid(clickEvent.position);
- 此方法试图在默认的地球椭球体表面上找到对应的点,仅当点击位置落在地球表面或非常接近地球表面时才会返回有效的坐标。
- 如果点击位置在地形之上(如建筑物顶部)或地球之外,那么返回的结果可能是
undefined
。
-
ray = viewer.camera.getPickRay(clickEvent.position);
- 此方法获取从相机指向点击位置的射线。
pick3 = viewer.scene.globe.pick(ray, viewer.scene);
- 这个组合方法使用获取的射线,在三维地球场景中寻找实际的交点,通常用于获取地形的实际高度坐标。
- 如果点击位置在地形上,它会返回最接近地形表面的实际坐标;如果点击位置在地形之下或之上(比如建筑物内部或上方),则返回的是穿透地形表面后的第一个碰撞点的坐标。
总结来说:
pick1
获取的是基于绝对空间的任意位置坐标,高程值是点击的实体高程!!!。pick2
获取的是基于地球椭球体表面的理想坐标,受地形影响较小,返回值没有高度值!!!。pick3
获取的是实际地形上的精确坐标,考虑到了地形起伏,点击任何实体都是获取到该实体的垂直地表高程值,而不是该实体的高程值!!!。
getPoint() {
this.handler = new Cesium.ScreenSpaceEventHandler(
window.mapViewer.scene.canvas
);
this.handler.setInputAction(function (clickEvent) {
let mapPosition = {};
let pick1 = viewer.scene.pickPosition(clickEvent.position);
let pick2 = viewer.scene.camera.pickEllipsoid(clickEvent.position);
let ray = viewer.camera.getPickRay(clickEvent.position);
let pick3 = viewer.scene.globe.pick(ray, viewer.scene);
// 是否都获得了有效值
if (Cesium.defined(pick1) && Cesium.defined(pick2) && Cesium.defined(pick3)) {
let pickArray = [pick1, pick2, pick3];
pickArray.forEach((item) => {
// 笛卡尔坐标系转为经纬度(弧度)坐标
let cartographic = Cesium.Cartographic.fromCartesian(item);
// 再将经纬度(弧度)坐标转化为经纬度角度坐标
let lat = Cesium.Math.toDegrees(cartographic.latitude);
let lng = Cesium.Math.toDegrees(cartographic.longitude);
mapPosition = {
x: lng,
y: lat,
z: cartographic.height,
};
console.log("鼠标点击的点坐标", mapPosition);
});
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}