Cesium-03:洪水淹沒

2022-11-25 15:00:21

Cesium-01:Vue 中基礎使用

Cesium-02:飛機模型簡單對等飛行

Cesium-03:洪水淹沒

前言

最開始想做洪水淹沒的話,查了一些資料。又基於不同的實現的,如 ArcScene 實現,有基於 Cesium 實現。

對比分析了下,ArcGIS 下的實現主要是軟體中,如果想自己程式碼實現的話,還要藉助 Arc Engine。加上自己前面也使用過 Cesium ,這裡就選擇了 Cesium 去做。

這裡特別說明下,所做的洪水淹沒,是簡單的水面的擡升,沒有降水、水流等演演算法分析在裡面(瞭解過一些演演算法,要對接的話還有很多工作要做)。

一、資料準備

準備資料

  1、底圖衛星資料,這裡選用天地圖衛星切片;

  2、DEM 資料,直接下載的哨兵資料(資料下載地址 ASF Data Search (alaska.edu),可以參考這裡

  3、DEM 切片,並行布服務

 

處理過程中注意點

  1、哨兵資料下載網站,需要註冊;

  2、沒有選擇自己下載衛星資料,是因為解析度、處理等問題,不如直接使用線上的天地圖衛星;

  3、DEM 切片使用的是 CesiumLab,但釋出的 DEM 服務,可以使用 CesiumLab 也可以自己釋出

如果自己釋出 DEM 服務的話,在 DEM 切片時,選擇「雜湊」,如下圖:

 

Nginx 釋出 DEM 切片,和一般的 Web 站點的設定一樣,如下:

server {
    listen 9001;
    root ./www/hzDEMcache;
    # Add index.php to the list if you are using PHP
    index index.html index.htm;
    server_name _;
    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        add_header Access-Control-Allow-Origin *;    # 跨域設定
    }
    add_header Cache-Control "no-cache,must-revalidate";    # 跨域設定
}

在設定完成後,瀏覽器中開啟  http://localhost:9001/layer.json,沒有問題的話,證明發布成功!

資料都完成後,可以進行開發啦!

二、效果實現

下面兩個問題時間:21年11月時沒有問題,22年11月出現下面兩個問題。

1、Cesium 版本問題

  前幾篇文章中,使用的 Cesium 是1.89版本。這個專案在初始化時,直接安裝 Cesium 包,安裝的是 1.99 版本。啟動後專案報錯,".?" 運運算元不能識別。

  經過分析,新版的 Cesium 對 TS 的支援更好,其中一些使用到了 TS 的新語法。這個對於使用 Vue3 + TS 會更友好。

  因當前使用的還是 Vue2 ,切沒有 TS,所以版本回退到了 1.89 ,再次執行正常!

2、token

  在使用 Cesium 自帶的底圖、高程時,直接報錯,沒有顯示。看了官網的檔案,發現現在需要 token。

  所以要先在官網註冊,並申請 token。在使用地圖前賦值 token:

Cesium.Ion.defaultAccessToken = 'token'

 

實現

底圖程式碼:

    this.cesiumViewer = new Cesium.Viewer('cesiumContainer', {
      infoBox: false,
      // terrainProvider: Cesium.createWorldTerrain(), // Cesium 自帶地形資料
      // terrainProvider: new Cesium.CesiumTerrainProvider({ url: 'http://localhost:9003/terrain/LktyW4LU' }), // cesiumLab 切的地形資料服務
      terrainProvider: new Cesium.CesiumTerrainProvider({ url: 'http://localhost:9001/' }), // nginx 代理切片,最後要帶上"/"
      baseLayerPicker: true, // 圖層選擇器
      // 不設定,預設使用自帶底圖,需要 token
      imageryProvider: new Cesium.UrlTemplateImageryProvider({
        // url 和 openlayer 使用區別,t{0-7}.tianditu  ,這裡需要指定數值
        url: 'http://t1.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=07d4e04324b413cb0582fa99fe833cd3'
      })
    })

洪水淹沒程式碼:這裡使用的是  Cesium.CallbackProperty,直接修改 extrudedHeight 會出現閃爍的情況

    drawWater() {
      this.showWater = true
      this.waterEntity && this.cesiumViewer.entities.remove(this.waterEntity)
      const waterCoord = [119.642769, 30.361905, 100, 119.591604, 30.448757, 100, 119.695767, 30.488232, 100, 119.748406, 30.395983, 100]

      let startHeight = 100
      const targetHeight = 500
      this.waterEntity = this.cesiumViewer.entities.add({
        polygon: {
          hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights(waterCoord),
          material: Cesium.Color.fromBytes(64, 157, 253, 200),
          perPositionHeight: true,
          extrudedHeight: new Cesium.CallbackProperty(() => { return startHeight }, false)
        }
      })
      const waterInterval = setInterval(() => {
        if (startHeight < targetHeight) {
          startHeight += 10
          if (startHeight >= targetHeight) {
            startHeight = targetHeight
            clearInterval(waterInterval)
            this.showWater = false
          }
          // 使用該方式會閃爍,改用 Cesium.CallbackProperty 平滑
          // this.waterEntity.polygon.extrudedHeight.setValue(startHeight)
        }
      }, 100)
    }

效果動圖: