HTML5+WebGL 的加油站 3D 可视化监控
2019-11-02 16:59
前言
随着数字化,工业互联网,物联网的发展,我国加油站正向有人值守,无人操作,远程控制的方向发展,传统的人工巡查方式逐渐转变为以自动化控制为主的在线监控方式,即采用数据采集与监控系统 SCADA。SCADA 系统的推广使用,大大提高了我国加油站的监控效率,本文所讲的则是通过对加油站的可视化建模,结合 HT 的 3D 可视化以及 2D 监控面板来实现对加油站的可视化监控。三维可视化监控系统是将三维的可视化技术和数据采集与监控技术融合,充分发挥了两种技术的核心优势,并通过数据库进行数据共享,共同构成一种全新的 SCADA 系统。该系统中也结合了海康的摄像头监控,通过调用海康提供的摄像头地址,实时的将视频流传输到前台,并且展示在 2d 页面上。在真实的系统中,每个加油机以及加油罐都有自己对应需要展示的数据,这个可以根据自己需要展示的内容来设计 2d 面板,之后根据后台传来的数据进行展示。数据采集与监控系统通过各类的传感器实时采集监控对象的各类数据,上传数据库并实时共享给三维可视化技术搭建的监控对象的三维可视化模型及场景,最后通过监控系统直观的展示出来,极大的提高了监控对象数据的表达能力和工作人员的工作效率。
该系统中实现了对加油机,油罐的监控,以及对加油站内的摄像头进行调取并显示,本文会讲解使用 HT 来搭建该系统的步骤,以及对场景中使用到的部分关键代码进行说明。
预览地址:
加油机监控效果

油罐监控效果

加油站切换效果

因为系统中对许多的加油站进行建模,所以系统中可以根据 url 地址的 stationCode 来区分不同的加油站,即 stationCode 为该加油站的唯一标识,当然该系统可以嵌入到任何第三方的系统中,HT 只需要第三方页面给一个 dom,就可以将该页面放到该 dom 中,例如上图 3d 场景,ht 可以通过 g3d.addToDOM(el) 来将 3d 场景的 dom append 到 el 这个 dom 下,g3d 为 ht 中 ht.graph3d.Graph3dView 的实例,具体可查看
1 var node = new ht.Node();2 node.s({3 "shape3d": "sphere" // 此处指定该 node style 的 shape3d 为 sphere 即球体的意思4 });
如果需要使用代码来进行较为复杂些的建模,则可以通过指定模型的顶点信息来进行搭建,大体可理解为 3d 中的模型都是由三角面进行拼接而成的,所以指定该模型的所有三角面就可以构造出该模型,三角面又是由三个顶点信息构成,所以指定模型的顶点信息也可以构建模型,具体可以参考
2.搭建场景
上一步中我们已经得到了场景所需要的所有模型,在 ht 中可以通过 ht.Default.loadObj(objUrl, mtlUrl, params) 来加载 obj 的模型,之后通过 ht.Default.setShape3dModel(name, model) 来注册模型,loadObj 用来读取模型的顶点信息以及贴图部分的信息,就是上一步中所指的第二点通过顶点信息来构造模型,此时顶点信息已经由 obj 模型提供,所以拿到顶点信息,贴图等信息之后,可以通过 setShape3dModel 来注册模型,具体使用方法请参考 OBJ 手册,之后可以通过 ht 的 node 图元来使用该模型,具体使用方法如下:
1 var node = new ht.Node();2 node.s({3 "shape3d": name4 });
上面的 name 就是通过 ht.Default.setShape3dModel(name, model) 中的 name 得到的,表示此图元使用该模型来展示。
构成该监控系统的还有用来展示加油机,油罐模型的具体监控参数的面板,ht 中所有的 2d 都为矢量,所以放大不会失真,2d 面板也是通过一个个图元进行摆放展示,通过调整每个图元的样式来美化图元,具体的样式可参考
3.对接数据
上一步中我们已经把需要展示的模型以及需要展示的监控数据进行了设计,并且在场景中进行了摆放,所以该步骤中则需要对数据进行对接,目前对接部分包括:
- 2d 面板两侧的数据对接
- 视频监控的对接
第一条的对接可以通过 socket 或者 ajax 来进行,将后台数据传输到前台之后动态绑定到界面上显示即可,ht 中通过数据绑定来驱动界面上内容的动态刷新,具体的绑定操作可以查看 数据绑定手册。
系统中摄像头监控部分主要是通过将第三方的视频 dom 嵌入到 ht 的图纸中,ht 中可以通过 renderHTML 来嵌入 dom,嵌入 dom 的原理其实也是在图纸的对应位置加入一个 node 图元,根据图纸的缩放值(zoom),以及横向偏移值(tx),纵向偏移值(ty) 的图纸信息以及该图元的 position, width, height 的图元信息来动态的计算 dom 的宽高和 dom 的位置,具体代码可以参考如下:
1 let rect = node.getRect(), // 获取该 node 的包围矩形信息 2 zoom = graphView.getZoom(), // 获取图纸的缩放值 3 tx = graphView.tx(), // 获取图纸的横向偏移值 4 ty = graphView.ty(); // 获取图纸的纵向偏移值 5 // 下面操作为对 node 的包围矩形进行缩放 6 rect.x *= zoom; 7 rect.y *= zoom; 8 rect.width *= zoom; 9 rect.height *= zoom;10 11 // div 的 left 即为下面的 x 坐标, top 即为下面的 y 坐标12 let x = tx + rect.x;13 let y = ty + rect.y;14 15 div.style.position = 'absolute';16 div.style.width = rect.width + 'px';17 div.style.height = rect.height + 'px';18 div.style.left = x + 'px';19 div.style.top = y + 'px';
上面代码展示了动态摆放 dom 到 ht 图纸的原理,所以用户可以根据自己的需求将 dom 元素放到 2d 图纸中去,该系统中的监控模块 dom 就是通过该方式的原理进行动态摆放,从下图可以看出 dom 叠加的效果。

4.制作动画效果
该系统中动画效果比较简单,主要就是点击加油机或者油罐时,将视角飞向该物体,并且二维面板上显示对应的监控数据,视角的切换主要是修改 3D 场景的 eye 以及 center 的数据,但是 ht 中提供了更为方便的操作函数 flyTo,所以主要代码即为下面一行: