关于cesium的使用心得

本文介绍了如何在Cesium.js中进行模型展示、设置相机视角、操作地图、添加自定义地形和模型标点,以及处理地形切片和模型压缩的相关技术。
摘要由CSDN通过智能技术生成

我使用的版本是1.112,因为版本不同,有些方法跟写法会有区别,这个需要注意

主要功能是实现模型展示,模型测点显示以及改变模型构件颜色

Cesium.Ion.defaultAccessToken = '你的token'
var viewer = new Cesium.Viewer('cesiumContainer', {
        skyAtmosphere: new Cesium.SkyAtmosphere(),
        baseLayerPicker: false, // 影像切换
        animation: false, //是否显示动画控件
        timeline: false, //是否显示时间线控件
        infoBox: false, //是否显示点击要素之后显示的信息
        geocoder: false, //是否显示地名查找控件
        navigationHelpButton: false, //是否显示帮助信息控件
        fullscreenButton:false,//全屏
        vrButton:false,
        homeButton:false,//首页
        infoBox:false,//信息框
        sceneModePicker:false,//场景模式
        selectionIndicator:false,//选择指示器
        navigationHelpButton:false//时间线
    });

设置相机,相机视角:v_longitude:定位经度,v_latitude:定位纬度,v_height:相机高度,v_heading:水平旋转角度,v_pitch:俯仰角度,v_roll:翻滚角度

viewer.scene.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(//参数:(经度,纬度,椭球上方的高度)
            view.v_longitude,
            view.v_latitude,//调纬度可以拉近视角
            view.v_height
        ),
        orientation: {
            heading: Cesium.Math.toRadians(view.v_heading),
            pitch: Cesium.Math.toRadians(view.v_pitch),
            roll: Cesium.Math.toRadians(view.v_roll) //heading、pitch和roll就是镜头相对于xyz轴的角度,比如pitch为-90°而另外两个为0时,就是90°向下俯视地球
        }
    });

对地图进行操作需得等地图加载出来后再执行

// 最小缩放高度(米)
        viewer.scene.screenSpaceCameraController.minimumZoomDistance = 100;
        // 最大缩放高度(米)
        viewer.scene.screenSpaceCameraController.maximumZoomDistance = 8000;

        //显示部分区域113.38, 22.11, 113.51, 22.22
        let coffeeBeltRectangle = new Cesium.Rectangle.fromDegrees(113.226394, 21.930137, 113.500404, 22.095537);//最西的经度,最南端的纬度,最东的经度,最北端的纬度
        viewer.scene.globe.cartographicLimitRectangle = coffeeBeltRectangle;
        //添加地形
        // viewer.terrainProvider = await Cesium.createWorldTerrainAsync({//添加全球范围高质量地形数据的便捷方法
        //添加自定义地形数据源
        viewer.terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl('../../HTML_model/scripts/Assets/dem',{
            requestWaterMask: true, // 请求水体遮罩
            requestVertexNormals: true // 请求顶点法线以改善光照效果
        });
        //添加建筑
        // viewer.scene.primitives.add(await Cesium.createOsmBuildingsAsync());
        //关闭时间对于模型亮度的影响
        // viewer.scene.light = new Cesium.DirectionalLight({
        //     direction: new Cesium.Cartesian3(0.354925, -0.890918, -0.283358)
        // });

对模型进行标点需要先点击模型获取经纬度高度坐标,再将其转换成笛卡尔坐标

获取坐标的方法

const search = (viewer) => {
        const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
        handler.setInputAction(function (event) {
            var earthPosition = viewer.scene.pickPosition(event.position);
            var cartographic = Cesium.Cartographic.fromCartesian(earthPosition);
            var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
            var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);

            console.log("坐标",longitudeString, latitudeString, cartographic.height);
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    };

转换成笛卡尔坐标

const position = Cesium.Cartesian3.fromDegrees(
 113.37539144506866, 22.01542218818829, 28.297001267728
  );

将测点遍历显示出来

const a=a_data;//测点笛卡尔坐标数据
    // const a=[{
    //     x:	-2352750.078,y:		5421498.473   ,z:2390420.521
    // }];
    const modelPunctuation=(viewer) => {
        a.forEach((el,index)=>{
            $(`
            <div class="coordinate" id="speed${index}">
                <!-- <div class="coordinate_label">{{ item.CameraName }}</div> -->
                <img class="coordinate_icon" src="/HTML_model/images/coordinate.png">
            </div>
            `).appendTo('#speed_points');
            let speedEvent = viewer.scene.preRender.addEventListener(() => {//在场景更新之后以及场景渲染之前执行
                let ele = document.getElementById("speed" + index);
                if (ele != null) {
                    let scratch = new Cesium.Cartesian2();
                    let position = {//3D笛卡尔点位置
                        x:el.x,
                        y:el.y,
                        z:el.z
                    };
                    // console.log(position);
                    let canvasPosition =viewer.scene.cartesianToCanvasCoordinates(position, scratch);//将笛卡尔坐标中的位置转换为画布坐标
                    if (canvasPosition && canvasPosition.x && canvasPosition.y) {//未缩放时整体坐标偏移位置
                        ele.style.left = `${canvasPosition.x - ele.offsetWidth / 2}px`;
                        ele.style.top = `${canvasPosition.y- ele.offsetHeight / 2}px`;
                    }
                };
            });
        });
    };

如果需要对地图不满意的部分进行遮挡,可以使用以下方法,不过不能调旋转角度,不好用

const hqeq_Texture=(viewer)=>{
        // 图片的经纬度范围
        var west = 113.456355;
        var south = 22.154288;
        var east = 113.460418;
        var north = 22.157447;
        // 图片的URL
        var imageUrl = '../public/HTML_model/images/hqeq_texture.png';
        // 创建 imagery provider
        var rectangle = Cesium.Rectangle.fromDegrees(west, south, east, north);
        var imageProvider = new Cesium.UrlTemplateImageryProvider({
            url: imageUrl,
            rectangle: rectangle,
            minimumLevel:1,
            maximumLevel:1
        });
        // 添加图像层到视图
        viewer.imageryLayers.addImageryProvider(imageProvider);
    };

导入模型

//导入模型
    async function loadModel(modelURL){
        const position = Cesium.Cartesian3.fromDegrees(//位置
            view.longitude,
            view.latitude,
            view.height
        );
        const heading = Cesium.Math.toRadians(view.heading);//转换成弧度,左右旋转
        const pitch = view.pitch;//上下旋转
        const roll = view.roll;//翻转
        const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
        const orientation = Cesium.Transforms.headingPitchRollQuaternion(
            position,
            hpr
        );//转换成四元数
        const scale=new Cesium.Cartesian3(
            view.scale,
            view.scale,
            view.scale
        );
        const entity_id=view.codec;
        let modelMatrix=Cesium.Matrix4.fromTranslationQuaternionRotationScale(position, orientation, scale);
        let primitive =viewer.scene.primitives.add(await Cesium.Model.fromGltfAsync({
            id:entity_id,
            url: view.url,
            modelMatrix: modelMatrix,
            minimumPixelSize: 128,
            maximumScale: 2000,
            // color : Cesium.Color.RED// 改颜色,白色半透明材质可以使模型显得更亮#8f97aa
            color : Cesium.Color.fromCssColorString('#e0e4e7')// 改颜色,白色半透明材质可以使模型显得更亮
        }));
        getSensorsList(stage);
    };

找到模型的构件

let entity = viewer.scene.primitives._primitives.find(item=>item._id===monitor_project);

构件都在entity._nodesByName里面,设置构件颜色并存取原来颜色,用于恢复颜色

entity.getNode(node)._runtimeNode.node.primitives.map((p,index)=>{
                        node_color.push({id:index,o_color:p.material.metallicRoughness.baseColorFactor});
                        p.material.metallicRoughness.baseColorFactor=new Cesium.Cartesian4(1,0,0,1);
                    });

模型需要进行压缩,不然太大,具体参考GLTF(2):使用gltf-pipeline对gltf进行压缩_gltf文件在线压缩-CSDN博客

快捷添加地形以前是Cesium.createWorldTerrain,现在改为Cesium.createWorldTerrainAsync

添加自定义数据以前是这种写法

viewer.terrainProvider = await Cesium.CesiumTerrainProvider({
            url:'../../HTML_model/scripts/Assets/dem',
            requestWaterMask: true, // 请求水体遮罩
            requestVertexNormals: true // 请求顶点法线以改善光照效果
        });

现在是这种写法,使用formUrl

viewer.terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl('../../HTML_model/scripts/Assets/dem',{
            requestWaterMask: true, // 请求水体遮罩
            requestVertexNormals: true // 请求顶点法线以改善光照效果
        });

CesiumJS 重大变动记录(2023年) - 知乎

但是这样添加地形山形会导致平面也会凹凸不平,最好是添加自定义地形数据

首先在地理空间数据云下载地形数据,在cesiumlab进行地形切片

参考cesium示例集--4.加载地形服务_cesium 添加地形-CSDN博客

【CesiumJS-2】自定义地图图层与加载地形服务_cesium 添加天地图三维地名-CSDN博客

其他参考资料:

Cesium基础教程_cesium教程-CSDN博客

Cesium(四)常用代码总结_viewer.scene.cullingvolume属性-CSDN博客

cesium 模型上标点-CSDN客

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值