安装包:下载点我
PPT素材: 下载点我
直接双击下图中nuozhadu Setup.exe即可安装

安装好了之后一定要注意使用时要连接网络!!!
介绍视频(视频都可以点右下角三个点下载):
一共四个视频 分辨是加caption和不加的 1080p和2K的
糯扎渡_caption_1080
糯扎渡_caption_2k
糯扎渡_no_caption_1080.
糯扎渡_no_caption_2k
这是单独的一个软件,以后会集成到云平台中,云平台的登录地址:
https://dam.kongqingzhao.com/#/user/guestLogin
该应用采用的技术栈为主要有Electron+WebGL+Flask
其中Electron是一个能够使用JavaScript+HTML+CSS构建跨平台桌面应用的一个开发框架:
采用Electron来构建该应用主要有几个原因:
1.JavaScript+HTML+CSS的这套技术栈原本是用于构建浏览器运行的Web前端应用,采用Electron可以使用这让这套原本运行再Web的应用作为独立的桌面端应用运行。
2.另一个不得不使用Electron技术栈是因为Web端仅能够采用缓存策略或者LocalStorage进行数据的存储,也就是说每一次获取有限元的分析结果的时候都需要请求Flask构建的Web Server(之前框架的例子就是每一次数据都需要请求Web Server),这会造成两个问题,一是每一个时间的分析数据切换的时候都会有传输的延迟因为要从web server将分析的结果传输到前端应用后再进行解析。但是cache和LocalStorage能够存储的数据非常的少(5MB),远远不足以存储大量的有限元分析结果,因此需要采用Electron的将其构建为桌面应用而不是Web应用,使其能够具备将文件自动后台下载至应用的能力以及本地文件存储的能力(读写本地文件的能力),从而快速的对从网络请求后存储在应用内部文件系统中的有限元分析结果进行读取,免去了每次都需要请求网络的时间,同时也减少了服务器带宽的传输压力。
WebGL(Web Graphics Library)是该应用的核心部分:
这是一种3D的绘图协议,这种绘图技术标准是基于OpenGL的,并增加了OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统GPU在浏览器里更流畅地展示3D场景和模型了,总之WebGL用于创建具有复杂3D结构的网站页面。
该应用场景的搭建首先是采用基于WebGL构建的Threejs进行场景地形模型的读取,场景地形模型是在City Engine种进行下载的,下载后的格式为OBJ,OBJ是一种不适用于网络传输的格式,因为OBJ的模型是未经压缩且包含大量不需要的信息的模型格式,这里采用的是Google开源的Draco进行OBJ模型压缩,提供了JavaScript encode的 API(压缩过程叫做encode),压缩后是drc格式,然后采用three.js的drcLoader进行解析和可视,再Web 3D中一直有一个重大的问题是所有的数据需要从云端加载,但是很多模型非常的大,导致传输速度过慢,使用Draco可以让Web 3D的应用程序可以显著的缩小而不影像视觉效果,这意味着用户可以快速的下载云端模型资源,更快的加载3D图形进行快速渲染。
为了进行有限元节点的三维渲染,首先每一个修建过程中的三维点的数据已经准备好了,原始节点的格式为:
1 |
x y z x_disp y_disp z_disp |
由于这样的数据包含的信息有限,不方便JavaScript进行解析,因此自定义了一种JSON的格式用于表征有限元的分析结果,我们先要对这样的数据处理为JSON格式,以key-value的形式存储这些数据,再在WebGL进行快速的读取、解析、渲染,一个处理后表示有限元分析结果的JSON数据格式为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{ "metadata": { "version": 4, "type": "BufferGeometry" }, "uuid": "AF2ADB07-FBC5-4BAE-AD60-123456789ABC", "type": "BufferGeometry", "data": { "attributes": { "position": { "itemSize": 3, "type": "Float32Array", "array": [] }, "disp_x": { "itemSize": 1, "type": "Float32Array", "array": [] }, "disp_y": { "itemSize": 1, "type": "Float32Array", "array": [] }, "disp_z": { "itemSize": 1, "type": "Float32Array", "array": [] } } } } |
其中metaData字段存放数据的描述,元数据就是一种描述数据的格式,这里我们命名这个有限元分析结果为一个缓冲区几何(BufferGeometry),这些元数据的描述对于可视化没有直接的意义,仅仅是用于描述这个JSON格式的有限元分析结果的数据。在attribute中的数据是有限元结果的存储位置,在这里进行一些声明,比如使用了itemSize来描述应该是几个数据来组成一个数据,比如一个点的位置为3个数字组成,因此itemSize为3,type描述了数据类型的申明,这里的数据类型为32位浮点数数组组成,以确保点的位置以及分析结果的数据保留足够的精度,之所以重新定义一种格式是因为原始的数据并不适用做Web的渲染与传输,定义成JSON文件可以快速直接的访问到JSON中的元素。
下面是一个完整的有限元分析数据,可以点击这个查看,https://digitaltwin.cdn.bcebos.com/result_to_cloud/res_1610296464793.json 这里这个链接中的cdn,这里采用了内容分发网络(Content delivery network)加速数据的分发,可以将这个JSON文件按下ctrl+s下载下来,下载下来后的JSON后可以复制到https://jsonformatter.curiousconcept.com/# 进行格式化,查看定义的新格式:

