Cesium-雷达遮罩动态扫描

# 效果

在这里插入图片描述
最终完整代码请看下面的封装一栏

# 基本思路

我们将他分为两个步骤来做第一步加载一个ellipsoid加载半圆体,第二步用cesium提供的wall属性加载一个立体墙,运用cesium提供的viewer.clock.onTick开启动画效果听起来很简单。下面我们来进行实现

# 实现方法

第一步我们先用cesium中提供ellipsoid方法加载半圆体,先看一下ellipsoid中都有哪些属性

属性名属性含义
distanceDisplayCondition指定将在距相机多远的距离显示和隐藏 new Cesium.DistanceDisplayCondition(0.0,10.5e6 ),
fill设置填充色显示隐藏
heightReference默认值: HeightReference.NONE
innerRadii指定椭圆体的内半径 默认值: radii
material设置球体材质 如:new Cesium.Color.fromCssColorString("#00dcff82")
maximumClock设置指定椭球最大时钟角的属性
maximumCone指定椭圆体最大锥角的属性 如:Cesium.Math.toRadians(90)
minimumClock设置指定椭球最小时钟角的属性
minimumCone指定椭圆体最小锥角的属性
outline设置指定corridor 是否有轮廓的Property 。true或false
outlineColor轮廓线颜色
outlineWidth轮廓线宽度
radii设置指定椭圆体的半径。 Cartesian3 Property
shadows设置阴影 默认值: ShadowMode.DISABLED
show设置实体显示隐藏
slicePartitions设置指定每 360 度的径向切片数的属性 默认值: 64
stackPartitions设置指定堆栈数的属性 默认值: 64
subdivisions指定每个轮廓环的样本数,确定曲率的粒度 默认值: 128
viewer.entities.add({
   position: Cesium.Cartesian3.fromDegrees(
     -80,
     35
   ),
   ellipsoid: {
     radii: new Cesium.Cartesian3(
       100000.0,
       100000.0,
       100000.0
     ),
     maximumCone: Cesium.Math.toRadians(90),
     material: new Cesium.Color.fromCssColorString("#00dcff82"),
     outline: true,
     outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
     outlineWidth: 1,
     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
       0.0,
       10.5e6
     ),
   },
 });

现在我们就行看见一个静态的半球体
在这里插入图片描述
第二步我们cesium中提供的wall来加载里面类似扇叶在动的东西,先不着急写代码,我们先来看一下wall里面的属性值

属性含义值
material设置材质
maximumHeights用于墙顶的高度数组,而不是每个位置的高度
minimumHeights用于墙底的高度数组
outline设置指定corridor 是否有轮廓的Property 默认
outlineColor轮廓线颜色
outlineWidth轮廓线宽度
fill设置填充色显示隐藏
distanceDisplayConditionnew Cesium.DistanceDisplayCondition( 0.0, 5.5e6 )距相机多远的距离处显示或隐藏
shadowsShadowMode.DISABLED设置投影
showtrue或false实体显示隐藏(动态改变直接改变show就可以)

注意wall加载出来的立体墙并不不是我们想要的,看图我们可以知道我们想要一个1/4圆形立体墙,我们可以通过两个算法来得到,我们分为两步第一步先来确定平面扫描区域,在来确定里面扫描区域。
先来确定平面扫描区域

  // 根据第一个点 偏移距离 角度 求取第二个点的坐标
function calcPoints(x1, y1, radius, heading){
  var m = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(x1, y1));
  var rx = radius * Math.cos(heading * Math.PI / 180.0);
  var ry = radius * Math.sin(heading * Math.PI / 180.0);
  var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
  var d = Cesium.Matrix4.multiplyByPoint(m, translation, new Cesium.Cartesian3());
  var c = Cesium.Cartographic.fromCartesian(d);
  var x2 = Cesium.Math.toDegrees(c.longitude);
  var y2 = Cesium.Math.toDegrees(c.latitude);
  return computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}

确定立面扫描区域

