cesuim利用插值实现平滑拐角 cesium

在近期的一个项目中要实现 根据后台数据生成轨迹动画,但是后台返回的数据在拐角处非常生硬,如下图

动画在拐角的地方会突然变化方向,想要实现动画平滑的拐角,想要后台完善数据是不可能的了,只能自己想办法,查了很多资料,推荐使用创建插值的方法。在Cesium官网中介绍了3中插值的使用方式,分别是:LinearApproximation、LagrangePolynomialApproximation、HermitePolynomialApproximation,相应的代码如下:

// LinearApproximation
entity.position.setInterpolationOptions({ 
    interpolationDegree : 1, 
    interpolationAlgorithm : Cesium.LinearApproximation 
});
// LagrangePolynomialApproximation

entity.position.setInterpolationOptions({ 
    interpolationDegree : 5, 
    interpolationAlgorithm : Cesium.LagrangePolynomialApproximation 
}); 
// HermitePolynomialApproximation

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

其中interpolationDegree数值越大,插值数越多。知识点说完了,以下是平滑动画实现的全部过程

1、从后台获取轨迹数据

      // 查询路线
      this.$get(false, '后台接口地址', '参数').then((res) => {
        if (!res.isError && res.data.length > 0) {
          const { data } = res;
          const polylineCollection = new Cesium.PolylineCollection();

          // 合成轨迹数据
          for (let t = 0, l = data.length; t < l; t++) {
            let path = [];
            data[t].TRACK.forEach((v) => {
              path.push(v.mapX * 1);
              path.push(v.mapY * 1);
              path.push(3); //设定一个默认的高程
            });

            // 折现集合
            polylineCollection.add({
              positions: Cesium.Cartesian3.fromDegreesArrayHeights(path),
            });
          }
          // 生成动画
          that.creatAnimat(polylineCollection._polylines[0])          
        } else {
          this.$message.error('没有查询到巡更轨迹');
        }
      });

2、生成动画

// 创建动画
    creatAnimat(line) {
      
      let modelUrl = '模型路径';
      let timeRate = 300; // 动画的时间

      
      viewer.clock.canAnimate = true;
      viewer.clock._shouldAnimate = true;

      const { length } = line._positions;
      const start = Cesium.JulianDate.fromDate(new Date());
      const stop = Cesium.JulianDate.addSeconds(start, length * timeRate, new Cesium.JulianDate());
      viewer.clock.startTime = start.clone();
      viewer.clock.stopTime = stop.clone();
      viewer.clock.currentTime = start.clone();
      viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; 
      viewer.clock.multiplier = 1; 
      const position = this.computeCirclularFlight(line, start, stop);

      this.nodeAnimationModel = viewer.entities.add({
        availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
          start,
          stop,
        })]),
        position,
        path:{
          show: true,
          width: 3,
          material: Cesium.Color.fromCssColorString('#03B24C'),
        },
        point:{
              pixelSize: 5,
              show: true, // 不能设为false
        },
        orientation: new Cesium.VelocityOrientationProperty(position),
        model: {
          uri: modelUrl,
          minimumPixelSize: 50,
          maximumScale: 100,
        },
      });
    },

3、计算轨迹,在这里设置了插值

// 计算轨迹
    computeCirclularFlight(line, start) {
      const { length } = line._positions;
      const property = new Cesium.SampledPositionProperty();
      // 设置平滑轨迹(利用插值实现)
      property.setInterpolationOptions({
        interpolationDegree: 2,  //值越大,越平滑,拐角越趋向圆形
        interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
      });
      let sum = 0;
      let distance;
      for (let i = 0; i < length; i++) {
        const pos = line._positions[i];
        if (i > 0) {
          const prepostion = line._positions[i - 1];
          distance = Cesium.Cartesian3.distance(pos, prepostion);
        }
        sum += distance || 0;
        const time = Cesium.JulianDate.addSeconds(start, sum / 20, new Cesium.JulianDate());
        if (i === length - 1) {
          viewer.clock.stopTime = time;
        }
        property.addSample(time, pos);
      }
      return property;
    },

最终效果

 

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值