目录
- 摘要
- 1 原始数据解析
- 2 数据空间插值
- 2.1流场UVW0.dat文件转xlsx
- 2.2生成流场点数据
- 2.3生成U、V栅格数据
- 2.4裁剪U、V栅格数据
- 2.5生成零值棋盘网格
- 2.6生成U、V棋盘栅格
- 3 棋盘栅格转棋盘点
- 3.1U、V棋盘栅格矢量化
- 3.2U、V字段追加
- 3.3流场数据JSON标准解析
- 3.3.1流场数据JSON范例
- 3.3.2参数说明
- 3.3.3参数信息来源
- 4 WebGL前端三维呈现
作者:xun
摘要
空间插值常用于将离散点的测量数据转换为连续的数据曲面,以便探究空 间现象的分布模式,按照数学原理来分,分成确定性插值和地统计插值(也可以叫非确定性)。
确定性插值是以研究区域内的相似性,或者以平滑度为基础,由已知样点来创建连续的栅格表面的插值方法。其中距离加权倒数(IDW)插值是较为常见的确定性插值方法,基于样点相近相似的原理,假设每个采样点都具有一定的局部影响能力,两个样点距离越近,则它们的性质越相似,反之,距离越远则相似性越小。它通过计算与到附近区域样点的加权平均值来估算出单元格的值。
每个流场点流速由坐标位置和U、V两个法线向量构成,非均匀分布流场点可按距离加权倒数(IDW)插值的方式分别对U和V进行插值,构建流场U栅格和V栅格,通过栅格矢量化提取每一个栅格格子的中心点,得到类似棋盘网格均匀分布的流场U值和V值点数据。最后,将均匀分布的流程点数据转为json格式可用于WebGL前端三维呈现。
1 原始数据解析
流场数据分两批次提供,第一批次为“日日算”Excel数据,第二批次为标准的*.data的流场数据。本文档阐述如何对*.data格式的流场数据处理为棋盘网格均匀分布的点数据。
原始数据由“体数据”、“原数据”、“坐标转换数据”三个文件夹构成,每个文件夹分别有一份UVW0.dat文件。
“原数据”、“坐标转换数据”文件夹里的UVW0.dat文件可以用记事本等工具打开。选择“原数据”里的UVW0.dat文件作为源数据。
单个UVW0.dat文件由两部分组成:
第一部分:流场点数据:Variables= “X” “Y” “ZB” “Z” “H” “U” “V” “C”
一行记录对应一个流场的点id,主要关注 “X” “Y” “U” “V” “C”;
一共有“N”条点数据,“Zone N= 47290 E= 91824”
第二部分:Tin数据:“F=FEPOINT ET=TRIANGLE ”,一行记录对应一个tin数据,每一列对应构成tin的三个顶点id;一共有“E”条Tin数据,“Zone N= 47290 E= 91824”。
2 数据空间插值
2.1流场UVW0.dat文件转xlsx
在wps新建xlsx文件,“数据-获取数据-导入数据-直接打开数据文件”选择“原数据”里的UVW0.dat文件,选择分隔符号,完成数据转换。
由于流场数据只用到Variables= “X” “Y” “ZB” “Z” “H” “U” “V” "C"的数据,剔除第二行“Zone N= 47290 E= 91824 F=FEPOINT ET=TRIANGLE”。及第二部分:Tin数据记录。
最终的xlsx成果如下:
2.2生成流场点数据
在超图桌面端SuperMap iDesktopX中新建数据源,选择导入xlsx成果数据,选择“首行为字段信息”,“导入空间数据”,一键生成流场点数据。
2.3生成U、V栅格数据
在超图桌面端SuperMap iDesktopX中对选择“空间分析-插值分析-距离反比权重” 分别对流场点数据的U、V值进行插值,分别构建出U和V的流场栅格。
2.4裁剪U、V栅格数据
在超图桌面端SuperMap iDesktopX中导入流场的“范围面shp”数据,得到范围面数据集。
将2.3得到的U、V栅格数据、范围面数据添加到地图窗口。选择“地图-地图裁剪-选中对象区域裁剪”,裁剪后得到范围面的U、V栅格。
2.5生成零值棋盘网格
超图桌面端SuperMap iDesktopX任意选择U或者V栅格数据集,通过复制数据集的方式,得到一份“棋盘网格”栅格数据。
选择“棋盘网格”栅格数据,“数据-数据处理-代数运算”
2.6生成U、V棋盘栅格
超图桌面端SuperMap iDesktopX中“数据-数据处理-栅格镶嵌”,将2.4裁剪生成的U、V栅格数据,分别与2.5生成的零值棋盘网格数据进行镶嵌,分别得到U值棋盘栅格和V值棋盘栅格。
3 棋盘栅格转棋盘点
3.1U、V棋盘栅格矢量化
超图桌面端SuperMap iDesktopX中“空间分析-矢栅转换-栅格矢量化”,将2.6生成的U、V棋盘网格进行栅格矢量化,得到U值棋盘点和V值棋盘点 。
3.2U、V字段追加
超图桌面端SuperMap iDesktopX中,通过“数据-数据处理-追加列”功能,将V值棋盘点数据的V字段和值,追加到U值棋盘点中。
3.3流场数据JSON标准解析
3.3.1流场数据JSON范例
{“nx”:815,“ny”:704,“max”:1.6841634341693739,“extent”:[114.1492542,30.38561341,114.5745801,30.70384409],“data”:[[0,0],[0,0]…]}
3.3.2参数说明
名称 | 含义 |
---|---|
“nx” | 棋盘列 |
“ny” | 棋盘行 |
“max” | 最大流速值 |
“extent” | 四至信息,排序[W,S,E,N] |
“data” | 棋盘格点[u,v]数组 |
3.3.3参数信息来源
1.获取2.5生成零值棋盘网格的栅格信息,记录列和行信息,作为nx和ny的值。
2.获取2.3生成的U、V栅格数据的Umax、Umin和Vmax、Vmin信息,可计算得到流速的最大值
3.将3.2得到的点数据进行投影转化为4490大地坐标,记录数据集的四至信息(E、S、W、N),作为"extent"[W,S,E,N]的来源。
4 WebGL前端三维呈现
所需产品包:supermap-iclient3d-for-webgl_webgpu-11.2.0 及以上版本。下载地址:supermap-iclient3d-for-webgl_webgpu-11.2.0下载链接
对应接口:FieldLayer3D
场数据图层类
对应的参数介绍可查看该篇博客: FieldLayer3D场数据图层类接口介绍,可通过ParticleVelocityFieldEffect
可修改场数据图层粒子效果渲染效果。
流场数据需要通过fieldLayer.particleVelocityFieldEffect._setDataBounds
设置数据的范围,该范围就是流场json中extent的四至范围。
示例代码如下:
let dataBounds = SuperMap3D.Rectangle.fromDegrees(118.60696, 31.933451, 118.780261, 32.150184); // dem50plet center = SuperMap3D.Rectangle.center(dataBounds);fieldLayer.particleVelocityFieldEffect._setDataBounds(dataBounds);
流场示例代码如下:产品包路径/examples/webglparticleWaterFlow.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"><title>水场</title><link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet"><link href="./css/font-awesome.min.css" rel="stylesheet"><link href="./css/pretty.css" rel="stylesheet"><link href="./css/style.css" rel="stylesheet"><link href="./style/particleWaterFlow.css" rel="stylesheet"><script type="text/javascript" src="./js/jquery.min.js"></script><script src="./js/slider.js"></script><script src="./js/config.js"></script><script src="./js/tooltip.js"></script><script src="./js/spectrum.js"></script><script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
</head><body><div id="Container"></div><div id='loadingbar' class="spinner"><div class="spinner-container container1"><div class="circle1"></div><div class="circle2"></div><div class="circle3"></div><div class="circle4"></div></div><div class="spinner-container container2"><div class="circle1"></div><div class="circle2"></div><div class="circle3"></div><div class="circle4"></div></div><div class="spinner-container container3"><div class="circle1"></div><div class="circle2"></div><div class="circle3"></div><div class="circle4"></div></div></div><div class="legend-toolbar"><p style="font-size: 1.3em;">水流速度</p><div id="color-legend"><div class="color-legend-label"> 2 </div><br /><div class="color-legend-label"> 1.5 </div><br /><div class="color-legend-label"> 1 </div><br /><div class="color-legend-label" style="margin-top:0.5em;"> 0.5 </div><br /><div class="color-legend-label" style="margin-top:0.5em;"> 0</div></div></div><script>function onload(SuperMap3D) {let EngineType = getEngineType();const viewer = new SuperMap3D.Viewer('Container', {contextOptions: {infobox: false,skyAtmosphere: true,contextType: Number(EngineType) // Webgl2:2 ; WebGPU:3}});viewer.scenePromise.then(function (scene) {init(SuperMap3D, scene, viewer);});}function init(SuperMap3D, scene, viewer) {viewer.scene.skyBox.show = false;viewer.scene.sun.show = false;scene.globe.depthTestAgainstTerrain = false;scene.skyBox.show = false;scene.fog.enabled = false;viewer.imageryLayers.addImageryProvider(new SuperMap3D.BingMapsImageryProvider({key: URL_CONFIG.BING_MAP_KEY,//当场景出现黑球时可至官网(https://www.bingmapsportal.com/)申请keyurl: URL_CONFIG.BINGMAP}));//全球影像图层调节const imageryLayer = viewer.imageryLayers._layers[1];imageryLayer.brightness = 1.2imageryLayer.saturation = 0.6imageryLayer.contrast = 1.0let floor = 0.1;let ceil = 1.6841634341693739;let dx = (ceil - floor) / 5;const colorTable = new SuperMap3D.ColorTable();colorTable.insert(floor, new SuperMap3D.Color(255 / 255, 35 / 255, 35 / 255, 1.0));colorTable.insert(floor + dx, new SuperMap3D.Color(223 / 255, 202 / 255, 67 / 255, 1.0));colorTable.insert(floor + dx * 2, new SuperMap3D.Color(116 / 255, 205 / 255, 180 / 255, 1.0));colorTable.insert(floor + dx * 3, new SuperMap3D.Color(107 / 255, 159 / 255, 204 / 255, 1.0));colorTable.insert(floor + dx * 4, new SuperMap3D.Color(107 / 255, 143 / 255, 204 / 255, 1.0));const fieldLayer = new SuperMap3D.FieldLayer3D(scene.context); //场数据图层fieldLayer.particleVelocityFieldEffect.colorTable = colorTable;fieldLayer.particleVelocityFieldEffect.velocityScale = 0.1; //初始化效果fieldLayer.particleVelocityFieldEffect.particleSize = 4;fieldLayer.particleVelocityFieldEffect.paricleCountPerDegree = 500;let dataBounds = SuperMap3D.Rectangle.fromDegrees(118.60696, 31.933451, 118.780261, 32.150184); // dem50plet center = SuperMap3D.Rectangle.center(dataBounds);fieldLayer.particleVelocityFieldEffect._setDataBounds(dataBounds);scene.camera.setView({destination: SuperMap3D.Cartesian3.fromRadians(center.longitude, center.latitude, 10000),orientation: {heading: 6.28316380083,pitch: -1.5707876933496}});scene.primitives.add(fieldLayer); //添加场图层let particleWindField = [];let particleWindInverseField = [];//加载风场数据$.ajax({url: './data/grid-wind1.json',success: function (data) {let p = 0;for (let j = 0; j < data.ny; j++) {particleWindField[j] = [];particleWindInverseField[j] = [];for (let i = 0; i < data.nx; i++, p++) {particleWindField[j][i] = data.data[p];particleWindInverseField[j][i] = [-data.data[p][0], -data.data[p][1]];}}$('#loadingbar').remove();setTimeout(function () {fieldLayer.fieldData = particleWindField;}, 3000)}});}if (typeof SuperMap3D !== 'undefined') {window.startupCalled = true;onload(SuperMap3D);}</script>
</body></html>
效果展示
流场效果展示