Cesium中绘制台风圈的动画

812 阅读3分钟

需求背景: 模拟台风运动情况,包含绘制台风路径,预测线,台风风圈,台风警戒线等。

效果图

1280X1280.PNG

台风的绘制分为两部分,静态图形的绘制与动态图形的绘制。其中静态图形是,台风的主线,台风的预测线与预警线。这部分用polyline做绘制。图形的动画,主要是风圈与风圈点,用availability去实现动画。

绘制台风圈

接口数据:radius7: "200|180|180|150"(台风圈四个方向上的半径,按照顺时针方向旋转。)

  /**
   * 计算风圈
   * @param lng
   * @param lat
   * @param radius
   * @param start
   * @param end
   * @returns
   */
  private computeCirclularFlight(lng: string, lat: string, radius: string, start: number, end: number) {
    let Ea = 6378137 // 赤道半径
    let Eb = 6356725 // 极半径
    let positionArr = []
    for (let i = start; i <= end; i = i + 2) {
      let dx = Number(radius) * Math.sin((i * Math.PI) / 180.0)
      let dy = Number(radius) * Math.cos((i * Math.PI) / 180.0)

      let ec = Eb + ((Ea - Eb) * (90.0 - Number(lat))) / 90.0
      let ed = ec * Math.cos((Number(lat) * Math.PI) / 180)

      let BJD = Number(lng) + ((dx / ed) * 180.0) / Math.PI
      let BWD = Number(lat) + ((dy / ec) * 180.0) / Math.PI

      positionArr.push(BJD)
      positionArr.push(BWD)
    }

    return positionArr
  }
  
  /**
   * 获取台风风圈,返回的是风圈点集数组
   * @param {object} circle
   */
  private getWindCircle(circle: { lng: any; lat: any; radius: any; direct: any }) {
    // 90°的扇形,四分之一圆,顺时针
    let start = 0
    let end = 90
    switch (circle.direct) {
      case 'EN':
        start = 0
        end = 90
        break
      case 'ES':
        start = 90
        end = 180
        break
      case 'WS':
        start = 180
        end = 270
        break
      case 'WN':
        start = 270
        end = 360
        break
    }

    let pointArr = []
    pointArr = this.computeCirclularFlight(circle.lng, circle.lat, circle.radius, start, end)
    return pointArr
  }

bf5a8e45-6965-4a25-9607-0cc6a7b2d325.png

在二维的平面里,已知半径与夹角求对边与邻边。得到点坐标。

1351a2cd-0085-42f3-9372-20387cedca2c.png

Ea 表示赤道半径,Eb表示极半径,地球是一个近似球体,Ea与Eb稍微有点差距。ec的作用就是修正因为纬度不断变化的球半径长度。如果在GLAT=0,即在赤道上的时候,ec=Eb+(Ea-Eb)(90-0)/90=Ea,那ec就刚好是赤道半径Ea;如果在极点GLAT=90,ec=Eb+(Ea-Eb)(90-90)/90=Eb,那ec 就刚好是极半径Eb。

b1967fd0-6bb1-485a-ad85-2913af666cd9.png

参看上图,那dx / ed 就相当于是在GLAT这个纬度上dx长度与总长度的占比,算出来应该是个经度跨度。如果这个经度跨度加上起始给定的经度就是最终的经度。

同理 dy/R就是在GLON这个经度上的dy长度与地球平均半径R的占比,算出来应该是一个纬度跨度。如果这个纬度跨度加上起始给定的纬度就是最终的纬度。这里使用了R,取地球平均半径。

dy/ec 就是用不断修正的ec半径替代了平均半径R。

(dy / ec + GLAT * Math.PI / 180.0) 就是起始纬度加上distance距离的最终纬度,同时需要将该结果转换为角度。 转换角度方法是:弧度* 180.0 / Math.PI。

BWD = (dy / ec + GLAT * Math.PI / 180.0) * 180.0 / Math.PI;

(dx / ed + GLON * Math.PI / 180.0)就是起始经度加上distance距离的最终经度,同时需要将该结果转换为角度。

BJD = (dx / ed + GLON * Math.PI / 180.0) * 180.0 / Math.PI;

参考资料

stackoverflow.com

根据2个经纬度点,计算这2个经纬度点之间的距离(通过经度纬度得到距离) - softfair - 博客园