最開始想做洪水淹沒的話,查了一些資料。又基於不同的實現的,如 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) }
效果動圖: