直升机救火

文章介绍了如何使用Cesium.js库在网页上创建3D直升机救火模拟,包括飞行路径、粒子效果和时间线控制,展示了如何通过JulianDate处理时间轴并结合模型位置进行实时更新。
摘要由CSDN通过智能技术生成

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>直升机救火</title>

    <script  src = "../Build/CesiumUnminified/Cesium.js" ></script>

    <link href= "../Source/Widgets/widgets.css" rel="stylesheet">

    <!-- <style>

        @import url(../Apps/Sandcastle/templates/bucket.css);

    </style> -->

    <style>

        /* 在这里添加样式,或者在外部引入 CSS 文件 */

        @import url(../Apps/Sandcastle/templates/bucket.css);

        .btn {

          position: absolute;

          left: 300px;

          top: 30px;

          z-index: 999;

        }

    </style>

</head>

<body>

    <div id="cesiumContainer" class="fullSize"></div>

    <div class="btn"></div>

</body>

    <script>

        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlYmY2ZDliMi1jY2I2LTRhZTgtODY2OC04ZGUyYWRjNWU3YjgiLCJpZCI6MTg5MzA4LCJpYXQiOjE3MDUwMjk5OTJ9.iQOR9QCy0BI_2LdRcH-xyrM1qtgOH0BJy-zh2MEIe3c'

        const viewer = new Cesium.Viewer("cesiumContainer")

        // const position = Cesium.Cartesian3.fromDegrees(116.834276,36.549893,50)

        // let orientation = Cesium.Transforms.headingPitchRollQuaternion(position,new Cesium.HeadingPitchRoll(-45,0,0));

        // let entity =viewer.entities.add({

        //         position: position, // 为实体指定位置

        //         orientation: orientation, // 为实体指定方向

        //         model:{

        //             uri:"../cesium学习/helicopter_v2.glb",

        //             minimumPixelSize:100,

        //             maximumScale:1000,

        //             show:true

        //         }

        //     })

        viewer.camera.flyTo({

            destination:Cesium.Cartesian3.fromDegrees(116.827983,36.54521,50),

            orientation:{

                 heading:Cesium.Math.toRadians(45),

                 pitch:Cesium.Math.toRadians(-90),

                 roll:0

        },

            duration:0,

        })

        // //粒子系统的起点,发射源

        // var staticPosition = Cesium.Cartesian3.fromDegrees(116.827983,36.54521,3.614538127977399);

        // var entity1 = viewer.entities.add({

        //     position : staticPosition

        // });

        // viewer.scene.primitives.add(new Cesium.ParticleSystem({

        //     image : './Apps/SampleData/fire.png',

        //     startColor : Cesium.Color.RED.withAlpha(0.7),

        //     endColor : Cesium.Color.YELLOW.withAlpha(0.3),

        //     startScale : 0,

        //     endScale : 10,

        //     //设定粒子寿命可能持续时间的最小限值(以秒为单位),在此限值之上将随机选择粒子的实际寿命。

        //     minimumParticleLife : 1,

        //     maximumParticleLife : 6,

        //     minimumSpeed :1,

        //     maximumSpeed : 4,

        //     imageSize : new Cesium.Cartesian2(55, 55),

        //     // Particles per second.

        //     emissionRate : 4,

        //     lifetime : 160.0,

        //     //cesium内置的发射器,圆形发射器,因此参数是一个半径值

        //     //还有锥形发射器,new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0))

        //     //长方形发射器,new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0))

        //     //半球发射器,new Cesium.SphereEmitter(0.5)

        //     emitter : new Cesium.CircleEmitter(5.0),

        //     //将粒子系统从模型转换为世界坐标的4x4变换矩阵

        //     modelMatrix : computeModelMatrix(entity1),

        //     //在粒子系统局部坐标系中变换粒子系统发射器的4x4变换矩阵。  

        //     emitterModelMatrix : computeEmitterModelMatrix()

       

        // }));

        // function computeModelMatrix(entity) {

        //     let position = Cesium.Property.getValueOrUndefined(entity.position);

        //     let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);

        //     return modelMatrix;

        // }

        // function computeEmitterModelMatrix() {

        //     let  hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0);

        //     let trs = new Cesium.TranslationRotationScale();

        //     trs.translation = Cesium.Cartesian3.fromElements(2.5,4, 1);

        //     trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);

        //     let result=Cesium.Matrix4.fromTranslationRotationScale(trs);

        //     return result

        // }

        //----------------------------------------------------------------------

        // 创建时间线

        var start = Cesium.JulianDate.fromDate(new Date()); // 设置时间轴当前时间为开始时间

        var start = Cesium.JulianDate.addHours(start, 8, new Cesium.JulianDate()); // 开始时间加8小时改为北京时间

        var stop = Cesium.JulianDate.addSeconds(start, 20, new Cesium.JulianDate()); // 设置结束时间为开始时间加400秒

        // 设置时钟开始时间

        viewer.clock.startTime = start.clone();

        // 设置时钟当前时间

        viewer.clock.currentTime = start.clone();

        // 设置时钟结束时间

        viewer.clock.stopTime = stop.clone();

        // 时间速率,数字越大时间过的越快,设置1好像是和实际时间一样

        viewer.clock.multiplier = 1;

        // 时间轴绑定到viewer上去

        //viewer.timeline.zoomTo(start, stop);

        // 循环执行,到达终止时间,重新从起点时间开始

        //viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

        // 不循环执行,到达终止时间后停止

        viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;

        // 到达终止时间后,不重新到起点时间开始,而是停在终止时间

        //viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;    

        // 以 TICK_DEPENDENT 模式停止时钟

        //viewer.clock.clockStep = Cesium.ClockStep.TICK_DEPENDENT;

        //   =================================================

        //设置飞行轨迹

        var data = [

        {

            longitude: 116.828887,

            dimension:  36.545243,

            height: 100,

            time: 0,

            },

            {

            longitude: 116.828051,

            dimension:  36.545253,

            height: 100,

            time: 6.4,

            },

            {

            longitude: 116.828049,

            dimension: 36.545253,

            height: 100,

            time: 20,

            },

           

            // {

            // longitude: 116.827070,

            // dimension: 36.545243,

            // height: 100,

            // time: 19,

            // },

         

        ];

       

        let property = computeFlight(data); // 这是通过一个方法把时间轴和飞机的位置信息绑定了

       

        //   时间轴和飞机的位置信息绑定

        function computeFlight(source) {

            let property = new Cesium.SampledPositionProperty();

            for (let i = 0; i < source.length; i++) {

            let time = Cesium.JulianDate.addSeconds(

                start,

                source[i].time,

                new Cesium.JulianDate()

            );

            let position = Cesium.Cartesian3.fromDegrees(

                source[i].longitude,

                source[i].dimension,

                source[i].height

            );

            // 添加位置,和时间对应

            property.addSample(time, position);

            }

            return property;

        }

        let a = new Cesium.VelocityOrientationProperty(property)

        console.log(a)

        //   添加并移动飞机

        var entity2 = viewer.entities.add({

            availability: new Cesium.TimeIntervalCollection([

            new Cesium.TimeInterval({

                start: start,

                stop: stop,

            }),

            ]),

            position: property,

           

            // 基于位置计算方向角

            orientation: new Cesium.VelocityOrientationProperty(property),

            model: {

            uri: "../cesium学习/5.glb",

            minimumPixelSize:100,

            maximumScale:1000,//放大倍数

            },

            // 模拟的飞行路径

            path: {

            resolution: 1, //  这个不知道是啥

            material: new Cesium.PolylineGlowMaterialProperty({

                glowPower: 0.1, // 颜色透明度

                color: Cesium.Color.fromCssColorString("rgba(255, 255, 0, 1)"), // 路线颜色

            }),

            width:4 , // 路线的显示宽度

            },

        });

        // 视角跟随模型

        viewer.trackedEntity = entity2;

        // 计算当前时间点飞机模型的位置矩阵

        function computeModelMatrix(entity, time) {

            //获取位置

            var position = Cesium.Property.getValueOrUndefined(

            entity2.position,

            time,

            new Cesium.Cartesian3()

            );

            if (!Cesium.defined(position)) {

            return undefined;

            }

            //获取方向

            var modelMatrix;

            var orientation = Cesium.Property.getValueOrUndefined(

            entity.orientation,

            time,

            new Cesium.Quaternion()

            );

            if (!Cesium.defined(orientation)) {

            modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(

                position,

                undefined,

                new Cesium.Matrix4()

            );

            } else {

            modelMatrix = Cesium.Matrix4.fromRotationTranslation(

                Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()),

                position,

                new Cesium.Matrix4()

            );

            }

            return modelMatrix;

        }

        //console.log(Cesium.Math.PI_OVER_TWO);

        // 粒子发射器位置

        function computeEmitterModelMatrix(x, y, z) {

            //方向

            var hpr = Cesium.HeadingPitchRoll.fromDegrees(

            0.0,

            180,

            0.0,

            new Cesium.HeadingPitchRoll()

            );

            var trs = new Cesium.TranslationRotationScale();

       

            //以modelMatrix(飞机模型)中心为原点的坐标系的xyz轴位置偏移

            trs.translation = Cesium.Cartesian3.fromElements(

            x,

            y,

            z,

            new Cesium.Cartesian3()

            );

            trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(

            hpr,

            new Cesium.Quaternion()

            );

            return Cesium.Matrix4.fromTranslationRotationScale(

            trs,

            new Cesium.Matrix4()

            );

        }

        // 会有两个粒子 一个左喷口一个右喷口

        let particleSystemaArr = [];

        particleSystemaArr[0] = particleSystema(0, 0, -5);

        particleSystemaArr[1] = particleSystema(0, 0, -5);

        //   创建粒子系统

        function particleSystema(z, x, y) {

            var particle;

            particle = viewer.scene.primitives.add(

            new Cesium.ParticleSystem({

                image: "../cesium学习/penquan.png",

                startScale: 70, //粒子图像的初始比例

                endScale: 80, //粒子图像的结束比例

                //lifetime: 1.0, //粒子系统发射粒子的时间(以秒为单位)。

                emissionRate: 100, //每秒要发射的粒子数

                //emitter: new Cesium.CircleEmitter(0.5, Cesium.Cartesian3.UNIT_NEGATIVE_Z), // 设置方向为垂直向下

                //主模型参数(位置)

                // 发射器参数

                emitter: new Cesium.CircleEmitter(0.5,), //粒子发射器样式 圆形

                //emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(45.0)), //锥形

                // emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1.0, 1.0, 1.0)), //方形

                // emitter: new Cesium.SphereEmitter(0.5), //球形

                speed: 20,

                minimumParticleLife: 1, //粒子生命的可能持续时间的最小范围

                maximumParticleLife: 4, //粒子生命的可能持续时间的最大范围

                //颜色

                startColor: new Cesium.Color(1, 1, 1, 0.6), //粒子在其生命初期的颜色

                endColor: new Cesium.Color(0.8, 0.86, 1, 0.4), //粒子在其生命结束的颜色

                modelMatrix: computeModelMatrix(entity2, Cesium.JulianDate.now()), //从模型转换为世界坐标的4x4转换矩阵

                emitterModelMatrix: computeEmitterModelMatrix(z, x, y), // 粒子发射器模型矩阵,粒子发射器位置

            })

            );

            return particle;

        }

        viewer.scene.preRender.addEventListener(function (scene, time) {

            //重新计算位置

            particleSystemaArr[0].modelMatrix = computeModelMatrix(entity2, time);

            particleSystemaArr[1].modelMatrix = computeModelMatrix(entity2, time);

        });

        viewer.scene.preRender.addEventListener(function (scene, time) {

        //重新计算位置

        particleSystemaArr[0].modelMatrix = computeModelMatrix(entity2, time);

        particleSystemaArr[1].modelMatrix = computeModelMatrix(entity2, time);

    // 判断是否超过终止时间

    if (Cesium.JulianDate.compare(time, stop) === 0) {

        // 停止发射新的粒子

        particleSystemaArr[0].emissionRate = 1;

        particleSystemaArr[1].emissionRate = 1;

    }

});

    // 创建用于显示经纬度和高程的HTML元素

    const infoElement = document.createElement('div');

        infoElement.style.position = 'absolute';

        infoElement.style.bottom = '10px';

        infoElement.style.right = '10px';

        infoElement.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';

        infoElement.style.padding = '10px';

        viewer.container.appendChild(infoElement);

        // 监听鼠标左键点击事件

        viewer.screenSpaceEventHandler.setInputAction(function (clickEvent) {

            var ray = viewer.camera.getPickRay(clickEvent.position);

            var cartesian = viewer.scene.globe.pick(ray, viewer.scene);

            // 清空之前的内容

            infoElement.innerHTML = '';

            if (cartesian) {

                // 将笛卡尔坐标转换为经纬度和高程

                var cartographic = Cesium.Cartographic.fromCartesian(cartesian);

                // 获取经纬度和高程

                var longitude = Cesium.Math.toDegrees(cartographic.longitude);

                var latitude = Cesium.Math.toDegrees(cartographic.latitude);

                var height = cartographic.height;

                // 显示信息在右上方

                infoElement.innerHTML = '经度: ' + longitude.toFixed(6) + '<br>纬度: ' + latitude.toFixed(6) + '<br>高程: ' + height.toFixed(2);

            }

            var pick = viewer.scene.pickPosition(clickEvent.position);

            if (pick) {

                var height = Cesium.Cartographic.fromCartesian(pick).height;

                var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(pick).latitude);

                var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(pick).longitude);

                // 显示模型高度信息在右上方

                infoElement.innerHTML += '<br>模型高度: ' + height.toFixed(2);

            }

        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

       



 

        //----------------------------------------------------------------------

    </script>

    <script>

        viewer.scene.primitives.add(new Cesium.ParticleSystem({

            image: '../cesium学习/fire.png',

            startColor: Cesium.Color.LIGHTSEAGREEN.withAlpha(0.7),

            endColor: Cesium.Color.WHITE.withAlpha(0.0),

            startScale: 1.0,

            endScale: 5.0,

            minimumParticleLife: 1.2,

            maximumParticleLife: 1.2,

            minimumSpeed: 1.0,

            maximumSpeed: 4.0,

            emissionRate: 40,

            lifetime: 1,

            imageSize: new Cesium.Cartesian2(40, 40),

            emitter: new Cesium.CircleEmitter(2.0),

            modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(116.827983, 36.54521, 0))  

        }));

        //------------------------------------------------

       // 定义椭圆中心位置

        var centerPosition = Cesium.Cartesian3.fromDegrees(116.827983, 36.54521, 0);

        // 定义椭圆参数

        var semiMajorAxis = 100.0; // 长轴

        var semiMinorAxis = 60.0; // 短轴

        // 创建椭圆实体

        var ellipseEntity = viewer.entities.add({

            position: centerPosition,

            ellipse: {

                semiMajorAxis: semiMajorAxis,

                semiMinorAxis: semiMinorAxis,

                material: new Cesium.ImageMaterialProperty({

                image: '../cesium学习/渐变圆形.png',

                transparent: true

                })

            }

        });

        //------------------------------------------------

    </script>

</html>

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值