// 根据两个点 开始角度、夹角度 求取立面的扇形
function computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
  let positionArr = [];
  positionArr.push(x1);
  positionArr.push(y1);
  positionArr.push(0);
  var radius = Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(x1, y1), Cesium.Cartesian3.fromDegrees(x2, y2));
  for (let i = fx; i <= fx + angle; i++) {
    let h = radius * Math.sin(i * Math.PI / 180.0);
    let r = Math.cos(i * Math.PI / 180.0);
    let x = (x2 - x1) * r + x1;
    let y = (y2 - y1) * r + y1;
    positionArr.push(x);
    positionArr.push(y);
    positionArr.push(h);
  }
  return positionArr;
}

然后来进行加载立体墙

// An highlighted block
viewer.entities.add({
   position: Cesium.Cartesian3.fromDegrees(
     -80,
		35
   ),
   wall: {
     positions: new Cesium.CallbackProperty(() => {
       return Cesium.Cartesian3.fromDegreesArrayHeights(positionArr);
     }, false),
     material: new Cesium.Color.fromCssColorString("#00dcff82"),
     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
       0.0,
       10.5e6
     ),
   },
 });
 var heading = 0;
var positionArr = calcPoints(
    -80,
	35,
    100000.0,//此处芋圆的半径保持一致
    heading 
);

此时我们可以看到一个静态的效果已经出来了,但是还出现了一个问题他并没有动,没有达到我们想要的效果如下图所示
在这里插入图片描述
我们在仔细观察cesium文档中给我们提供了一个viewer.clock.onTick方法

viewer.clock.onTick.addEventListener(() => {
  heading += 10.0;
  positionArr = calcPoints(
    -80,
	35,
 	100000.0,
    heading
  );
});

现在我们的动画效果就出现了,来看一眼完整代码

viewer.entities.add({
   position: Cesium.Cartesian3.fromDegrees(
     -80,
     35
   ),
   wall: {
     positions: new Cesium.CallbackProperty(() => {
       return Cesium.Cartesian3.fromDegreesArrayHeights(positionArr);
     }, false),
     material: new Cesium.Color.fromCssColorString("#00dcff82"),
     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
       0.0,
       10.5e6
     ),
   },
   ellipsoid: {
     radii: new Cesium.Cartesian3(
       100000.0,
       100000.0,
       100000.0
     ),
     maximumCone: Cesium.Math.toRadians(90),
     material: new Cesium.Color.fromCssColorString("#00dcff82"),
     outline: true,
     outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
     outlineWidth: 1,
     distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
       0.0,
       10.5e6
     ),
   },
 });
 var heading = 0;
var positionArr = calcPoints(
    -80,
	35,
    100000.0,//此处芋圆的半径保持一致
    heading 
);
viewer.clock.onTick.addEventListener(() => {
  heading += 10.0;
  positionArr = calcPoints(
    -80,
	35,
 	100000.0,
    heading
  );
});
 function calcPoints(x1, y1, radius, heading){
  var m = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(x1, y1));
  var rx = radius * Math.cos(heading * Math.PI / 180.0);
  var ry = radius * Math.sin(heading * Math.PI / 180.0);
  var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
  var d = Cesium.Matrix4.multiplyByPoint(m, translation, new Cesium.Cartesian3());
  var c = Cesium.Cartographic.fromCartesian(d);
  var x2 = Cesium.Math.toDegrees(c.longitude);
  var y2 = Cesium.Math.toDegrees(c.latitude);
  return computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}
function computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
  let positionArr = [];
  positionArr.push(x1);
  positionArr.push(y1);
  positionArr.push(0);
  var radius = Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(x1, y1), Cesium.Cartesian3.fromDegrees(x2, y2));
  for (let i = fx; i <= fx + angle; i++) {
    let h = radius * Math.sin(i * Math.PI / 180.0);
    let r = Math.cos(i * Math.PI / 180.0);
    let x = (x2 - x1) * r + x1;
    let y = (y2 - y1) * r + y1;
    positionArr.push(x);
    positionArr.push(y);
    positionArr.push(h);
  }
  return positionArr;
}

