基于AcrGIS平台实现三维场景下的积水效果动态模拟
文章目錄
- 1.前言
- 2.環境準備
- 3.開發過程
- 3.1 軟件安裝
- 3.2 共享(發布)場景服務
- 3.3 積水區三維可視化
- 3.4 動態模擬
- 4. 完整代碼
- 5. 效果圖
- 6. 在線演示
1.前言
現有基于暴雨洪水管理模型(SWMM)生成的多個時刻的積水區數據(json格式),要求在三維場景下依照時間動態展示積水的變化效果。在此記錄開發過程中遇到的一些問題及注意事項。
2.環境準備
3.開發過程
3.1 軟件安裝
- ArcGIS Enterprise安裝及配置方法介紹(windows版)
- ArcGIS Pro許可操作手冊
ArcGIS Pro用于發布三維場景服務(包含Elevation Layer和Tile Layer),發布到Portal賬戶下。
3.2 共享(發布)場景服務
這部分需要注意在ArcGIS Pro中創建項目時是選擇Global Scene 還是Local Scene,Global Scene是個球,而Local Scene是平的,只是一塊區域。
另外一個區別是Gloal Scene支持WGS84 or WebMercator坐標系(wkid: 4326 or wkid: 3857),而Local Scene支持任何投影坐標系統。
The SceneView supports following coordinate systems in a global scene:
- WGS84 or WebMercator
- Noncached layers with any spatial reference since they will be reprojected to the scene spatial reference
In a local scene the following coordinate systems are supported:
- Any Projected Coordinate System
- Noncached layers with any spatial reference since they will be reprojected to the scene spatial reference
發布服務的詳細步驟參見: ArcGIS Pro發布三維場景服務
3.3 積水區三維可視化
積水數據通過GeoJson格式存儲,每個時刻對應一個GeoJson文件。要實現對GeoJson數據的渲染有兩種方式:
- 使用類GeoJSONLayer,要求里面的坐標數據必須是WGS84坐標系;
The GeoJSON data must comply with the RFC 7946 specification which states that the coordinates are in SpatialReference.WGS84.
- 解析GeoJson數據,獲取其坐標數據,通過要素圖層(FeatureLayer)、渲染器(Renderer)、視覺變量(VisualVariable)進行可視化。
另外還有一種方式,先解析GeoJson數據,通過其坐標數據創建graphic添加至GraphicsLayer,再進行符號化。不過這種方式下,在graphic數量較大時,頁面會出現卡頓甚至崩潰(10000時出現崩潰情況)。主要還是由于GraphicsLayer和FeatureLayer作用不太一致,前者可以承載多種類型的幾何體(Point、Polyline、Polygon等),各個graphic之間沒有統一的模式,每個graphic可以有自己的符號;而后者是有統一模式的,同樣的幾何類型,同樣的屬性字段,可以用同樣的符號渲染(一個renderer即可),因此可視化效率更高。
Each graphic must have its own symbol since the GraphicsLayer cannot have an associated renderer. Graphics may also contain different attribute schema from one another.
It is generally preferred to construct a FeatureLayer with its source property when working with client-side graphics since the FeatureLayer has more capabilities than the GraphicsLayer, including rendering, querying, and labeling.
這里采用第二種方式,部分代碼如下:
// FeatureLayer的渲染器var renderer = {type: "simple", // autocasts as new SimpleRenderer()symbol: {type: "polygon-3d", // autocasts as new PolygonSymbol3D()symbolLayers: [{type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()material: {color: "#4ec2cd"}}]},visualVariables: [ //視覺變量,elevation字段控制拉伸高度{type: "size",field: "elevation",valueUnit: "meters"}]};let features = [];var layer = new FeatureLayer({fields: [{name: "ObjectID",alias: "ObjectID",type: "oid"}, {name: "elevation",alias: "elevation",type: "double"}],objectIdField: "ObjectID",// source: features, // autocast as a Collection of new Graphic()geometryType: "polygon",spatialReference: { wkid: 3857 },renderer: renderer,outFields: ["*"]});// 先添加開始時刻的積水數據$.get('assets/data/2019-03-01-16-00.json', function (geoJson) {var featureCollections = geoJson.features;//獲取積水區域featureCollections.forEach(function (element) {let feature = {geometry: {type: "polygon", //不可省略rings: element.geometry.coordinates,spatialReference: { wkid: 3857 }, //不可省略},attributes: {ObjectID: element.id,elevation: element.properties.elevation,}};features.push(feature);}, this);layer.source = features;//設置featurelayer數據源map.add(layer);});具體可參考基于ArcGIS JS API 4.11實現對FeatureLayer的多變量渲染
3.4 動態模擬
要實現積水的動態變化效果的話,就要借助時間滑塊TimeSlider,這里的主要思路就是通過監聽時間滑塊狀態變化,去取該時刻對應的積水數據,解析GeoJson數據,創建FeatureLayer的數據源,重置數據源,刷新FeatureLayer。部分代碼如下:
// watch for time slider timeExtent changetimeSlider.watch("timeExtent", function (timeExtent) {console.log("Time extent now starts at", timeExtent.start, "and finishes at:", timeExtent.end);// 動態修改featureLayer數據源var fileName = dateUtil(timeExtent.end);$.get(`assets/data/${fileName}.json`, function (geoJson) {features = [];//清空var featureCollections = geoJson.features;featureCollections.forEach(function (element) {let feature = {geometry: {type: "polygon", //不可省略rings: element.geometry.coordinates,spatialReference: { wkid: 3857 }, //不可省略},attributes: {ObjectID: element.id,elevation: element.properties.elevation,}};features.push(feature);}, this);layer.source = features; //重置FeatureLayer數據源layer.refresh(); // 刷新FeatureLayer});});4. 完整代碼
<html><head><meta charset="utf-8" /><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /><title>三維場景下的積水效果動態模擬</title><style>html,body,#viewDiv {padding: 0;margin: 0;height: 100%;width: 100%;}#timeSlider {position: absolute;left: 200px;right: 200px;bottom: 30px;}</style><link rel="stylesheet" href="https://js.arcgis.com/4.12/esri/themes/dark/main.css" /><script src="https://js.arcgis.com/4.12/"></script><script src="assets/js/jquery-2.1.1.min.js"></script><script>require(["esri/Map","esri/layers/GeoJSONLayer","esri/layers/FeatureLayer","esri/views/SceneView","esri/views/MapView","esri/WebScene","esri/config","esri/widgets/TimeSlider",], function (Map,GeoJSONLayer,FeatureLayer,SceneView,MapView,WebScene,esriConfig,TimeSlider) {// 此處可使用ArcGIS Pro發布的場景服務(包含Ground Layer、2D Layer)// esriConfig.portalUrl = "https://myHostName.esri.com/arcgis";// var map = new WebScene({// portalItem: { // autocasts as new PortalItem()// id: "0614ea1f9dd043e9ba157b9c20d3c538" // ID of the WebScene on the on-premise portal// }// });var map = new Map({basemap: "hybrid",ground: "world-elevation" //使用ArcGIS自帶高程圖層});var view = new SceneView({container: "viewDiv",map: map,camera: {position: [117.147, // lon39.06, // lat328 // elevation in meters],tilt: 78, //傾斜角. 垂直地面為0heading: 6 //方位角,正北為0 ,0-360}});view.on("click", function (event) {console.log(view);console.log("click event: ", event.mapPoint.x + ',' + event.mapPoint.y + ',' + event.mapPoint.z);});const timeSlider = new TimeSlider({container: "timeSlider",mode: "instant",stops: {interval: {value: 10,unit: "minutes"}}});view.ui.add(timeSlider, "manual");// FeatureLayer的渲染器var renderer = {type: "simple", // autocasts as new SimpleRenderer()symbol: {type: "polygon-3d", // autocasts as new PolygonSymbol3D()symbolLayers: [{type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()material: {color: "#4ec2cd"}}]},visualVariables: [ //視覺變量,elevation字段控制拉伸高度{type: "size",field: "elevation",valueUnit: "meters"}]};let features = [];var layer = new FeatureLayer({fields: [{name: "ObjectID",alias: "ObjectID",type: "oid"}, {name: "elevation",alias: "elevation",type: "double"}],objectIdField: "ObjectID",// source: features, // autocast as a Collection of new Graphic()geometryType: "polygon",spatialReference: { wkid: 3857 },renderer: renderer,outFields: ["*"]});//根據GeoJson文件名,設置時間滑塊范圍var dateString = "2019-03-01-16-00";var dateArr = dateString.split("-");dateArr = dateArr.map(date => {return parseInt(date);});timeSlider.fullTimeExtent = {start: new Date(dateArr[0], dateArr[1] - 1, dateArr[2], dateArr[3], dateArr[4]),end: new Date(dateArr[0], dateArr[1] - 1, dateArr[2], dateArr[3], dateArr[4] + 50)};timeSlider.values = [timeSlider.fullTimeExtent.start];// 先添加開始時刻的積水數據$.get('assets/data/2019-03-01-16-00.json', function (geoJson) {var featureCollections = geoJson.features;//獲取積水區域featureCollections.forEach(function (element) {let feature = {geometry: {type: "polygon", //不可省略rings: element.geometry.coordinates,spatialReference: { wkid: 3857 }, //不可省略},attributes: {ObjectID: element.id,elevation: element.properties.elevation,}};features.push(feature);}, this);layer.source = features;//設置featurelayer數據源map.add(layer);});// watch for time slider timeExtent changetimeSlider.watch("timeExtent", function (timeExtent) {console.log("Time extent now starts at", timeExtent.start, "and finishes at:", timeExtent.end);// 動態修改featureLayer數據源var fileName = dateUtil(timeExtent.end);$.get(`assets/data/${fileName}.json`, function (geoJson) {features = [];//清空var featureCollections = geoJson.features;featureCollections.forEach(function (element) {let feature = {geometry: {type: "polygon", //不可省略rings: element.geometry.coordinates,spatialReference: { wkid: 3857 }, //不可省略},attributes: {ObjectID: element.id,elevation: element.properties.elevation,}};features.push(feature);}, this);layer.source = features; //重置FeatureLayer數據源layer.refresh(); // 刷新FeatureLayer});});});// 時間對象轉換成 YYYY-MM-DD-HH-mm 格式字符串function dateUtil(dateObject) {let year = dateObject.getFullYear();let month = dateObject.getMonth() + 1;let day = dateObject.getDate();let hour = dateObject.getHours();let minute = dateObject.getMinutes();let dateString = year + '-' + fillZero(month) + '-' + fillZero(day) + '-' + fillZero(hour) + '-' + fillZero(minute);return dateString;}// 為小于 10 的數補零function fillZero(num) {return num < 10 ? '0' + num : num;}</script> </head><body><div id="viewDiv"></div><div id="timeSlider"></div> </body></html>完整的代碼文件及依賴的json數據等下載地址:https://download.csdn.net/download/wml00000/11357207
5. 效果圖
6. 在線演示
示例地址
總結
以上是生活随笔為你收集整理的基于AcrGIS平台实现三维场景下的积水效果动态模拟的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArcGIS Pro发布三维场景服务
- 下一篇: varchar与varchar2的区别