目录
老规矩首先看下效果
风场v1.0(平面版,只有U V 方向风速)
三维风场(不带高度)
(如果观看不了就点击链接:三维风场(不带高度)_哔哩哔哩_bilibili)
风场v2.0(高度版,加入W垂直风速)
三维风场(带垂直风速)
(如果观看不了就点击链接:三维风场(带垂直风速)_哔哩哔哩_bilibili)
风场v1.0结合风速热力图效果(风速只有计算U V 方向)
三维风场叠加风速热力图
(如果观看不了就点击链接:三维风场叠加风速热力图_哔哩哔哩_bilibili)
看完效果,那就开始风场吧
一、风场
1、数据
首先是风场的数据格式
这篇博客详细介绍了风场的数据格式,但这个是解析过后的,原始数据一般是netcdf数据或grib2数据,然后解析成类似上面展示的json格式。
其实那个我也没用他的,我只用了东西方向 V 的风速数据 、南北方向 U 的风速数据,垂直方向W 的风速数据 (一般你们不要求高度也不用这个数据,现在网上还没看到用垂直风速的),网格数(宽度+长度),网格的四至范围 ,这些就够了。
其中U 和 V 以及W 的数据是数组格式的,单位是m/s,数据长度是 网格数宽*高。
什么意思呢,你就想象成一个矩形的面,然后划分成多少行多少列(宽的意思就是多少列cols,高的意思就是多少行rows),也就是网上大家普遍说的构造棋盘格。每个格子都有初始的风速,东西方向和南北方向的。
看下我的数据吧

 
比如说上面风速有2256条数据,就是cols * rows 的数,代表每个47*48个网格里面的风速,分东西和南北的。
max和min就是这个方向上 数组里最大最小值,不是必须的,我是因为业务需要
2、原理剖析
根据网上大部队来吧,
首先,第一步就是构造网格数据
造好了上述的json数据后,还需要做一步事就是计算水平面上南北和东西方向结合的矢量数据,算向量模长 u*u + v*v 开根号,就是朝这个方向的风速,用来计算下一步风的经纬度的。这个没啥说的吧就是算向量。
看下我的棋盘格数据吧

是47*48条,然后每条数据是【u,v,w, Math.sqrt(u * u + v * v)】,没有高度的就没有w

然后,撒粒子
有了这么多格子,那我们就往这些个格子里面撒点吧,随机撒,以为我们也不知道风的起点在哪里,撒上就算作风的起点了,只需要计算下一步风的走向就行。
按随机撒5000个点吧,让这5000个点落在棋盘格内,(随机数落在四至内,不说了)

其中 age 表述粒子的生命周期,
lng,lat,height表示当前位置的经纬度高度,
tlng,tlat,theight表示下一步的位置经纬度高度,
speed表示水平方向的风速
如果你们用不上高度那就不要。
为什么不能用speed直接成风速呢?因为这个speed是水平方向的风速,他的风速不是m/s而是每一步所走的经纬度,如果你看其他人的源码就知道了,大家都是这么去做的,为什么不看我的源码呢?因为我不准备放我的源码!!!
所以高程点只能通过水平距离去算移动的时间,然后再 乘 垂直方向的风速 m/s (这是我所理解的算法,或许有大佬可以直接算三维向量的模长,算三维方向的风速那也是可以的,但是我就不麻烦了,我分开,水平是水平的,垂直另算)
再然后,起风吧
用canvas去做比cesium 的 primitive 效率会高上很多,我也是用canvas去做的。这里用到的是循环去 实现 canvas的画线以及浏览器的刷新机制 requestAnimationFrame 。
好了,到此就全部完成了。(具体的源码我就不放了,因为我也是站在别人的肩膀去完善的,网上也能找到源码,csdn上就有, 大家的源码都是这样的,我的被我改的乱七八糟的,给了也只会误导你们,如果你看了网上还不太明白的,那你联系我,有空我给你解答哈)
最后在插一嘴实现高度的方法,因为网上我没找到有实现高度的,用的都是canvas 2d 的方式,我最后实现了,但其实也是2d方法的,不过我觉得结合three.js去实现 应该可以完美复现三维风场垂直风速的那种效果。
现在说下高度的获取方法吧:
如果用上高度,那我多一嘴,这是网上其他都没有说到的,也是我自己胡JB想的,不知道对不对。
高度计算方法:首先撒完点后,拿到经纬度和下一步的经纬度后,算当前点的贴地高程,算当前点和下一个点的空间距离,计算出距离,比上速度,算出移动的时间,在根据时间 * 当前网格的垂直风速,就是这个点移动到下一个位置所移动的高度,最后再加上当前点的贴地高程即是下个点的高程数据。
二、热力场
热力场怎么做呢?在上面我们已经构建好网格数据了,那热力数据就展示每个网格的风速数据,这里我就只展示了uv方向的数据。
算好uv方向的数据,然后撒5000个点,计算每个点落在的网格数据,然后利用二分插值算法找到这个网格内的风速,把这个风速就赋给这个点作为这个点的value。这样一个热力图的数据就做好了。
接下来就是构建热力图层然后叠加了,这个网上都很完善了,我就不写了哈。
最后看下我的热力点位数据吧