哇这代码看起来很乱,不便于后期维护,我们可以对其进行封装一下 ,让代码更加美观

# 封装

我们用es6 class对其进行封装,我们先命名一个js文件,trackMatte.js

/**
 * 
 * @param {Viewer} viewer
 * @param {Cartesian3} position 经纬度
 * @param {String} id 
 * @param {number} shortwaveRange 半径
 * @return {*}
 * 
*/

export default class TrackMatte {
    constructor(val) {
        this.viewer = val.viewer;
        this.id = val.id;
        this.shortwaveRange = val.shortwaveRange;
        this.longitude = val.position[0],
        this.latitude = val.position[1],
        this.position = Cesium.Cartesian3.fromDegrees(
          val.position[0],
          val.position[1],
        );
        this.heading = 0;
        this.positionArr = this.calcPoints(
            val.position[0],
            val.position[1],
            val.shortwaveRange,
            0
        ) //储存脏数据
        this.addEntities()
    }
    addEntities(){
        let entity = this.viewer.entities.add({
            id: this.id,
            position: this.position,
            wall: {
              positions: new Cesium.CallbackProperty(() => {
                return Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr);
              }, false),
              material: new Cesium.Color.fromCssColorString("#00dcff82"),
              distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
                0.0,
                10.5e6
              ),
            },
            ellipsoid: {
              radii: new Cesium.Cartesian3(
                this.shortwaveRange,
                this.shortwaveRange,
                this.shortwaveRange
              ),
              maximumCone: Cesium.Math.toRadians(90),
              material: new Cesium.Color.fromCssColorString("#00dcff82"),
              outline: true,
              outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
              outlineWidth: 1,
              distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
                0.0,
                10.5e6
              ),
            },
        });
        this.addPostRender()
    }
    addPostRender(){
        this.viewer.clock.onTick.addEventListener(() => {
            this.heading += 10.0;//可调节转动速度
            this.positionArr = this.calcPoints(
              this.longitude,
              this.latitude,
              this.shortwaveRange,
              this.heading
            );
        });
    }
    calcPoints(x1, y1, radius, heading) {
        var m = Cesium.Transforms.eastNorthUpToFixedFrame(
          Cesium.Cartesian3.fromDegrees(x1, y1)
        );
        var rx = radius * Math.cos((heading * Math.PI) / 180.0);
        var ry = radius * Math.sin((heading * Math.PI) / 180.0);
        var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
        var d = Cesium.Matrix4.multiplyByPoint(
          m,
          translation,
          new Cesium.Cartesian3()
        );
        var c = Cesium.Cartographic.fromCartesian(d);
        var x2 = Cesium.Math.toDegrees(c.longitude);
        var y2 = Cesium.Math.toDegrees(c.latitude);
        return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90);
    }
    computeCirclularFlight(x1, y1, x2, y2, fx, angle) {
        let positionArr = [];
        positionArr.push(x1);
        positionArr.push(y1);
        positionArr.push(0);
        var radius = Cesium.Cartesian3.distance(
          Cesium.Cartesian3.fromDegrees(x1, y1),
          Cesium.Cartesian3.fromDegrees(x2, y2)
        );
        for (let i = fx; i <= fx + angle; i++) {
          let h = radius * Math.sin((i * Math.PI) / 180.0);
          let r = Math.cos((i * Math.PI) / 180.0);
          let x = (x2 - x1) * r + x1;
          let y = (y2 - y1) * r + y1;
          positionArr.push(x);
          positionArr.push(y);
          positionArr.push(h);
        }
        return positionArr;
    }

}

最后我们只需在我们页面中引用即可

import TrackMatte from "./trackMatte.js"
trackMatte(){
	let trackMatte = new TrackMatte({
        viewer:viewer,
        id:1,
        shortwaveRange:100000.0,
        position:[-80,35],
     })
}

至此我们我们的效果就与开始图中的效果一摸一样了。大功告成

  • 10
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GIS-CL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值