Cesium快速入门到精通系列教程九:实现飞机动态圆锥形光柱扫描效果

重点思路:在于如何实现从圆锥上面到下面的动态扫描。

以下实现的Cesium版本为1.106。最终要实现的效果如下:

Cesium快速入门到精通系列教程九:实现飞机动态圆锥形光柱

一、定位初始场景

目的是将地球定位到自己需要的区域。

// 场景定位
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(121.195,21.813,738947.02),
    orientation :{
        heading : Cesium.Math.toRadians(355.1),
        pitch : Cesium.Math.toRadians(-75.3),
        roll :0.0
    }
});

二、加载动态飞机Entity模型

此处分为两个步骤,第一步进行动态数据的整理与拟合,第二步进行加载模型。

1 动态数据整理与拟合

此处主要运用了Cesium中的SampledPositionProperty类,该类的目的是给定不同时间的位置信息,返回线性插值后平滑的位置数据,优点在于位置轨迹线性变化,不突兀,丝滑具有物理世界的真实感。

// 定义一个数组,存储物体运动的时间和位置点
let positionData = [
      { time: 0, longitude: 120.49155063, latitude: 25.47218132,height:80000 },
      { time: 25, longitude: 119.7230824, latitude:23.027839,height:80000 },
  ];

let positionSampler = new Cesium.SampledPositionProperty();

positionSampler.setInterpolationOptions({
    interpolationDegree: 2,
    interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});

let startTime = new Cesium.JulianDate.now()

for (let i = 0; i < positionData.length; i++) {
    let data = positionData[i];
    let time = new Cesium.JulianDate.addSeconds(startTime, data.time, new Cesium.JulianDate());
    let position = new Cesium.Cartesian3.fromDegrees(data.longitude, data.latitude,data.height);
    positionSampler.addSample(time, position);
}

2 加载glb格式的Entity模型

此处注意调整scale(模型比例)参数的设置,避免模型看不到的现象,最后记得跳转到模型本身。

let model_entity = viewer.entities.add({
  name: "model_entity",
  position: positionSampler,
  orientation : new Cesium.VelocityOrientationProperty(positionSampler),
  // 设置朝向
  model: {
    show: true,
    uri: "/Assets/Cesium_Air.glb",
    scale: 4000, // 缩放比例
    minimumPixelSize: 128, // 最小像素大小
    maximumScale: 20000, // 模型的最大比例尺大小。minimumPixelSize的上限
    incrementallyLoadTextures: true, // 加载模型后纹理是否可以继续流入
    runAnimations: true, // 是否应启动模型中指定的glTF动画
    clampAnimations: true, // 指定glTF动画是否应在没有关键帧的持续时间内保持最后一个姿势
    shadows: Cesium.ShadowMode.ENABLED,
    heightReference: Cesium.HeightReference.NONE,
    color:Cesium.Color.WHITE.withAlpha(1)
  },
});

viewer.zoomTo(model_entity); //定位到模型

三 、创建跟随飞机模型移动的圆锥体

首先圆锥体的类型是“cylinder”,参数的含义分别为length(圆锥体的高度)、topRadius(圆锥体顶部半径)、bottomRadius(圆锥体底部半径)、material(圆锥体颜色)。设置圆锥体position的时候,需要注意两点:1、利用Cesium的CallbackProerty属性去动态设置position,2、设置圆锥体height的时候,要设置为飞机模型高度的一半,因为圆锥体的position在圆锥体的中心位置。

// 飞机扫描轴体
let cylinder_model = viewer.entities.add({
  name:'cylinder_entity',
  cylinder: {
    length: 80000, //圆锥高度
    topRadius: 0.0, //顶部半径
    bottomRadius: 20000.0, //底部半径
    material: Cesium.Color.fromCssColorString(`rgba(255,0,0,0.5)`), //圆的颜色,
  },
  position: new Cesium.CallbackProperty((time)=>{
    let pos = model_entity.position.getValue(time)
    if(!pos) return
    let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);
    let lon = Cesium.Math.toDegrees(cartographic.longitude);
    let lat = Cesium.Math.toDegrees(cartographic.latitude);
    return Cesium.Cartesian3.fromDegrees(lon,lat,40000)
  },false)
})

四 、创建环圆锥体扫描高亮圆

此处分为两个步骤讲解,第一步:绘制圆形平面,第二步是让圆半径和高度动态改变。

4.1 绘制圆形面

注意cesium中无直接绘制圆形,是通过椭圆进行绘制的,entity的类型为ellipse,部分参数解释:semiMinorAxis(短半轴)、semiMajorAxis(长半轴)、height为高度。

let circle_height = 0
let circle_radius = 0
let circle_model = viewer.entities.add({
  name:'circle_entity',
  position: new Cesium.CallbackProperty((time)=>{
    let pos = model_entity.position.getValue(time)
    if(!pos) return
    let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);
    let lon = Cesium.Math.toDegrees(cartographic.longitude);
    let lat = Cesium.Math.toDegrees(cartographic.latitude);
    return Cesium.Cartesian3.fromDegrees(lon,lat,80000)
  },false), 
  ellipse: {
    semiMinorAxis: new Cesium.CallbackProperty(()=>{
      return  circle_radius
    },false), // 短轴
    semiMajorAxis:new Cesium.CallbackProperty(()=>{
      return  circle_radius
    },false), // 长轴
    material: Cesium.Color.RED.withAlpha(1),
    outline: true,
    outlineColor: Cesium.Color.RED,
    outlineWidth: 10,
    height: new Cesium.CallbackProperty(()=>{
      return  circle_height
    },false),
  }
})

4.2 动态改变圆半径和高度

此处利用定时去动态改变圆的半径和高度,需要注意的是,此处采用cesium中math.lerp函数对中间值进行插值,该函数的作用是:通过输入参数(a,b,比例)去获取a,b之间对应比例的值。因此圆的半径应该由小到大(0-20000),圆的高度应该由高到低(80000-0)。

// 每100ms更新圆的大小与高度,3000ms为一循环。
let i = 0
let timeInterval =  setInterval(()=>{
  if(i>3000){
    i = 0
  }else{
    i +=100 
  }
  circle_height = Cesium.Math.lerp(80000,0,i/3000)
  circle_radius = Cesium.Math.lerp(0,20000,i/3000)
},100) 

五、时间轴相关参数

此处主要设置cesium时间轴的起始时间、终止时间等相关参数,需要注意的是记得最后销毁定时器。

let stopTime = Cesium.JulianDate.addSeconds(startTime, 30, new Cesium.JulianDate());
viewer.clock.startTime = startTime.clone();
viewer.clock.stopTime = stopTime.clone();
viewer.clock.currentTime = startTime.clone();
viewer.clock.shouldAnimate = true;
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;  
viewer.clock.multiplier = 1; 

viewer.clock.onStop(()=>{clearInterval(timeInterval)})

六、全部代码





七、再实现一个类似效果:

Cesium快速入门到精通系列教程九:实现飞机动态圆锥形光柱扫描效果_第1张图片

全部代码:





八、再实现一个类似效果:

Cesium快速入门到精通系列教程九:实现飞机动态圆锥形光柱扫描效果_第2张图片

全部代码





你可能感兴趣的:(cesium,cesium)