如果你看到了这里,那么恭喜你,我最终还是决定把源码放上供大家参考下,但是我事先说明啊,我写的和网上大差不差,但是被我乱改一通。也不设置积分下载了,纯纯福利好不啦~
不带高度的
  
   - 
    
     
    
    
     
      /**
     
    
- 
    
     
    
    
     
       * @Description:风场
     
    
- 
    
     
    
    
     
       * @author MrKuang
     
    
- 
    
     
    
    
     
       * @date 2023/1/13 0013
     
    
- 
    
     
    
    
     
       */
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      class 
      CanvasWindy {
     
    
- 
    
     
    
    
         
      constructor(
      json, params) {
     
    
- 
    
     
    
    
             
      this.
      _windData = json;
     
    
- 
    
     
    
    
             
      this.
      _viewer = params.
      viewer;
     
    
- 
    
     
    
    
             
      this.
      _canvas = params.
      canvas;
     
    
- 
    
     
    
    
             
      //可配置的参数
     
    
- 
    
     
    
    
             
      this.
      _canvasContext = params.
      canvas.
      getContext(
      '2d')
      // canvas上下文
     
    
- 
    
     
    
    
             
      this.
      _canvasWidth = params.
      canvasWidth;
      //画布宽度
     
    
- 
    
     
    
    
             
      this.
      _canvasHeight = params.
      canvasHeight;
      //画布高度
     
    
- 
    
     
    
    
             
      this.
      _speedRate = params.
      speedRate || 
      50;
     
    
- 
    
     
    
    
             
      this.
      _particlesNumber = params.
      particlesNumber || 
      5000;
      //粒子数
     
    
- 
    
     
    
    
             
      this.
      _maxAge = params.
      maxAge || 
      120; 
      //粒子生命周期
     
    
- 
    
     
    
    
             
      this.
      _frameTime = 
      1000/(params.
      frameRate || 
      10) ;
      // 每秒刷新次数
     
    
- 
    
     
    
    
             
      this.
      _color = params.
      color || 
      '#ffffff';
     
    
- 
    
     
    
    
             
      this.
      _lineWidth = params.
      lineWidth || 
      1
      // 线宽度
     
    
- 
    
     
    
    
             
      // 内置参数
     
    
- 
    
     
    
    
             
      this.
      _grid = [];
     
    
- 
    
     
    
    
             
      this.
      _initExtent = []
      // 风场初始范围
     
    
- 
    
     
    
    
             
      this.
      _calc_speedRate = [
      0, 
      0]
      // 根据speedRate参数计算经纬度步进长度
     
    
- 
    
     
    
    
             
      this.
      _windField = 
      null
     
    
- 
    
     
    
    
             
      this.
      _particles = []
     
    
- 
    
     
    
    
             
      this.
      _animateFrame = 
      null
      // requestAnimationFrame事件句柄,用来清除操作
     
    
- 
    
     
    
    
             
      this.
      isdistory = 
      false
      // 是否销毁,进行删除操作
     
    
- 
    
     
    
    
             
      this.
      _init();
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
          
      _init(
      ) {
     
    
- 
    
     
    
    
             
      //创建棋盘格子
     
    
- 
    
     
    
    
             
      this.
      _createWindField();
     
    
- 
    
     
    
    
             
      this.
      _calcStep();
     
    
- 
    
     
    
    
             
      // 创建风场粒子
     
    
- 
    
     
    
    
             
      for (
      var i = 
      0; i < 
      this.
      _particlesNumber; i++) {
     
    
- 
    
     
    
    
                 
      this.
      _particles.
      push(
      this.
      _randomParticle(
      new 
      CanvasParticle()));
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      fillStyle = 
      'rgba(0, 0, 0, 0.97)'
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalAlpha = 
      0.6
     
    
- 
    
     
    
    
             
      this.
      _animate();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      var then = 
      Date.
      now();
     
    
- 
    
     
    
    
             
      let that = 
      this;
     
    
- 
    
     
    
    
     
              (
      function 
      frame(
      ) {
     
    
- 
    
     
    
    
                 
      if (!that.
      isdistory) {
     
    
- 
    
     
    
    
     
                      that.
      _animateFrame = 
      requestAnimationFrame(frame)
     
    
- 
    
     
    
    
                     
      var now = 
      Date.
      now();
     
    
- 
    
     
    
    
                     
      var delta = now - then;
     
    
- 
    
     
    
    
                     
      if (delta> that.
      _frameTime) {
     
    
- 
    
     
    
    
     
                          then = now - delta % that.
      _frameTime;
     
    
- 
    
     
    
    
     
                          that.
      _animate()
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  } 
      else {
     
    
- 
    
     
    
    
     
                      that.
      removeLines()
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
          
      _animate(
      ) {
     
    
- 
    
     
    
    
             
      var nextLng = 
      null
     
    
- 
    
     
    
    
             
      var nextLat = 
      null
     
    
- 
    
     
    
    
             
      var uv = 
      null
     
    
- 
    
     
    
    
              
      this.
      _graphicData = [];
     
    
- 
    
     
    
    
             
      this.
      _particles.
      forEach( 
      (particle) => {
     
    
- 
    
     
    
    
                 
      if (particle.
      age <= 
      0) {
     
    
- 
    
     
    
    
                      
      this.
      _randomParticle(particle);
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
                 
      if (particle.
      age > 
      0) {
     
    
- 
    
     
    
    
                     
      var tlng = particle.
      tlng
     
    
- 
    
     
    
    
                     
      var tlat = particle.
      tlat
     
    
- 
    
     
    
    
                     
      let height = particle.
      theight;
     
    
- 
    
     
    
    
                     
      var gridpos = 
      this.
      _togrid(tlng, tlat)
     
    
- 
    
     
    
    
                     
      var tx = gridpos[
      0]
     
    
- 
    
     
    
    
                     
      var ty = gridpos[
      1]
     
    
- 
    
     
    
    
                     
      if (!
      this.
      _isInExtent(tlng, tlat)) {
     
    
- 
    
     
    
    
     
                          particle.
      age = 
      0
     
    
- 
    
     
    
    
     
                      } 
      else {
     
    
- 
    
     
    
    
     
                          uv = 
      this.
      _getIn(tx, ty)
     
    
- 
    
     
    
    
     
                          nextLng = tlng + 
      this.
      calc_speedRate[
      0] * uv[
      0]
     
    
- 
    
     
    
    
     
                          nextLat = tlat + 
      this.
      calc_speedRate[
      1] * uv[
      1]
     
    
- 
    
     
    
    
     
                          particle.
      lng = tlng
     
    
- 
    
     
    
    
     
                          particle.
      lat = tlat
     
    
- 
    
     
    
    
     
                          particle.
      x = tx
     
    
- 
    
     
    
    
     
                          particle.
      y = ty
     
    
- 
    
     
    
    
     
                          particle.
      tlng = nextLng
     
    
- 
    
     
    
    
     
                          particle.
      tlat = nextLat
     
    
- 
    
     
    
    
     
                          particle.
      age--
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      if (
      this.
      _particles.
      length <= 
      0) 
      this.
      removeLines()
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      this.
      _drawLines()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      _drawLines(
      ) {
     
    
- 
    
     
    
    
             
      var particles = 
      this.
      _particles
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      lineWidth = 
      this.
      _lineWidth
     
    
- 
    
     
    
    
             
      // 后绘制的图形和前绘制的图形如果发生遮挡的话,只显示后绘制的图形跟前一个绘制的图形重合的前绘制的图形部分,示例:https://www.w3school.com.cn/tiy/t.asp?f=html5_canvas_globalcompop_all
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalCompositeOperation = 
      'destination-in'
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      fillRect(
      0, 
      0, 
      this.
      _canvasWidth, 
      this.
      _canvasHeight)
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalCompositeOperation = 
      'lighter'
      // 重叠部分的颜色会被重新计算
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalAlpha = 
      0.9
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      beginPath()
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      strokeStyle = 
      this.
      _color
     
    
- 
    
     
    
    
     
              particles.
      forEach(
      (particle) => {
     
    
- 
    
     
    
    
                 
      var movetopos = 
      this.
      _tomap(particle.
      lng, particle.
      lat, particle)
     
    
- 
    
     
    
    
                 
      var linetopos = 
      this.
      _tomap(particle.
      tlng, particle.
      tlat, particle)
     
    
- 
    
     
    
    
                 
      if (movetopos != 
      null && linetopos != 
      null) {
     
    
- 
    
     
    
    
                     
      this.
      _canvasContext.
      moveTo(movetopos[
      0], movetopos[
      1])
     
    
- 
    
     
    
    
                     
      this.
      _canvasContext.
      lineTo(linetopos[
      0], linetopos[
      1])
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      stroke()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 根据粒子当前所处的位置(棋盘网格位置),计算经纬度,在根据经纬度返回屏幕坐标
     
    
- 
    
     
    
    
         
      _tomap(
      lng, lat, particle) {
     
    
- 
    
     
    
    
             
      if (!lng || !lat) {
     
    
- 
    
     
    
    
                 
      return 
      null
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      var ct3 = 
      Cesium.
      Cartesian3.
      fromDegrees(lng, lat, 
      0)
     
    
- 
    
     
    
    
             
      // 判断当前点是否在地球可见端
     
    
- 
    
     
    
    
             
      var isVisible = 
      new 
      Cesium.
      EllipsoidalOccluder(
      Cesium.
      Ellipsoid.
      WGS84, 
      this.
      _viewer.
      camera.
      position).
      isPointVisible(ct3)
     
    
- 
    
     
    
    
             
      var pos = 
      Cesium.
      SceneTransforms.
      wgs84ToWindowCoordinates(
      this.
      _viewer.
      scene, ct3)
     
    
- 
    
     
    
    
             
      if (!isVisible) {
     
    
- 
    
     
    
    
     
                  particle.
      age = 
      0
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      return pos ? [pos.
      x, pos.
      y] : 
      null
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 粒子是否在地图范围内
     
    
- 
    
     
    
    
         
      _isInExtent(
      lng, lat) {
     
    
- 
    
     
    
    
             
      if ((lng >= 
      this.
      _windData.
      xmin && lng <= 
      this.
      _windData.
      xmax) && (lat >= 
      this.
      _windData.
      ymin && lat <= 
      this.
      _windData.
      ymax)) 
      return 
      true
     
    
- 
    
     
    
    
             
      return 
      false
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //创建棋盘格子
     
    
- 
    
     
    
    
         
      _createWindField(
      ) {
     
    
- 
    
     
    
    
             
      var k = 
      0
     
    
- 
    
     
    
    
             
      var rows = 
      null
     
    
- 
    
     
    
    
             
      var uv = 
      null
     
    
- 
    
     
    
    
             
      for (
      var j = 
      0; j < 
      this.
      _windData.
      rows; j++) {
     
    
- 
    
     
    
    
     
                  rows = []
     
    
- 
    
     
    
    
                 
      for (
      var i = 
      0; i < 
      this.
      _windData.
      cols; i++, k++) {
     
    
- 
    
     
    
    
     
                      uv = 
      this.
      _calcUV(
      this.
      _windData.
      udata[k], 
      this.
      _windData.
      vdata[k])
     
    
- 
    
     
    
    
     
                      rows.
      push(uv)
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
                 
      this.
      _grid.
      push(rows)
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      console.
      log(
      this.
      _grid)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //计算风场向量
     
    
- 
    
     
    
    
         
      _calcUV(
      u, v) {
     
    
- 
    
     
    
    
             
      return [+u, +v, 
      Math.
      sqrt(u * u + v * v)]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 计算经纬度步进长度
     
    
- 
    
     
    
    
         
      _calcStep(
      ) {
     
    
- 
    
     
    
    
             
      var calcSpeed = 
      this.
      _speedRate;
     
    
- 
    
     
    
    
             
      this.
      calc_speedRate = [(
      this.
      _windData.
      xmax - 
      this.
      _windData.
      xmin) / calcSpeed, (
      this.
      _windData.
      ymax - 
      this.
      _windData.
      ymin) / calcSpeed]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //根据风场范围随机生成粒子
     
    
- 
    
     
    
    
         
      _randomParticle(
      particle) {
     
    
- 
    
     
    
    
                 
      let safe = 
      30;
     
    
- 
    
     
    
    
                 
      let x = -
      1;
     
    
- 
    
     
    
    
                 
      let y = -
      1;
     
    
- 
    
     
    
    
                 
      let lng = 
      null;
     
    
- 
    
     
    
    
                 
      let lat = 
      null;
     
    
- 
    
     
    
    
                 
      do {
     
    
- 
    
     
    
    
                     
      try {
     
    
- 
    
     
    
    
     
                          lng = 
      this.
      _fRandomByfloat(
      this.
      _windData.
      xmin, 
      this.
      _windData.
      xmax)
     
    
- 
    
     
    
    
     
                          lat = 
      this.
      _fRandomByfloat(
      this.
      _windData.
      ymin, 
      this.
      _windData.
      ymax)
     
    
- 
    
     
    
    
     
                      } 
      catch (e) {
     
    
- 
    
     
    
    
                         
      // console.log(e)
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
                     
      if (lng) {
     
    
- 
    
     
    
    
                         
      //找到随机生成的粒子的经纬度在棋盘的位置 x y
     
    
- 
    
     
    
    
                         
      var gridpos = 
      this.
      _togrid(lng, lat);
     
    
- 
    
     
    
    
     
                          x = gridpos[
      0];
     
    
- 
    
     
    
    
     
                          y = gridpos[
      1];
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  } 
      while (
      this.
      _getIn(x, y)[
      2] <= 
      0 && safe++ < 
      30)
     
    
- 
    
     
    
    
                 
      let uv = 
      this.
      _getIn(x, y);
     
    
- 
    
     
    
    
                 
      var nextLng = lng + 
      this.
      calc_speedRate[
      0] * uv[
      0]
     
    
- 
    
     
    
    
                 
      var nextLat = lat + 
      this.
      calc_speedRate[
      1] * uv[
      1]
     
    
- 
    
     
    
    
     
                  particle.
      lng = lng
     
    
- 
    
     
    
    
     
                  particle.
      lat = lat
     
    
- 
    
     
    
    
     
              particle.
      x = x
     
    
- 
    
     
    
    
     
              particle.
      y = y
     
    
- 
    
     
    
    
     
              particle.
      tlng = nextLng
     
    
- 
    
     
    
    
     
              particle.
      tlat = nextLat
     
    
- 
    
     
    
    
     
              particle.
      speed = uv[
      2]
     
    
- 
    
     
    
    
     
              particle.
      age = 
      Math.
      round(
      Math.
      random() * 
      this.
      _maxAge)
      // 每一次生成都不一样
     
    
- 
    
     
    
    
             
      return particle;
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      _getIn(
      x, y) {
     
    
- 
    
     
    
    
             
      // 局部风场使用
     
    
- 
    
     
    
    
             
      if (x < 
      0 || x >= 
      this.
      _windData.
      cols || y >= 
      this.
      _windData.
      rows || y <= 
      0) {
     
    
- 
    
     
    
    
                 
      return [
      0, 
      0, 
      0]
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      var x0 = 
      Math.
      floor(x)
      //向下取整
     
    
- 
    
     
    
    
             
      var y0 = 
      Math.
      floor(y)
     
    
- 
    
     
    
    
             
      var x1;
     
    
- 
    
     
    
    
             
      var y1
     
    
- 
    
     
    
    
             
      if (x0 === x && y0 === y) 
      return 
      this.
      _grid[y][x]
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              x1 = x0 + 
      1
     
    
- 
    
     
    
    
     
              y1 = y0 + 
      1
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      var g00 = 
      this.
      _getIn(x0, y0)
     
    
- 
    
     
    
    
             
      var g10 = 
      this.
      _getIn(x1, y0)
     
    
- 
    
     
    
    
             
      var g01 = 
      this.
      _getIn(x0, y1)
     
    
- 
    
     
    
    
             
      var g11 = 
      this.
      _getIn(x1, y1)
     
    
- 
    
     
    
    
             
      var result = 
      null
     
    
- 
    
     
    
    
             
      // console.log(x - x0, y - y0, g00, g10, g01, g11)
     
    
- 
    
     
    
    
             
      try {
     
    
- 
    
     
    
    
     
                  result = 
      this.
      _bilinearInterpolation(x - x0, y - y0, g00, g10, g01, g11)
     
    
- 
    
     
    
    
                 
      // console.log(result)
     
    
- 
    
     
    
    
     
              } 
      catch (e) {
     
    
- 
    
     
    
    
                 
      console.
      log(x, y)
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      return result
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 二分差值算法计算给定节点的速度
     
    
- 
    
     
    
    
         
      _bilinearInterpolation(
      x, y, g00, g10, g01, g11) {
     
    
- 
    
     
    
    
             
      var rx = (
      1 - x)
     
    
- 
    
     
    
    
             
      var ry = (
      1 - y)
     
    
- 
    
     
    
    
             
      var a = rx * ry;
     
    
- 
    
     
    
    
             
      var b = x * ry;
     
    
- 
    
     
    
    
             
      var c = rx * y;
     
    
- 
    
     
    
    
             
      var d = x * y
     
    
- 
    
     
    
    
             
      var u = g00[
      0] * a + g10[
      0] * b + g01[
      0] * c + g11[
      0] * d
     
    
- 
    
     
    
    
             
      var v = g00[
      1] * a + g10[
      1] * b + g01[
      1] * c + g11[
      1] * d
     
    
- 
    
     
    
    
             
      return 
      this.
      _calcUV(u, v)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 随机数生成器(小数)
     
    
- 
    
     
    
    
         
      _fRandomByfloat(
      under, over) {
     
    
- 
    
     
    
    
             
      return under + 
      Math.
      random() * (over - under)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 根据经纬度,算出棋盘格位置
     
    
- 
    
     
    
    
         
      _togrid(
      lng, lat) {
     
    
- 
    
     
    
    
             
      var x = (lng - 
      this.
      _windData.
      xmin) / (
      this.
      _windData.
      xmax - 
      this.
      _windData.
      xmin) * (
      this.
      _windData.
      cols - 
      1)
     
    
- 
    
     
    
    
             
      var y = (
      this.
      _windData.
      ymax - lat) / (
      this.
      _windData.
      ymax - 
      this.
      _windData.
      ymin) * (
      this.
      _windData.
      rows - 
      1)
     
    
- 
    
     
    
    
             
      return [x, y]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _resize(
      width, height) {
     
    
- 
    
     
    
    
             
      this.
      canvasWidth = width
     
    
- 
    
     
    
    
             
      this.
      canvasHeight = height
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      removeLines(
      ) {
     
    
- 
    
     
    
    
             
      window.
      cancelAnimationFrame(
      this.
      _animateFrame)
     
    
- 
    
     
    
    
             
      this.
      isdistory = 
      true
     
    
- 
    
     
    
    
             
      this.
      _canvas.
      width = 
      1
     
    
- 
    
     
    
    
             
      document.
      getElementById(
      'box').
      removeChild(
      this.
      _canvas)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      function 
      CanvasParticle(
      ) {
     
    
- 
    
     
    
    
         
      this.
      lng = 
      null
      // 粒子初始经度
     
    
- 
    
     
    
    
         
      this.
      lat = 
      null
      // 粒子初始纬度
     
    
- 
    
     
    
    
         
      this.
      x = 
      null
      // 粒子初始x位置(相对于棋盘网格,比如x方向有360个格,x取值就是0-360,这个是初始化时随机生成的)
     
    
- 
    
     
    
    
         
      this.
      y = 
      null
      // 粒子初始y位置(同上)
     
    
- 
    
     
    
    
         
      this.
      tlng = 
      null
      // 粒子下一步将要移动的经度,这个需要计算得来
     
    
- 
    
     
    
    
         
      this.
      tlat = 
      null
      // 粒子下一步将要移动的y纬度,这个需要计算得来
     
    
- 
    
     
    
    
         
      this.
      age = 
      null
      // 粒子生命周期计时器,每次-1
     
    
- 
    
     
    
    
         
      this.
      speed = 
      null
      // 粒子移动速度,可以根据速度渲染不同颜色
     
    
- 
    
     
    
    
     
      }
     
    
 带高度的
  
   - 
    
     
    
    
     
      /**
     
    
- 
    
     
    
    
     
       * @Description:风场
     
    
- 
    
     
    
    
     
       * @author MrKuang
     
    
- 
    
     
    
    
     
       * @date 2023/1/13 0013
     
    
- 
    
     
    
    
     
       */
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      export 
      default 
      class 
      CanvasWindy {
     
    
- 
    
     
    
    
         
      constructor(
      json, params) {
     
    
- 
    
     
    
    
             
      this.
      _windData = json;
     
    
- 
    
     
    
    
             
      this.
      _viewer = params.
      viewer;
     
    
- 
    
     
    
    
             
      this.
      _canvas = params.
      canvas;
     
    
- 
    
     
    
    
             
      //可配置的参数
     
    
- 
    
     
    
    
             
      this.
      _canvasContext = params.
      canvas.
      getContext(
      '2d')
      // canvas上下文
     
    
- 
    
     
    
    
             
      this.
      _canvasWidth = params.
      canvasWidth;
      //画布宽度
     
    
- 
    
     
    
    
             
      this.
      _canvasHeight = params.
      canvasHeight;
      //画布高度
     
    
- 
    
     
    
    
             
      this.
      _speedRate = params.
      speedRate || 
      50;
     
    
- 
    
     
    
    
             
      this.
      _particlesNumber = params.
      particlesNumber || 
      5000;
      //粒子数
     
    
- 
    
     
    
    
             
      this.
      _maxAge = params.
      maxAge || 
      120; 
      //粒子生命周期
     
    
- 
    
     
    
    
             
      this.
      _frameTime = 
      1000/(params.
      frameRate || 
      10) ;
      // 每秒刷新次数
     
    
- 
    
     
    
    
             
      this.
      _color = params.
      color || 
      '#ffffff';
     
    
- 
    
     
    
    
             
      this.
      _lineWidth = params.
      lineWidth || 
      1
      // 线宽度
     
    
- 
    
     
    
    
             
      // 内置参数
     
    
- 
    
     
    
    
             
      this.
      _grid = [];
     
    
- 
    
     
    
    
             
      this.
      _initExtent = []
      // 风场初始范围
     
    
- 
    
     
    
    
             
      this.
      _calc_speedRate = [
      0, 
      0]
      // 根据speedRate参数计算经纬度步进长度
     
    
- 
    
     
    
    
             
      this.
      _windField = 
      null
     
    
- 
    
     
    
    
             
      this.
      _particles = []
     
    
- 
    
     
    
    
             
      this.
      _animateFrame = 
      null
      // requestAnimationFrame事件句柄,用来清除操作
     
    
- 
    
     
    
    
             
      this.
      isdistory = 
      false
      // 是否销毁,进行删除操作
     
    
- 
    
     
    
    
             
      this.
      _zspeed = 
      0;
     
    
- 
    
     
    
    
             
      this.
      _init();
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _init(
      ) {
     
    
- 
    
     
    
    
             
      //创建棋盘格子
     
    
- 
    
     
    
    
             
      this.
      _createWindField();
     
    
- 
    
     
    
    
             
      this.
      _calcStep();
     
    
- 
    
     
    
    
             
      // 创建风场粒子
     
    
- 
    
     
    
    
             
      for (
      var i = 
      0; i < 
      this.
      _particlesNumber; i++) {
     
    
- 
    
     
    
    
                 
      this.
      _particles.
      push(
      this.
      _randomParticle(
      new 
      CanvasParticle()));
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      fillStyle = 
      'rgba(0, 0, 0, 0.97)'
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalAlpha = 
      0.6
     
    
- 
    
     
    
    
             
      this.
      _animate();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      var then = 
      Date.
      now();
     
    
- 
    
     
    
    
             
      let that = 
      this;
     
    
- 
    
     
    
    
     
              (
      function 
      frame(
      ) {
     
    
- 
    
     
    
    
                 
      if (!that.
      isdistory) {
     
    
- 
    
     
    
    
     
                      that.
      _animateFrame = 
      requestAnimationFrame(frame)
     
    
- 
    
     
    
    
                     
      var now = 
      Date.
      now();
     
    
- 
    
     
    
    
                     
      var delta = now - then;
     
    
- 
    
     
    
    
                     
      if (delta> that.
      _frameTime) {
     
    
- 
    
     
    
    
     
                          then = now - delta % that.
      _frameTime;
     
    
- 
    
     
    
    
     
                          that.
      _animate()
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  } 
      else {
     
    
- 
    
     
    
    
     
                      that.
      removeLines()
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _animate(
      ) {
     
    
- 
    
     
    
    
             
      var nextLng = 
      null
     
    
- 
    
     
    
    
             
      var nextLat = 
      null
     
    
- 
    
     
    
    
             
      var uvw = 
      null;
     
    
- 
    
     
    
    
             
      this.
      _graphicData = [];
     
    
- 
    
     
    
    
             
      this.
      _particles.
      forEach(
      (particle) => {
     
    
- 
    
     
    
    
                 
      if (particle.
      age <= 
      0) {
     
    
- 
    
     
    
    
                     
      this.
      _randomParticle(particle);
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
                 
      if (particle.
      age > 
      0) {
     
    
- 
    
     
    
    
                     
      var tlng = particle.
      tlng
     
    
- 
    
     
    
    
                     
      var tlat = particle.
      tlat
     
    
- 
    
     
    
    
                     
      let height = particle.
      theight;
     
    
- 
    
     
    
    
                     
      var gridpos = 
      this.
      _togrid(tlng, tlat)
     
    
- 
    
     
    
    
                     
      var tx = gridpos[
      0]
     
    
- 
    
     
    
    
                     
      var ty = gridpos[
      1]
     
    
- 
    
     
    
    
                     
      if (!
      this.
      _isInExtent(tlng, tlat)) {
     
    
- 
    
     
    
    
     
                          particle.
      age = 
      0
     
    
- 
    
     
    
    
     
                      } 
      else {
     
    
- 
    
     
    
    
     
                          uvw = 
      this.
      _getIn(tx, ty)
     
    
- 
    
     
    
    
     
                          nextLng = tlng + 
      this.
      _calc_speedRate[
      0] * uvw[
      0]
     
    
- 
    
     
    
    
     
                          nextLat = tlat + 
      this.
      _calc_speedRate[
      1] * uvw[
      1]
     
    
- 
    
     
    
    
     
                          particle.
      lng = tlng
     
    
- 
    
     
    
    
     
                          particle.
      lat = tlat
     
    
- 
    
     
    
    
     
                          particle.
      x = tx
     
    
- 
    
     
    
    
     
                          particle.
      y = ty
     
    
- 
    
     
    
    
     
                          particle.
      tlng = nextLng
     
    
- 
    
     
    
    
     
                          particle.
      tlat = nextLat
     
    
- 
    
     
    
    
     
                          particle.
      height = height;
     
    
- 
    
     
    
    
                         
      //计算空间距离
     
    
- 
    
     
    
    
                         
      let d = mars3d.
      MeasureUtil.
      getDistance([
      new mars3d.
      LngLatPoint(particle.
      lng, particle.
      lat, 
      0), 
      new mars3d.
      LngLatPoint(particle.
      tlng, particle.
      tlat, 
      0)])
     
    
- 
    
     
    
    
                         
      let t = d / uvw[
      3];
     
    
- 
    
     
    
    
     
                          particle.
      theight = particle.
      height + t * uvw[
      2];
     
    
- 
    
     
    
    
     
                          particle.
      age--
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      if (
      this.
      _particles.
      length <= 
      0) 
      this.
      removeLines()
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      this.
      _drawLines()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _drawLines(
      ) {
     
    
- 
    
     
    
    
             
      var particles = 
      this.
      _particles
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      lineWidth = 
      this.
      _lineWidth
     
    
- 
    
     
    
    
             
      // 后绘制的图形和前绘制的图形如果发生遮挡的话,只显示后绘制的图形跟前一个绘制的图形重合的前绘制的图形部分,示例:https://www.w3school.com.cn/tiy/t.asp?f=html5_canvas_globalcompop_all
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalCompositeOperation = 
      'destination-in'
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      fillRect(
      0, 
      0, 
      this.
      _canvasWidth, 
      this.
      _canvasHeight)
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalCompositeOperation = 
      'lighter'
      // 重叠部分的颜色会被重新计算
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      globalAlpha = 
      0.9
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      beginPath()
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      strokeStyle = 
      this.
      _color
     
    
- 
    
     
    
    
     
              particles.
      forEach(
      (particle) => {
     
    
- 
    
     
    
    
                 
      var movetopos = 
      this.
      _tomap(particle.
      lng, particle.
      lat, particle)
     
    
- 
    
     
    
    
                 
      var linetopos = 
      this.
      _tomap1(particle.
      tlng, particle.
      tlat, particle)
     
    
- 
    
     
    
    
                 
      if (movetopos != 
      null && linetopos != 
      null) {
     
    
- 
    
     
    
    
                     
      this.
      _canvasContext.
      moveTo(movetopos[
      0], movetopos[
      1])
     
    
- 
    
     
    
    
                     
      this.
      _canvasContext.
      lineTo(linetopos[
      0], linetopos[
      1])
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              })
     
    
- 
    
     
    
    
             
      this.
      _canvasContext.
      stroke()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 根据粒子当前所处的位置(棋盘网格位置),计算经纬度,在根据经纬度返回屏幕坐标
     
    
- 
    
     
    
    
         
      _tomap(
      lng, lat, particle) {
     
    
- 
    
     
    
    
             
      if (!lng || !lat) {
     
    
- 
    
     
    
    
                 
      return 
      null
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      var ct3 = 
      Cesium.
      Cartesian3.
      fromDegrees(lng, lat, particle.
      height)
     
    
- 
    
     
    
    
             
      // 判断当前点是否在地球可见端
     
    
- 
    
     
    
    
             
      var isVisible = 
      new 
      Cesium.
      EllipsoidalOccluder(
      Cesium.
      Ellipsoid.
      WGS84, 
      this.
      _viewer.
      camera.
      position).
      isPointVisible(ct3)
     
    
- 
    
     
    
    
             
      var pos = 
      Cesium.
      SceneTransforms.
      wgs84ToWindowCoordinates(
      this.
      _viewer.
      scene, ct3)
     
    
- 
    
     
    
    
             
      if (!isVisible) {
     
    
- 
    
     
    
    
     
                  particle.
      age = 
      0
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      return pos ? [pos.
      x, pos.
      y] : 
      null
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _tomap1(
      lng, lat, particle) {
     
    
- 
    
     
    
    
             
      if (!lng || !lat) {
     
    
- 
    
     
    
    
                 
      return 
      null
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      var ct3 = 
      Cesium.
      Cartesian3.
      fromDegrees(lng, lat, particle.
      theight)
     
    
- 
    
     
    
    
             
      // 判断当前点是否在地球可见端
     
    
- 
    
     
    
    
             
      var isVisible = 
      new 
      Cesium.
      EllipsoidalOccluder(
      Cesium.
      Ellipsoid.
      WGS84, 
      this.
      _viewer.
      camera.
      position).
      isPointVisible(ct3)
     
    
- 
    
     
    
    
             
      var pos = 
      Cesium.
      SceneTransforms.
      wgs84ToWindowCoordinates(
      this.
      _viewer.
      scene, ct3)
     
    
- 
    
     
    
    
             
      if (!isVisible) {
     
    
- 
    
     
    
    
     
                  particle.
      age = 
      0
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      return pos ? [pos.
      x, pos.
      y] : 
      null
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 粒子是否在地图范围内
     
    
- 
    
     
    
    
         
      _isInExtent(
      lng, lat) {
     
    
- 
    
     
    
    
             
      if ((lng >= 
      this.
      _windData.
      xmin && lng <= 
      this.
      _windData.
      xmax) && (lat >= 
      this.
      _windData.
      ymin && lat <= 
      this.
      _windData.
      ymax)) 
      return 
      true
     
    
- 
    
     
    
    
             
      return 
      false
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //创建棋盘格子
     
    
- 
    
     
    
    
         
      _createWindField(
      ) {
     
    
- 
    
     
    
    
             
      var k = 
      0
     
    
- 
    
     
    
    
             
      var rows = 
      null
     
    
- 
    
     
    
    
             
      var uvw = 
      null
     
    
- 
    
     
    
    
             
      for (
      var j = 
      0; j < 
      this.
      _windData.
      rows; j++) {
     
    
- 
    
     
    
    
     
                  rows = []
     
    
- 
    
     
    
    
                 
      for (
      var i = 
      0; i < 
      this.
      _windData.
      cols; i++, k++) {
     
    
- 
    
     
    
    
     
                      uvw = 
      this.
      _calcUVW(
      this.
      _windData.
      udata[k], 
      this.
      _windData.
      vdata[k], 
      this.
      _windData.
      wdata[k])
     
    
- 
    
     
    
    
     
                      rows.
      push(uvw)
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
                 
      this.
      _grid.
      push(rows)
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      console.
      log(
      this.
      _grid)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //计算风场向量
     
    
- 
    
     
    
    
         
      _calcUVW(
      u, v, w) {
     
    
- 
    
     
    
    
             
      return [+u, +v, +w, 
      Math.
      sqrt(u * u + v * v)]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 计算经纬度步进长度
     
    
- 
    
     
    
    
         
      _calcStep(
      ) {
     
    
- 
    
     
    
    
             
      var calcSpeed = 
      this.
      _speedRate;
     
    
- 
    
     
    
    
             
      this.
      _calc_speedRate = [(
      this.
      _windData.
      xmax - 
      this.
      _windData.
      xmin) / calcSpeed, (
      this.
      _windData.
      ymax - 
      this.
      _windData.
      ymin) / calcSpeed]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      //根据风场范围随机生成粒子
     
    
- 
    
     
    
    
         
      _randomParticle(
      particle) {
     
    
- 
    
     
    
    
             
      let safe = 
      30;
     
    
- 
    
     
    
    
             
      let x = -
      1;
     
    
- 
    
     
    
    
             
      let y = -
      1;
     
    
- 
    
     
    
    
             
      let lng = 
      null;
     
    
- 
    
     
    
    
             
      let lat = 
      null;
     
    
- 
    
     
    
    
             
      do {
     
    
- 
    
     
    
    
                 
      try {
     
    
- 
    
     
    
    
     
                      lng = 
      this.
      _fRandomByfloat(
      this.
      _windData.
      xmin, 
      this.
      _windData.
      xmax)
     
    
- 
    
     
    
    
     
                      lat = 
      this.
      _fRandomByfloat(
      this.
      _windData.
      ymin, 
      this.
      _windData.
      ymax)
     
    
- 
    
     
    
    
     
                  } 
      catch (e) {
     
    
- 
    
     
    
    
                     
      // console.log(e)
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
                 
      if (lng) {
     
    
- 
    
     
    
    
                     
      //找到随机生成的粒子的经纬度在棋盘的位置 x y
     
    
- 
    
     
    
    
                     
      var gridpos = 
      this.
      _togrid(lng, lat);
     
    
- 
    
     
    
    
     
                      x = gridpos[
      0];
     
    
- 
    
     
    
    
     
                      y = gridpos[
      1];
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              } 
      while (
      this.
      _getIn(x, y)[
      2] <= 
      0 && safe++ < 
      30)
     
    
- 
    
     
    
    
             
      let uvw = 
      this.
      _getIn(x, y);
     
    
- 
    
     
    
    
             
      var nextLng = lng + 
      this.
      _calc_speedRate[
      0] * uvw[
      0]
     
    
- 
    
     
    
    
             
      var nextLat = lat + 
      this.
      _calc_speedRate[
      1] * uvw[
      1]
     
    
- 
    
     
    
    
     
              particle.
      lng = lng
     
    
- 
    
     
    
    
     
              particle.
      lat = lat
     
    
- 
    
     
    
    
             
      //计算随机点的高程
     
    
- 
    
     
    
    
     
              particle.
      height = mars3d.
      PointUtil.
      getHeight(
      this.
      _viewer.
      scene, 
      new mars3d.
      LngLatPoint(particle.
      lng, particle.
      lat, 
      0));
     
    
- 
    
     
    
    
     
              particle.
      x = x
     
    
- 
    
     
    
    
     
              particle.
      y = y
     
    
- 
    
     
    
    
     
              particle.
      tlng = nextLng
     
    
- 
    
     
    
    
     
              particle.
      tlat = nextLat
     
    
- 
    
     
    
    
     
              particle.
      speed = uvw[
      3]
     
    
- 
    
     
    
    
     
              particle.
      age = 
      Math.
      round(
      Math.
      random() * 
      this.
      _maxAge)
      // 每一次生成都不一样
     
    
- 
    
     
    
    
             
      //计算空间距离
     
    
- 
    
     
    
    
             
      let d = mars3d.
      MeasureUtil.
      getDistance([
      new mars3d.
      LngLatPoint(particle.
      lng, particle.
      lat, 
      0), 
      new mars3d.
      LngLatPoint(particle.
      tlng, particle.
      tlat, 
      0)])
     
    
- 
    
     
    
    
             
      let t = d / uvw[
      3];
     
    
- 
    
     
    
    
             
      // console.log("距离"+d)
     
    
- 
    
     
    
    
             
      // console.log("时间"+t)
     
    
- 
    
     
    
    
             
      // console.log("速度"+particle.speed)
     
    
- 
    
     
    
    
     
              particle.
      theight = particle.
      height + t * uvw[
      2];
     
    
- 
    
     
    
    
             
      // console.log("垂直风速"+uvw[2])
     
    
- 
    
     
    
    
             
      // console.log("一开始垂直高度"+particle.height)
     
    
- 
    
     
    
    
             
      // console.log("垂直高度"+particle.theight)
     
    
- 
    
     
    
    
             
      return particle;
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _getIn(
      x, y) {
     
    
- 
    
     
    
    
             
      // 局部风场使用
     
    
- 
    
     
    
    
             
      if (x < 
      0 || x >= 
      this.
      _windData.
      cols || y >= 
      this.
      _windData.
      rows || y <= 
      0) {
     
    
- 
    
     
    
    
                 
      return [
      0, 
      0, 
      0]
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      var x0 = 
      Math.
      floor(x)
      //向下取整
     
    
- 
    
     
    
    
             
      var y0 = 
      Math.
      floor(y)
     
    
- 
    
     
    
    
             
      var x1;
     
    
- 
    
     
    
    
             
      var y1
     
    
- 
    
     
    
    
             
      if (x0 === x && y0 === y) 
      return 
      this.
      _grid[y][x]
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              x1 = x0 + 
      1
     
    
- 
    
     
    
    
     
              y1 = y0 + 
      1
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      var g00 = 
      this.
      _getIn(x0, y0)
     
    
- 
    
     
    
    
             
      var g10 = 
      this.
      _getIn(x1, y0)
     
    
- 
    
     
    
    
             
      var g01 = 
      this.
      _getIn(x0, y1)
     
    
- 
    
     
    
    
             
      var g11 = 
      this.
      _getIn(x1, y1)
     
    
- 
    
     
    
    
             
      var result = 
      null
     
    
- 
    
     
    
    
             
      // console.log(x - x0, y - y0, g00, g10, g01, g11)
     
    
- 
    
     
    
    
             
      try {
     
    
- 
    
     
    
    
     
                  result = 
      this.
      _bilinearInterpolation(x - x0, y - y0, g00, g10, g01, g11)
     
    
- 
    
     
    
    
                 
      // console.log(result)
     
    
- 
    
     
    
    
     
              } 
      catch (e) {
     
    
- 
    
     
    
    
                 
      console.
      log(x, y)
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
             
      return result
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 根据现有参数重新生成风场
     
    
- 
    
     
    
    
         
      redraw(
      ) {
     
    
- 
    
     
    
    
             
      window.
      cancelAnimationFrame(
      this.
      _animateFrame)
     
    
- 
    
     
    
    
             
      this.
      _particles = [];
     
    
- 
    
     
    
    
             
      this.
      _grid = [];
     
    
- 
    
     
    
    
             
      this.
      _init()
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 二分差值算法计算给定节点的速度
     
    
- 
    
     
    
    
         
      _bilinearInterpolation(
      x, y, g00, g10, g01, g11) {
     
    
- 
    
     
    
    
             
      var rx = (
      1 - x)
     
    
- 
    
     
    
    
             
      var ry = (
      1 - y)
     
    
- 
    
     
    
    
             
      var a = rx * ry;
     
    
- 
    
     
    
    
             
      var b = x * ry;
     
    
- 
    
     
    
    
             
      var c = rx * y;
     
    
- 
    
     
    
    
             
      var d = x * y
     
    
- 
    
     
    
    
             
      var u = g00[
      0] * a + g10[
      0] * b + g01[
      0] * c + g11[
      0] * d
     
    
- 
    
     
    
    
             
      var v = g00[
      1] * a + g10[
      1] * b + g01[
      1] * c + g11[
      1] * d
     
    
- 
    
     
    
    
             
      var w = g00[
      2] * a + g10[
      2] * b + g01[
      2] * c + g11[
      2] * d
     
    
- 
    
     
    
    
             
      return 
      this.
      _calcUVW(u, v, w)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 随机数生成器(小数)
     
    
- 
    
     
    
    
         
      _fRandomByfloat(
      under, over) {
     
    
- 
    
     
    
    
             
      return under + 
      Math.
      random() * (over - under)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // 根据经纬度,算出棋盘格位置
     
    
- 
    
     
    
    
         
      _togrid(
      lng, lat) {
     
    
- 
    
     
    
    
             
      var x = (lng - 
      this.
      _windData.
      xmin) / (
      this.
      _windData.
      xmax - 
      this.
      _windData.
      xmin) * (
      this.
      _windData.
      cols - 
      1)
     
    
- 
    
     
    
    
             
      var y = (
      this.
      _windData.
      ymax - lat) / (
      this.
      _windData.
      ymax - 
      this.
      _windData.
      ymin) * (
      this.
      _windData.
      rows - 
      1)
     
    
- 
    
     
    
    
             
      return [x, y]
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      _resize(
      width, height) {
     
    
- 
    
     
    
    
             
      this.
      canvasWidth = width
     
    
- 
    
     
    
    
             
      this.
      canvasHeight = height
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      removeLines(
      ) {
     
    
- 
    
     
    
    
             
      window.
      cancelAnimationFrame(
      this.
      _animateFrame)
     
    
- 
    
     
    
    
             
      this.
      isdistory = 
      true
     
    
- 
    
     
    
    
             
      this.
      _canvas.
      width = 
      1
     
    
- 
    
     
    
    
             
      document.
      getElementById(
      'box').
      removeChild(
      this.
      _canvas)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      function 
      CanvasParticle(
      ) {
     
    
- 
    
     
    
    
         
      this.
      lng = 
      null
      // 粒子初始经度
     
    
- 
    
     
    
    
         
      this.
      lat = 
      null
      // 粒子初始纬度
     
    
- 
    
     
    
    
         
      this.
      x = 
      null
      // 粒子初始x位置(相对于棋盘网格,比如x方向有360个格,x取值就是0-360,这个是初始化时随机生成的)
     
    
- 
    
     
    
    
         
      this.
      y = 
      null
      // 粒子初始y位置(同上)
     
    
- 
    
     
    
    
         
      this.
      tlng = 
      null
      // 粒子下一步将要移动的经度,这个需要计算得来
     
    
- 
    
     
    
    
         
      this.
      tlat = 
      null
      // 粒子下一步将要移动的y纬度,这个需要计算得来
     
    
- 
    
     
    
    
         
      this.
      age = 
      null
      // 粒子生命周期计时器,每次-1
     
    
- 
    
     
    
    
         
      this.
      speed = 
      null
      // 粒子移动速度,可以根据速度渲染不同颜色
     
    
- 
    
     
    
    
     
      }
     
    
 然后页面调用

 
初始化球和数据重构后

 网上有些加了重新绘制,但是我这个数据算起来比较麻烦不是静态的都是走接口然后自己拼起来的,加了比较耗时,我就去了,也不影响。
 网上有些加了重新绘制,但是我这个数据算起来比较麻烦不是静态的都是走接口然后自己拼起来的,加了比较耗时,我就去了,也不影响。
热力场我就不放了,你把数据搞好了就很简单了,数据怎么做我上面都说了,上面方法也有,你就从里面找。核心代码就是撒完点找到对应的网格,然后利用插值算法算出uv平方和开根号的风速值作为当前点的热力数值,即可!
转载:https://blog.csdn.net/KK_bluebule/article/details/128702207
 
					