cesium 添加无人机巡航轨迹

1,605 阅读5分钟

Cesium 实现播放无人机巡航轨迹

在 Cesium 中实现播放无人机巡航轨迹,主要涉及的api

  1. let property =new Cesium.SampledPositionProperty()
  2. viewer.clock.onTick.addEventListener((clock)=> {});
  3. viewer.clock

效果图

巡航轨迹效果图.png

使用

//引入
import { Track } from 'track';
import {getDataByName} 'getDataByName'
const viewer = new Cesium.Viewer('cesiumContainer');
//显示无人机
function  showDrone() {
      //获取无人机轨迹数据
      var b = getDataByName('高山下树村巡视');

      /**
       * @param {*} viewer
       * @param {*} options.speed 速度m/s
       * @param {*} options.stayTime 拍摄点等待时间
       * @param {*} options.Lines  点集合
       * @param {*} options.frustumFar  视锥长度
       * @param {*} options.shootCallback  拍摄点回调函数返回isShoot为true的shootId
       * @memberof Track
       */
      let roaming = new Track(viewer, {
        Lines: b,
        stayTime: 1,
        speed: 3,
        frustumFar: 10,
        shootCallback: function (shootId) {
          console.log(shootId);
        },
      });
      this.roaming = roaming;
      window.myRoaming = roaming;
      setTimeout(() => {
        // 开始飞行
        roaming.StartFlying();
        //改变观看角度
        // roaming.ChangePerspective('ViewSide');
        window.viewer.flyTo(roaming.dataSource);
      }, 1000);
    };
//返回数据

轨迹数据