三维有限元数据基于WebGL的渲染
首先在上文中自定义了有限元分析结果的适合Web传输与渲染的形式,这样的数据我们可以使用两种方式进行传输或存储:
- 以electron使用Web技术开发的桌面应用进行本地存储(对应NZD施工期就是这样做的)
- 使用纯Web即时开发的Web应用,并使用CDN进行大量数据的加速传输(对应框架和悬臂梁的两个应用)
再拿到了自定义JSON格式的有限元分析结果之后可以开始进行基于WebGL(无论是基于electron还是Web的都是基于WebGL)的点的渲染,基于WebGL点的渲染的中步骤为构建、初始化、渲染三个部分组成
第一步:构建基本设置
首先需要初始化一个WebGL渲染器,并且对透视相机、轨道控制器(鼠标控制模型操作)进行创建,并且需要构建一个场景并设置光线,对应的代码部分:

上述的代码首先创建了一个WebGL渲染器,开启了抗锯齿,然后设置了背景颜色,将渲染器挂载到HTML的body中(就是挂载到了一个浏览器的元素中,并且对轨道控制器进行初始化。


其中透视相机的视场角为60度,clipping plane为1-100000米(camera的可见区域)

第二步:初始化
在初始化中,主要是将场景和UI加入到其中,上文中提到GIS数据采用的是Draco来进行的压缩(压缩后是drc格式),因此需要javascript的draco加载器进行加载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
function loadMapModel() { const manager = new THREE.LoadingManager(); manager.onStart = function (item, loaded, total) { console.log('Loading started'); }; manager.onLoad = function () { console.log('Loading complete'); }; manager.onProgress = function (item, loaded, total) { console.log(item, loaded, total); console.log('Loaded:', Math.round(loaded / total * 100, 2) + '%') $("#loading-process").css("width", ( loaded / total * 60 ) + '%') }; manager.onError = function (url) { console.log('Error loading'); }; let largeMap; var materials=new THREE.MeshLambertMaterial(); new THREE.TextureLoader(manager) // .load('../static/models/draco/large.jpg', function (texture ) { // 加载模型及纹理 // .load('https://digitaltwin.cdn.bcebos.com/cloud_cdn/campus.jpg', function (texture ) { .load('./Models/NuozhaduTerrain.jpg', function (texture ) { new THREE.DRACOLoader(manager) .setDecoderPath( '../static/three/js/libs/draco/' ) .setDecoderConfig( { type: 'js' } ) // .load('https://digitaltwin.cdn.bcebos.com/cloud_cdn/campus.drc', function (geometry) { .load('./Models/Nuozhadu_cut.drc', function (geometry) { // .load('https://bingxiong.bj.bcebos.com/out.drc', function (geometry) { materials.map=texture;//设置材质为纹理 materials.needsUpdate=true; geometry.computeVertexNormals(); const largeMap = new THREE.Mesh( geometry, materials ); // X -> 红色 Y -> 绿色 Z -> 蓝色 // 调整整个模型的到校及位置到指定位置 largeMap.rotation.y = 110 * Math.PI / 360; largeMap.translateZ(100) // 自身Z轴方向 largeMap.translateX(-150) // 自身X轴方向 largeMap.translateY(600) // 垂直方向 scene.add( largeMap ) // 这里添加进场景之后要重新render一下 render() }, function ( error ) { console.log( 'An error happened when loading the model' ); console.log(error) }) }) } |
这样我们就加载了drc压缩后的GIS模型,并移动到了需要的位置上。
由于我们需要用到有限元数据,因此我们先定义一个面板来做有限元数据的渲染,
这个采用的是dat.gui来进行UI的构建,采用了Lut.js对colormap进行计算
对于点的渲染则是先从JSON中提取出点的位置,作为一个Buffer geometry的坐标,然后将JSON中的位移提取出来,使用Lut这个计算出每个点的colormap放入buffer geometry中。接下来定义一个Point的材质,这里定义了其大小和使能顶点着色,最后使用定义的point材质和缓冲区几何体进行渲染出三维效果的点,也就是有限元的数据可视化的部分。动态加载的时候每次要释放(dispose)掉之前有限元点集的集合体再进行新的渲染,否则虽然点移除但是占用的内容不会被释放。

第三步 渲染
渲染只做了两件事,一个是渲染初始化好的scene和camera,一个是不断的进行渲染(也就是fps=30代表每秒渲染了30次,也就是说即时画面没有变化也是在不断的渲染的),
应用整体架构:

传感器的数据
传感器的数据存储我们也定义一个JSON的存储格式,这样的好处使直接从JSON中可以直接找寻到传感器的数据(时间/数据)以及对应的时间区间还有对应的分析node的位置,这样只需要一次性的读取就可以直接解析所有需要传感器相关的数据机型渲染。
