文章目录

  • 1.前言
  • 2.环境准备
  • 3.开发过程
    • 3.1 软件安装
    • 3.2 共享(发布)场景服务
    • 3.3 积水区三维可视化
    • 3.4 动态模拟
  • 4. 完整代码
  • 5. 效果图
  • 6. 在线演示

1.前言

现有基于暴雨洪水管理模型(SWMM)生成的多个时刻的积水区数据(json格式),要求在三维场景下依照时间动态展示积水的变化效果。在此记录开发过程中遇到的一些问题及注意事项。

2.环境准备

  1. ArcGIS Pro 2.3, ArcGIS Enterprise 10.6, ArcGIS JS API 4.12
  2. 高程数据(DEM,用于产生地形起伏效果), 影像数据(DOM,用于展示地形)

3.开发过程

3.1 软件安装

  • ArcGIS Enterprise安装及配置方法介绍(windows版)
  • ArcGIS Pro许可操作手册

ArcGIS Pro用于发布三维场景服务(包含Elevation Layer和Tile Layer),发布到Portal账户下。

3.2 共享(发布)场景服务

这部分需要注意在ArcGIS Pro中创建项目时是选择Global Scene 还是Local SceneGlobal 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时出现崩溃情况)。主要还是由于GraphicsLayerFeatureLayer作用不太一致,前者可以承载多种类型的几何体(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平台实现三维场景下的积水效果动态模拟相关推荐

  1. shader编程-三维场景下SDF建模,平滑交集、平滑并集、平滑差集(WebGL-Shader开发基础11)

    三维场景下SDF建模,平滑交集.平滑并集.平滑差集 1. demo效果 2. 实现要点 2.1 平滑运算方法定义 2.2 模型计算 3. demo代码 1. demo效果 smooth-operate ...

  2. ABAC - 基于属性的访问控制 - 复杂场景下访问控制解决之道

    引言 引言 在一个典型的软件开发场景中,你作为一名开发人员加入到某个项目后,假设是"超人组",你往往需要访问这个项目的代码库然后才能开始工作.当你的 Team Lead 将你加入 ...

  3. Dataset之图片数据增强:设计自动生成汽车车牌图片算法(cv2+PIL)根据随机指定七个字符生成逼真车牌图片数据集(自然场景下+各种噪声效果)可视化

    Dataset之图片数据增强:设计自动生成汽车车牌图片算法(cv2+PIL)根据随机指定七个字符生成逼真车牌图片数据集(自然场景下+各种噪声效果)可视化 导读 设计自动生成汽车车牌图片算法,基于cv2 ...

  4. 基于Android平台的三维实时全景地图设计与实现(二)

    2 三维全景地图系统的设计实现 2.1基于百度地图API的手机地图应用开发 在使用百度地图SDK所提供的各种LBS能力之前,需要获取百度地图移动版的开发密钥,该密钥与开发者的百度账户相关联.如图2所示 ...

  5. android绘制论文,基于Android平台的三维地形绘制研究与实现

    摘要: 地形是一种常见的三维场景,也是三维场景的重要组成部分,地形数据的实时绘制在PC端已经有大量研究,但如何实现移动端大规模地形的实时绘制是一个新问题.目前,移动端设备硬件性能发展迅速,但在移动端地 ...

  6. 超大规模商用 K8s 场景下,阿里巴巴如何动态解决容器资源的按需分配问题?

    作者 | 张晓宇(衷源) 阿里云容器平台技术专家 关注『阿里巴巴云原生』公众号,回复关键词"1010",可获取本文 PPT. **导读:**资源利用率一直是很多平台管理和研发人员关 ...

  7. 基于Unity3D平台的三维虚拟城市研究与应用

     0 引 言 随着现代城市的不断拓展延伸,城市空间多层次.立体模式管理逐渐成为城市规划管理的发展趋势[1],实现城市空间信息管理模式从二维到三维的转变,三维虚拟城市技术,已经成为人们关注和研究的热点[ ...

  8. 基于目标检测实现遥感场景下的车辆检测计数

    在很多实际场景里面,车辆的检测识别是很广泛应用到的,大多都是基于路面摄像头采集的图像完成的模型开发训练与后续的检测识别,在遥感场景中或者是无人机航拍视频数据中也是可以使用目标检测模型来完成对应目标的检 ...

  9. 基于Android实现K歌场景下超低延时耳返

    1 功能简介 在音视频应用中我们经常涉及到耳机麦克风和设备麦克风的切换.不同声道的配置.在遇到这种情况的时候,我们如何配置呢? 耳返即耳机采集监听,在设备上插入耳机(普通耳机或蓝牙耳机)后,能从本机耳 ...

最新文章

  1. labelme标注需要精确标注吗_国内需要一个数据标注平台
  2. Adreno GPU Profiler
  3. 前后台json交互,以及数据库json转换——PHPThinkphp5.1
  4. javascript有用小功能总结(未完待续)
  5. Spring DefaultListableBeanFactory
  6. P2597-[ZJOI2012]灾难【DAG支配树】
  7. Pytm:威胁建模框架
  8. html时间格式转换,时间格式转换
  9. taxi计费器c语言程序,基于单片机的出租车计费器的设计(附实物图,原理图,程序)...
  10. Unity 关于制作UV动画,模拟管路气路流向示意图
  11. 微信小程序如何实现点击链接跳转到手机自带浏览器
  12. 蚂蚁分类信息系统5.8 短信通道2 互亿无线配置使用说明
  13. 习惯养成android软件,六款有助于养成良好习惯的APP(安卓)
  14. 卓有成效的管理者——第5章 要事优先
  15. Linux 命令--SS
  16. 如何查看谷歌账户的实际消费金额和扣款金额是否一致?
  17. php 浪漫代码,技术宅用代码表白也可以很浪漫
  18. 产品经理的工作职责是什么,需要具备什么能力?
  19. 分贝(dB)的计算与理解
  20. python环境-基于go-cqhttp-简易qq聊天机器人

热门文章

  1. 谷歌chrome浏览器的源码分析(三)
  2. Python爬虫实战(3):计算大学本学期绩点
  3. 从hello server开始,到hello client结束
  4. Windows远程Linux/Ubuntu桌面
  5. 010-ThreadGroup线程组
  6. (转载)Android进阶2之Activity之间数据交流(onActivityResult的用法)
  7. 在.NET中不安装Office使用EPPlus生成带图表(Chart)的Excel报表
  8. 30个非常有吸引力的黑色网站设计作品
  9. APP-V与RemotoAPP
  10. vim 使用技巧 转载