//getDataByName.js
export function getDataByName(name) { 
  const trajectoryData = {
  高山下树村巡视: [
          {
            shootId: 1,
            aircraftAltitude: 1.013,
            aircraftLatitude: 23.948266565,
            aircraftLongitude: 115.73361269,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 2,
            aircraftAltitude: 122.768,
            aircraftLatitude: 23.949607669,
            aircraftLongitude: 115.73315135,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 3,
            aircraftAltitude: 131.457,
            aircraftLatitude: 23.950299679,
            aircraftLongitude: 115.733446393,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 4,
            aircraftAltitude: 129.369,
            aircraftLatitude: 23.951254545,
            aircraftLongitude: 115.734100852,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 5,
            aircraftAltitude: 131.612,
            aircraftLatitude: 23.952112852,
            aircraftLongitude: 115.734470997,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 6,
            aircraftAltitude: 126.981,
            aircraftLatitude: 23.952917515,
            aircraftLongitude: 115.735018167,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 7,
            aircraftAltitude: 137.017,
            aircraftLatitude: 23.953201829,
            aircraftLongitude: 115.735109362,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 8,
            aircraftAltitude: 134.756,
            aircraftLatitude: 23.953146668,
            aircraftLongitude: 115.735619208,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 9,
            aircraftAltitude: 116.025,
            aircraftLatitude: 23.952975006,
            aircraftLongitude: 115.73666527,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 10,
            aircraftAltitude: 108.798,
            aircraftLatitude: 23.95271215,
            aircraftLongitude: 115.737228534,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 11,
            aircraftAltitude: 115.438,
            aircraftLatitude: 23.952331276,
            aircraftLongitude: 115.737453839,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 12,
            aircraftAltitude: 122.532,
            aircraftLatitude: 23.951848479,
            aircraftLongitude: 115.737410924,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 13,
            aircraftAltitude: 124.454,
            aircraftLatitude: 23.951548071,
            aircraftLongitude: 115.736917397,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 14,
            aircraftAltitude: 113.606,
            aircraftLatitude: 23.951215477,
            aircraftLongitude: 115.736429235,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 15,
            aircraftAltitude: 111.247,
            aircraftLatitude: 23.950625391,
            aircraftLongitude: 115.735801598,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 16,
            aircraftAltitude: 112.885,
            aircraftLatitude: 23.95017478,
            aircraftLongitude: 115.735238335,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 17,
            aircraftAltitude: 121.049,
            aircraftLatitude: 23.949686618,
            aircraftLongitude: 115.734760901,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: true,
          },
          {
            shootId: 18,
            aircraftAltitude: 144.961,
            aircraftLatitude: 23.948983879,
            aircraftLongitude: 115.734299561,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 19,
            aircraftAltitude: 154.97,
            aircraftLatitude: 23.9483777,
            aircraftLongitude: 115.733907959,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
          {
            shootId: 20,
            aircraftAltitude: 1.689,
            aircraftLatitude: 23.947910996,
            aircraftLongitude: 115.733629009,
            gimbalPitchValue: -34.86589098646805,
            gimbalYawValue: -141.52559172027878,
            isShoot: false,
          },
        ],
  }
   return trajectoryData[name];
    }

track

//track.js
export class Track {
  /**
   *Creates an instance of Roaming.
   * @param {*} viewer 需要传入
   * @param {*} options.speed 速度m/s 需要传入
   * @param {*} options.stayTime 等待时间  需要传入
   * @param {*} options.Lines  点集合 需要传入
   * @param {*} options.shootCallback  拍设点回调函数
   * @memberof Track
   */
  constructor(viewer, options) {
    this.viewer = viewer;
    this.entity = undefined;
    this.entity1 = undefined;
    this.Lines = options.Lines;
    this.stayTime = options.stayTime;
    this.stayTimeCalc = options.stayTime;
    this.speed = options.speed;
    this.primitivesone = null;
    this.primitivestwo = null;
    this.spotLightCamera = null;
    this.frustumFar = options.frustumFar;
    this.dataSource;
    // this.RoamingSpeed
    this.onTickstate = false;
    this.shootCallback = options.shootCallback;
    this.TrackPath(options.Lines);
  }

  TrackPath(Lines) {
    var lins = [];
    this.dataSource = new Cesium.CustomDataSource('TrackPath');
    for (let i = 0; i < Lines.length; i++) {
      let LinesIndex = new Cesium.Cartesian3.fromDegrees(
        Lines[i].aircraftLongitude,
        Lines[i].aircraftLatitude,
        Lines[i].aircraftAltitude
      );
      this.dataSource.entities.add({
        position: LinesIndex,
        point: {
          pixelSize: 8,
          //点的颜色
          color: Cesium.Color.fromCssColorString('#19CAF1'),
        },
      });
      lins.push(Lines[i].aircraftLongitude);
      lins.push(Lines[i].aircraftLatitude);
      lins.push(Lines[i].aircraftAltitude);
    }
    this.dataSource.entities.add({
      polyline: {
        positions: new Cesium.Cartesian3.fromDegreesArrayHeights(lins),
        width: 2,
        // 修改线的颜色
        // material: Cesium.Color.fromCssColorString('#8BF5F2').withAlpha(0.5),
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.fromCssColorString('#19CAF1'),
          dashLength: 16,
        }),
      },
    });

    this.viewer.dataSources.add(this.dataSource);
    // this.ChangePerspective('ViewSide');
  }
  StartFlying() {
    this.property = this.ComputeRoamingLineProperty(this.Lines);
    //添加无人机模型
    this.InitRoaming(
      this.property.property,
      this.property.startTime,
      this.property.stopTime
    );
  }
  /**
   * @param {*} Lines 点集合
   * @returns
   * @memberof Track
   */
  ComputeRoamingLineProperty(Lines) {
    this.onTickstate = true;
    //用于将JavaScript日期对象转换为儒略日日期对象。
    // 儒略日是一种天文学中常用的日期表示方式,它表示自4713年1月1日中午12点以来的天数。
    // 在Cesium中,儒略日日期对象通常用于表示时间,例如场景中的当前时间、动画的开始时间和结束时间等
    let startTime = Cesium.JulianDate.fromDate(new Date());
    let stopTime;
    //SampledPositionProperty用于表示一个位置随时间变化的属性。该类通常用于在场景中添加动态元素,例如飞行路径、动画等。
    let property = new Cesium.SampledPositionProperty();
    let startWaiting, endWaiting;
    let Waiting = [];
    for (let i = 0, t = 0; i < Lines.length; i++) {
      if (i == 0) {
        t = 0;
      } else {
        //经纬度坐标转空间直角坐标
        let p1 = new Cesium.Cartesian3.fromDegrees(
          Lines[i - 1].aircraftLongitude,
          Lines[i - 1].aircraftLatitude,
          Lines[i - 1].aircraftAltitude
        );
        let p2 = new Cesium.Cartesian3.fromDegrees(
          Lines[i].aircraftLongitude,
          Lines[i].aircraftLatitude,
          Lines[i].aircraftAltitude
        );
        //计算两点之间的距离
        let d = Cesium.Cartesian3.distance(p1, p2);
        //计算两点之间的时间
        t += d / this.speed;
      }
      let LinesIndex = new Cesium.Cartesian3.fromDegrees(
        Lines[i].aircraftLongitude,
        Lines[i].aircraftLatitude,
        Lines[i].aircraftAltitude
      );
      //addSample('时间','位置')
      property.addSample(
        //Cesium.JulianDate.addSeconds(startTime, 2, new Cesium.JulianDate())则是将给定的儒略日日期对象增加指定的秒数后返回新的儒略日日期对象。
        //  需要注意的是,Cesium.JulianDate.addSeconds方法并不会修改原始的儒略日日期对象,而是返回一个新的儒略日日期对象。
        // 如果需要修改原始的儒略日日期对象,可以使用Cesium.JulianDate.addSeconds(startTime, 2, startTime)的形式。
        Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()),
        LinesIndex
      );
      //显示视椎体部分的逻辑
      if (Lines[i].isShoot == true) {
        startWaiting = Cesium.JulianDate.addSeconds(
          startTime,
          t,
          new Cesium.JulianDate()
        );
        t += this.stayTime || 1;
        //添加时间,位置
        property.addSample(
          Cesium.JulianDate.addSeconds(startTime, t, new Cesium.JulianDate()),
          LinesIndex
        );
        endWaiting = Cesium.JulianDate.addSeconds(
          startTime,
          t,
          new Cesium.JulianDate()
        );
        Waiting.push({
          startWaiting,
          endWaiting,
          shootId: Lines[i].shootId,
        });
      }

      if (i == Lines.length - 1) {
        stopTime = Cesium.JulianDate.addSeconds(
          startTime,
          t,
          new Cesium.JulianDate()
        );
      }
    }

    let k = true;
    this.viewer.clock.onTick.addEventListener((e) => {
      if (this.onTickstate) {
        this.resetPosition();
        // console.log(e)
        let finds = false;
        for (let i = 0; i < Waiting.length; i++) {
          if (
            Waiting[i].startWaiting.secondsOfDay < e.currentTime.secondsOfDay &&
            Waiting[i].endWaiting.secondsOfDay > e.currentTime.secondsOfDay
          ) {
            if (k) {
              //拍摄点的回调
              this.shootCallback(Waiting[i].shootId);
              //显示视椎体
              // this.SetLookCone(Waiting[i].shootId);
            }
            finds = true;
            break;
          }
        }
        if (finds) {
          k = false;
        } else {
          k = true;
        }
      }
    });
    // startTime.clone()则是创建startTime的副本
    // 设置场景中的起始时间为startTime
    this.viewer.clock.startTime = startTime.clone();
    // 设置场景中的结束时间为stopTime
    this.viewer.clock.stopTime = stopTime.clone();
    // 设置场景中的当前时间为startTime
    this.viewer.clock.currentTime = startTime.clone();
    // 设置时钟的范围为循环模式,即当时间到达结束时间时,会重新从起始时间开始循环。
    this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
    // 设置时间流逝的速度为1倍
    this.viewer.clock.multiplier = 1;
    // 设置场景中的动画效果为开启状态
    this.viewer.clock.shouldAnimate = true;

    return {
      property,
      startTime,
      stopTime,
    };
  }
  /**
   *
   *
   * @param {*} position computeRoamingLineProperty计算的属性 position是SampledPositionProperty的实例对象
   * @param {*} isPathShow path路径是否显示
   * @memberof Track
   */
  InitRoaming(position, start, stop) {
    this.entity = this.viewer.entities.add({
      //通过availability属性设置实体对象的可用时间段
      // 如果实体对象超过了availability属性设置的可用时间段,它将不会在场景中显示。
      // 具体来说,availability属性用于指定实体对象的可用时间段,
      // 如果实体对象的时间超出了这个时间段,它将被视为不可用,不会在场景中显示。
      // 因此,如果您希望实体对象在整个时间范围内都可见,可以将availability属性设置为包含整个时间范围的时间段。
      // 如果您希望实体对象在特定时间段内可见,可以将availability属性设置为该时间段的时间段对象
      availability: new Cesium.TimeIntervalCollection([
        new Cesium.TimeInterval({
          start: start,
          stop: stop,
        }),
      ]),
      // 位置列表 position是SampledPositionProperty的实例对象
      position: position,
      // 计算朝向
      orientation: new Cesium.VelocityOrientationProperty(position),
      // 加载模型
      model: {
        // 模型路径
        uri: './data/model/CesiumDrone.glb',
        // 模型最小刻度
        minimumPixelSize: 64,
        maximumSize: 128,
        // 设置模型最大放大大小
        maximumScale: 200,
        // 模型是否可见
        show: true,
        // 模型轮廓颜色
        silhouetteColor: Cesium.Color.WHITE,
        // 模型颜色  ,这里可以设置颜色的变化
        // color: Cesium.Color.fromCssColorString('#8BF5F2').withAlpha(0.5),
        // 仅用于调试,显示魔仙绘制时的线框
        debugWireframe: false,
        // 仅用于调试。显示模型绘制时的边界球。
        debugShowBoundingVolume: false,

        scale: 0.02,
        runAnimations: true, // 是否运行模型中的动画效果
      },
      path: {
        // 是用于设置路径实体对象的分辨率。
        // 具体来说,resolution属性用于设置路径实体对象的分段数,即将路径分成多少段进行绘制。
        // 在代码中,resolution:1表示将路径分成1段进行绘制,即不进行分段。
        // 如果您希望路径更加平滑,可以将resolution属性设置为更大的值,以增加路径的分段数。
        resolution: 1,
        // 属性用于设置路径的材质
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.1,
          color: Cesium.Color.RED,
        }),
        width: 10,
        // 设置路径是否可见。
        show: false,
        // show: true,
      },
    });
    console.log('position----', position);

    // this.viewer.trackedEntity = this.entity
  }

  /**
   *航迹模拟的暂停和继续
   *
   * @param {*} state bool类型 false为暂停,ture为继续
   * @memberof Track
   */
  PauseOrContinue(state) {
    this.viewer.clock.shouldAnimate = state;
  }

  SetLookCone(value) {
    // this.RemovePrimitives()

    setTimeout(() => {
      this.RemovePrimitives();
    }, this.stayTime * 1000);

    value = this.Lines.filter(function (item) {
      return item.shootId == value;
    });

    value = value[0];
    let positions = new Cesium.Cartesian3.fromDegrees(
      value.aircraftLongitude,
      value.aircraftLatitude,
      value.aircraftAltitude
    );
    this.spotLightCamera = new Cesium.Camera(this.viewer.scene);
    let spotLightCamera = this.spotLightCamera;

    spotLightCamera.setView({
      destination: positions,
      orientation: {
        // heading: Cesium.Math.toRadians(value.gimbalYawValue),
        heading: Cesium.Math.toRadians(0.0),
        // pitch: Cesium.Math.toRadians(value.gimbalPitchValue),
        pitch: Cesium.Math.toRadians(-90.0),
        roll: Cesium.Math.toRadians(0.0),
      },
    });

    let scratchRight = new Cesium.Cartesian3();
    let scratchRotation = new Cesium.Matrix3();
    var scratchOrientation = new Cesium.Quaternion();

    let position = spotLightCamera.positionWC;

    let directions = spotLightCamera.directionWC;
    let up = spotLightCamera.upWC;
    let right = spotLightCamera.rightWC;
    right = Cesium.Cartesian3.negate(right, scratchRight);

    let rotation = scratchRotation;
    Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
    Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
    Cesium.Matrix3.setColumn(rotation, 2, directions, rotation);
    //计算视锥姿态
    let orientation = Cesium.Quaternion.fromRotationMatrix(
      rotation,
      scratchOrientation
    );
    spotLightCamera.frustum.near = 0.1;
    spotLightCamera.frustum.far = this.frustumFar;
    //视锥轮廓线图形

    let instanceOutline = new Cesium.GeometryInstance({
      geometry: new Cesium.FrustumGeometry({
        frustum: spotLightCamera.frustum,
        origin: position,
        orientation: orientation,
      }),
      material: Cesium.Color.RED.withAlpha(1),
      id: 'pri' + this.viewer.scene.primitives.length + 1,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          new Cesium.Color(1.0, 1.0, 0.0, 0.5)
        ),
        show: new Cesium.ShowGeometryInstanceAttribute(true),
      },
    });

    let instance = new Cesium.GeometryInstance({
      geometry: new Cesium.FrustumOutlineGeometry({
        frustum: spotLightCamera.frustum,
        origin: position,
        // origin: new Cesium.CallbackProperty(() => {
        //   const positionProperty = this.property.property.getValue(
        //     Cesium.JulianDate.now()
        //   );
        //   const cartographic =
        //     Cesium.Cartographic.fromCartesian(positionProperty);
        //   const lon = Cesium.Math.toDegrees(cartographic.longitude);
        //   const lat = Cesium.Math.toDegrees(cartographic.latitude);
        //   const alt = cartographic.height;
        //   return Cesium.Cartesian3.fromDegrees(lon, lat, alt);
        // }, true),
        orientation: orientation,
      }),
      material: Cesium.Color.RED.withAlpha(0.1),
      id: 'pri0' + this.viewer.scene.primitives.length + 1,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          new Cesium.Color(1.0, 0.0, 0.0, 1)
        ),
        show: new Cesium.ShowGeometryInstanceAttribute(true),
      },
    });
    //外轮廓线
    this.primitivesone = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        geometryInstances: instance,
        appearance: new Cesium.PerInstanceColorAppearance({
          translucent: true,
          flat: true,
        }),
        asynchronous: false,
      })
    );

    // 视锥几何体
    this.primitivestwo = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        geometryInstances: instanceOutline,
        appearance: new Cesium.PerInstanceColorAppearance({
          translucent: true,
          flat: true,
        }),
        asynchronous: false,
      })
    );
  }
  /**
   * 删除视锥
   */
  RemovePrimitives() {
    if (this.primitivesone) {
      this.primitivesone.destroy();
      this.primitivestwo.destroy();
      this.spotLightCamera = null;
    }
  }
  /**
   * 根据时间动态更新视锥体
   */
  resetPosition() {
    this.RemovePrimitives();
    let positions = this.property.property.getValue(Cesium.JulianDate.now());
    const cartographic = Cesium.Cartographic.fromCartesian(positions);
    const alt = cartographic.height;
    this.spotLightCamera = new Cesium.Camera(this.viewer.scene);
    let spotLightCamera = this.spotLightCamera;

    spotLightCamera.setView({
      destination: positions,
      orientation: {
        // heading: Cesium.Math.toRadians(value.gimbalYawValue),
        heading: Cesium.Math.toRadians(0.0),
        // pitch: Cesium.Math.toRadians(value.gimbalPitchValue),
        pitch: Cesium.Math.toRadians(-90.0),
        roll: Cesium.Math.toRadians(0.0),
      },
    });

    let scratchRight = new Cesium.Cartesian3();
    let scratchRotation = new Cesium.Matrix3();
    var scratchOrientation = new Cesium.Quaternion();

    let position = spotLightCamera.positionWC;

    let directions = spotLightCamera.directionWC;
    let up = spotLightCamera.upWC;
    let right = spotLightCamera.rightWC;
    right = Cesium.Cartesian3.negate(right, scratchRight);

    let rotation = scratchRotation;
    Cesium.Matrix3.setColumn(rotation, 0, right, rotation);
    Cesium.Matrix3.setColumn(rotation, 1, up, rotation);
    Cesium.Matrix3.setColumn(rotation, 2, directions, rotation);
    //计算视锥姿态
    let orientation = Cesium.Quaternion.fromRotationMatrix(
      rotation,
      scratchOrientation
    );
    spotLightCamera.frustum.near = 0.1;
    spotLightCamera.frustum.far =
      this.frustumFar >= alt ? this.frustumFar : alt;
    //视锥轮廓线图形

    let instanceOutline = new Cesium.GeometryInstance({
      geometry: new Cesium.FrustumGeometry({
        frustum: spotLightCamera.frustum,
        origin: position,
        orientation: orientation,
      }),
      material: Cesium.Color.RED.withAlpha(1),
      id: 'pri' + this.viewer.scene.primitives.length + 1,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          Cesium.Color.fromCssColorString('#215B7F').withAlpha(0.5)
        ),
        show: new Cesium.ShowGeometryInstanceAttribute(true),
      },
    });

    let instance = new Cesium.GeometryInstance({
      geometry: new Cesium.FrustumOutlineGeometry({
        frustum: spotLightCamera.frustum,
        origin: position,
        orientation: orientation,
      }),
      material: Cesium.Color.RED.withAlpha(0.1),
      id: 'pri0' + this.viewer.scene.primitives.length + 1,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          Cesium.Color.fromCssColorString('#008DCF').withAlpha(0.8)
        ),
        show: new Cesium.ShowGeometryInstanceAttribute(true),
      },
    });
    //外轮廓线
    this.primitivesone = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        geometryInstances: instance,
        appearance: new Cesium.PerInstanceColorAppearance({
          translucent: true,
          flat: true,
        }),
        asynchronous: false,
      })
    );

    // 视锥几何体
    this.primitivestwo = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        geometryInstances: instanceOutline,
        appearance: new Cesium.PerInstanceColorAppearance({
          translucent: true,
          flat: true,
        }),
        asynchronous: false,
      })
    );
  }
  /**
   * 改变观看角度
   *
   * @param {*} name string
   *
   * ViewTopDown:顶视图
   * ViewSide :正视图
   * trackedEntity:跟随模型
   * @memberof Track
   */
  ChangePerspective(name) {
    if (name === 'ViewTopDown') {
      this.viewer.trackedEntity = undefined;
      this.viewer.flyTo(this.dataSource, {
        offset: {
          heading: 0,
          pitch: Cesium.Math.toRadians(-90),
          range: 35,
        },
      });
    } else if (name === 'ViewSide') {
      this.viewer.trackedEntity = undefined;
      this.viewer.flyTo(this.dataSource, {
        offset: {
          // heading: Cesium.Math.toRadians(-90),
          heading: Cesium.Math.toRadians(-90),
          // pitch: Cesium.Math.toRadians(-15),
          pitch: Cesium.Math.toRadians(-65),
          range: 50,
        },
      });
    } else if (name === 'trackedEntity') {
      this.viewer.trackedEntity = this.entity;
    }
  }
  /**
   *改变飞行的速度
   *
   * @param {*} value  整数类型
   * @memberof Track
   */
  ChangeRoamingSpeed(value) {
    this.viewer.clock.multiplier = value;
    this.stayTime = this.stayTimeCalc / value;
  }
  /**
   *
   *取消航迹模拟
   * @memberof Track
   */
  EndRoaming() {
    this.onTickstate = false;
    if (this.entity !== undefined) {
      this.viewer.entities.remove(this.entity);
    }
    if (this.dataSource !== undefined) {
      this.viewer.dataSources.remove(this.dataSource);
    }
    this.viewer.clock.multiplier = 1;
    this.RemovePrimitives();
  }
}