cesium中各种类型坐标转换

目录

viewer.scene.pick(e.position) 

viewer.scene.pickPosition(e.position)  场景坐标

viewer.scene.globe.pick(viewer.camera.getPickRay(e.position), viewer.scene))  地表坐标

​viewer.camera.pickEllipsoid(e.position)  世界坐标

鼠标点击点位置,有以下情形:

  • 获取点击处屏幕坐标 
  • 获取鼠标点的对应椭球面位置
  • 获取加载地形后对应的经纬度和高程
  • 获取倾斜摄影或模型点击处的坐标

<template>
    <div id="cesiumContainer"></div>
</template>
    
<script setup>
import * as Cesium from "cesium";
import { onMounted } from "vue";

onMounted(() => {
    const viewer = new Cesium.Viewer("cesiumContainer", {
        infoBox: false, // 禁用沙箱,解决控制台报错
        selectionIndicator: false, //选择指示器
    });
    viewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏logo版权
    viewer.entities.add({
        name: "点",
        position: Cesium.Cartesian3.fromDegrees(-75.0, 30.0), //经纬度转世界坐标
        point: {
            show: true,
            color: Cesium.Color.GREEN,
            pixelSize: 20,
            outlineColor: Cesium.Color.YELLOW,
            outlineWidth: 3,
        },
    })

    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((e) => {
        console.log("e:", e);

        // 通过屏幕坐标获取当前位置的实体信息
        console.log("viewer.scene.pick(e.position):", viewer.scene.pick(e.position));//只有点击entity才不为undefined,否则就算点击地球也会是undefined

        console.log("viewer.scene.pickPosition(e.position):", viewer.scene.pickPosition(e.position));

        console.log("viewer.camera.pickEllipsoid(e.position):", viewer.camera.pickEllipsoid(e.position));

        console.log("viewer.scene.globe.pick(viewer.camera.getPickRay(e.position), viewer.scene)):", viewer.scene.globe.pick(viewer.camera.getPickRay(e.position), viewer.scene));

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

});
</script>
    
<style scoped>
#cesiumContainer {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    margin: 0;
    padding: 0;
    overflow: hidden;
}
</style>

其中,e.position中的x,y为屏幕坐标,屏幕左上角为原点

 

viewer.scene.pick(e.position) 

viewer.scene.pick (windowPosition,width , height ) →0bject 

拾取cesium场景中的空间对象,且返回最前面的一个空间对象,可以拾取entity实体,primitive图元,数据源datasource,3dtiles瓦片数据。

只有点击entity等实体才不为undefined,否则就算点击地球也会是undefined

    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((e) => {
        console.log("e:", e);

        let pickedObject = viewer.scene.pick(e.position)
        // 通过屏幕坐标获取当前位置的实体信息
        console.log("viewer.scene.pick(e.position):", viewer.scene.pick(e.position));//只有点击entity才不为undefined,否则就算点击地球也会是undefined

        if (!Cesium.defined(pickedObject)) {
            console.log("没有拾取到空间对象")
            return;
        }

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

viewer.scene.pickPosition(e.position)  场景坐标

  •     获取场景里的点的经纬度(模型上的点)。相机看过去第一个被挡住的模型(如entity)上的坐标
  •     可以采集entity,primitive,3dtile的坐标
  •     当拾取区域无entity,primitive,3dtile时,将返回一个无法预料的坐标(标准椭球面以下,无法使用,无法预料)
  • 只有在开启深度测试且不使用默认地形的情况下才是准确的,在未开启“地形深度检测”的情况下只能在3DTile上准确获取空间坐标

viewer.scene.pickPosition (windowPosition,result)→Cartesian3 

注意:获取到笛卡尔坐标存在不准确性:

1.在无地形的情况下,不开启深度测试,在地球上拾取是准确的;

2.在有地形的情况下,不开启深度测试,在地球上拾取是不准确的;因为存在深度问题,必须开启深度测试,即 viewer.scene.globe.depthTestAgainstTerrain = true。

总结:

pickPosition在depthTestAgainstTerrain=false时只能在3DTile上获取准确位置

depthTestAgainstTerrain=true时,在3DTile和底图上均能获取准确位置

    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((e) => {
        console.log("e:", e);
        let cartesian = viewer.scene.pickPosition(e.position);
        console.log("cartesian:", cartesian);

        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        console.log("cartographic:", cartographic);

        let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
        let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
        let alt = cartographic.height; // 高度
        let coordinate = {
            longitude: Number(lng.toFixed(6)),
            latitude: Number(lat.toFixed(6)),
            altitude: Number(alt.toFixed(2)),
        };
        console.log("coordinate:", coordinate);

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

viewer.scene.globe.pick(viewer.camera.getPickRay(e.position), viewer.scene))  地表坐标

  • 此方法无论是否存在地形,无论是否开启地形深度检测,获取与地形的笛卡尔坐标都是准确的,因为此方法只是与地形的求交,不包括模型、倾斜摄影表面 
  •     获取地表面的点的经纬度(地形上的点)
  •     将无视entity、3dtile,不能拾取其表面坐标
  •     获取当前点击视线与地球表面相交的坐标(有无地形时候均可用,无地形时高程几乎为0)

 let ray = viewer.camera.getPickRay(e.position);

viewer.scene.globe.pick (ray,scene,result ) Cartesian3

    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((e) => {
        console.log("e:", e);

        let ray = viewer.camera.getPickRay(e.position);
        console.log("ray:", ray);

        let cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        console.log("cartesian:", cartesian);

        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        console.log("cartographic:", cartographic);

        let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
        let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
        let alt = cartographic.height; // 高度
        let coordinate = {
            longitude: Number(lng.toFixed(6)),
            latitude: Number(lat.toFixed(6)),
            altitude: Number(alt.toFixed(2)),
        };
        console.log("coordinate:", coordinate);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

viewer.camera.pickEllipsoid(e.position)  世界坐标

  •     获取椭球上的点的经纬度(数学模型上的椭球)
  •     获取当前点击视线与标准椭球面相交处的坐标,无高程(恒为0)

viewer.scene.camera.pickEllipsoid (windowPosition,ellipsoid , result ) →Cartesian3

pickEllipsoid 只用于无地形椭球面的获取坐标,不可用于加载地形场景。在加载地形的场景上获取的坐标不准确

    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((e) => {
        console.log("e:", e);
        let cartesian = viewer.camera.pickEllipsoid(e.position);
        console.log("cartesian:", cartesian);

        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        console.log("cartographic:", cartographic);

        let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
        let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
        let alt = cartographic.height; // 高度,椭球面height永远等于0
        let coordinate = {
            longitude: Number(lng.toFixed(6)),
            latitude: Number(lat.toFixed(6)),
            altitude: Number(alt.toFixed(2)),
        };
        console.log("coordinate:", coordinate);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Cesium,我们可以使用`Cesium.Matrix3`和`Cesium.Cartesian3`等工具类来将J2000坐标系下的坐标转换为笛卡尔坐标系下的坐标。具体的操作步骤如下: 1. 创建一个`Cesium.Matrix3`类型的旋转矩阵,用来将J2000坐标系下的坐标转换为惯性坐标系下的坐标。可以使用`Cesium.Transforms.computeIcrfToFixedMatrix(date, result)`方法来创建这个旋转矩阵,其`date`参数表示当前时间,`result`参数表示创建的旋转矩阵。 2. 创建一个`Cesium.Cartesian3`类型的坐标点,表示J2000坐标系下的坐标。 3. 调用`Cesium.Matrix3.multiplyByVector(matrix, point, result)`方法,将旋转矩阵和J2000坐标系下的坐标进行相乘,得到惯性坐标系下的坐标。其`matrix`参数表示旋转矩阵,`point`参数表示J2000坐标系下的坐标,`result`参数表示计算结果。 4. 调用`Cesium.Transforms.pointToWindowCoordinates(viewer.scene, cartesian, result)`方法,将惯性坐标系下的坐标转换为屏幕坐标系下的坐标。其`viewer.scene`表示当前场景,`cartesian`参数表示惯性坐标系下的坐标,`result`参数表示计算结果。 完整的代码如下: ```javascript var j2000Position = new Cesium.Cartesian3(x, y, z); // J2000坐标系下的坐标点 var date = Cesium.JulianDate.now(); // 当前时间 var icrfToFixed = new Cesium.Matrix3(); Cesium.Transforms.computeIcrfToFixedMatrix(date, icrfToFixed); // 创建旋转矩阵 var inertialPosition = new Cesium.Cartesian3(); Cesium.Matrix3.multiplyByVector(icrfToFixed, j2000Position, inertialPosition); // 将J2000坐标系下的坐标转换为惯性坐标系下的坐标 var screenPosition = new Cesium.Cartesian2(); var scene = viewer.scene; if (scene.mode === Cesium.SceneMode.SCENE3D) { screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, inertialPosition); } else { screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, inertialPosition, screenPosition); } // 将惯性坐标系下的坐标转换为屏幕坐标系下的坐标 ``` 需要注意的是,上述代码的`viewer`变量表示当前的Cesium.Viewer对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值