基于 HTML5 WebGL 的加油站 3D 可视化监控

2024-08-30 11:08

本文主要是介绍基于 HTML5 WebGL 的加油站 3D 可视化监控,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

该系统中实现了对加油机,油罐的监控,以及对加油站内的摄像头进行调取并显示,本文会讲解使用 HT 来搭建该系统的步骤,以及对场景中使用到的部分关键代码进行说明。

预览地址:基于 HTML5 WebGL 的加油站 3D 可视化监控 http://www.hightopo.com/demo/gas-station-demo/

界面效果预览

视频监控效果

加油机监控效果

油罐监控效果

加油站切换效果

因为系统中对许多的加油站进行建模,所以系统中可以根据 url 地址的 stationCode 来区分不同的加油站,即 stationCode 为该加油站的唯一标识,当然该系统可以嵌入到任何第三方的系统中,HT 只需要第三方页面给一个 dom,就可以将该页面放到该 dom 中,例如上图 3d 场景,ht 可以通过 g3d.addToDOM(el) 来将 3d 场景的 dom append 到 el 这个 dom 下,g3d 为 ht 中 ht.graph3d.Graph3dView 的实例,具体可查看 3D 手册

HT 搭建系统步骤

1.制作模型

在 ht 的 3D 场景中部分简单的建模可以根据 ht 的 api 来进行搭建,例如墙面,管道,六面体,地板等等基本 3d 模型,例如如果想制作一个三维的球体模型,则可以通过以下代码:

1 var node = new ht.Node();
2 node.s({
3     "shape3d": "sphere" // 此处指定该 node style 的 shape3d 为 sphere 即球体的意思
4 });

如果需要使用代码来进行较为复杂些的建模,则可以通过指定模型的顶点信息来进行搭建,大体可理解为 3d 中的模型都是由三角面进行拼接而成的,所以指定该模型的所有三角面就可以构造出该模型,三角面又是由三个顶点信息构成,所以指定模型的顶点信息也可以构建模型,具体可以参考 建模手册

但是在我们这个加油站可视化监控系统中,我们的加油机模型以及油罐和加油站外景的模型都是十分复杂的模型,如果采用上述两种方法:

  1. 通过第一种简单的墙面,球体,六面体等模型拼接出加油站是不现实的,因为模型没有那么全面,而且贴图部分也不好分开贴,所以不可行。
  2. 通过指定顶点信息来构造加油站的所有模型,这部分虽然在理论上是可行的,但是计算顶点信息需要大量的工作,可想而知代码部分的工作量是不小的,所以不可行。

目前 ht 可以支持 obj 模型的导入,所以设计师可以根据加油站拍摄的外景图片对加油站场景以及加油机,油罐等的模型进行建模,obj 模型可以使用主流的 3dMAX 等的建模工具进行搭建,之后导入到 ht 中进行显示。对于系统中需要交互的模型则要分开进行建模,例如加油机模型不可和加油站场景的 obj 模型在同一个 obj 中,例如下图分开方式:

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": name
4 });

上面的 name 就是通过 ht.Default.setShape3dModel(name, model) 中的 name 得到的,表示此图元使用该模型来展示。

构成该监控系统的还有用来展示加油机,油罐模型的具体监控参数的面板,ht 中所有的 2d 都为矢量,所以放大不会失真,2d 面板也是通过一个个图元进行摆放展示,通过调整每个图元的样式来美化图元,具体的样式可参考 风格手册。

油罐 2d 面板展示如下:

3.对接数据

上一步中我们已经把需要展示的模型以及需要展示的监控数据进行了设计,并且在场景中进行了摆放,所以该步骤中则需要对数据进行对接,目前对接部分包括:

  1. 2d 面板两侧的数据对接
  2. 视频监控的对接

第一条的对接可以通过 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,所以主要代码即为下面一行:

1 // node 即为要飞向的节点 例如加油机
2 // 第二参数为配置参数
3 g3d.flyTo(node, { animation: true, direction: [-16, 6, 8], distance: 600 });

上述第二个参数具体可参考上述所提供的 3D 手册,direction:默认undefined,眼睛处于目标的方向(相对目标,受到目标自身旋转影响,distance :默认undefined(未定义的话则使用下面的ratio模式计算距离),浮点类型,表示眼睛跟中心的固定距离,上述所用到的两个参数解释即为此。

该函数还有一个使用方法为当第一参数传值为 null 空时,视角会调整看向场景内所有节点,所以利用此功能可能看到加油站的全景。

系统中还有一个效果是虚化背景,虚化背景的原理就是修改场景中所有模型的透明度,例如该系统中通过遍历所有节点,将当前节点的透明度设置为 0.1,则在视觉上我们看到的场景即为虚化的场景,具体节点的样式属性可以参考上面已经给出的风格手册,关键代码如下:

 1 // 遍历场景中所有图元 2 dataModel.each((d) = >{3     // opacityMap 用来记录当前某个节点没有虚化之前的透明度值4     if (!opacityMap[d.getId()]) {5         opacityMap[d.getId()] = {6             'shape3d.opacity': d.s('shape3d.opacity'),7             'shape3d.transparent': d.s('shape3d.transparent'),8             'all.opacity': d.s('all.opacity'),9             'all.transparent': d.s('all.transparent'),
10             'left.opacity': d.s('left.opacity'),
11             'left.transparent': d.s('left.transparent'),
12             'right.opacity': d.s('right.opacity'),
13             'right.transparent': d.s('right.transparent'),
14             'front.opacity': d.s('front.opacity'),
15             'front.transparent': d.s('front.transparent'),
16             'back.opacity': d.s('back.opacity'),
17             'back.transparent': d.s('back.transparent'),
18             'top.opacity': d.s('top.opacity'),
19             'top.transparent': d.s('top.transparent'),
20             'bottom.opacity': d.s('bottom.opacity'),
21             'bottom.transparent': d.s('bottom.transparent'),
22             '3d.selectable': d.s('3d.selectable')
23         };
24     }
25     // 设置当前节点的透明度 opacity 为需要虚化至多大透明度 系统中为 0.1
26     d.s({
27         'shape3d.opacity': opacity,
28         'shape3d.transparent': true,
29         'all.opacity': opacity,
30         'all.transparent': true,
31         'left.opacity': opacity,
32         'left.transparent': true,
33         'right.opacity': opacity,
34         'right.transparent': true,
35         'front.opacity': opacity,
36         'front.transparent': true,
37         'back.opacity': opacity,
38         'back.transparent': true,
39         'top.opacity': opacity,
40         'top.transparent': true,
41         'bottom.opacity': opacity,
42         'bottom.transparent': true,
43         '3d.selectable': false
44     });
45 });

上面代码执行之后场景中所有的节点就被虚化,因为每个节点虚化所需要设置的透明度属性不同,所以一共有上面十几种样式属性需要判断设置,具体的样式名称可以参考上文提出的风格手册,以下为虚化效果:

场景中有双击便利店进入便利店内景的操作,具体交互以及效果如下图:

5.优化场景

当 3d 场景中点或者面的数量较多时,3d 面板,公告板部分较多时,ht 中有几种优化策略可以进行优化,我们知道 3d 场景中的所有模型都是由三角面构成的,而三角面又是由三个顶点构成的,所以如果场景中的点或者面比较多的时候场景会出现一定的卡顿,GPU 渲染会比较费时,在 ht 中可以通过在控制台输入 g3d.showDebugTip() 来显示当前场景一共有多少面和顶点,具体效果如下:

其中 Vertices 为点的数量,Faces 为面的数量。

所以在 ht 中可以有以下 4 种直观优化策略可以优化:

  1. 减少模型的面数
  2. 使用批量处理场景中大量的相同图元
  3. 对 3d 面板使用缓存
  4. 当场景视角距离较远时隐藏部分细节图元,或者当场景视角距离某个模型很近时,隐藏看不见的图元以提高性能

第一种情况可以在设计建模时通过各种减面的手段来减少模型的面数,这一部分优化的空间是最大的,也是效果最明显的。

第二种情况可以使用批量,批量能提高性能的原理在于,当图元一个个独立绘制模型时性能较差,而但一批图元聚合成一个大模型进行一次性的绘制时, 则会极大提高WebGL刷新性能,具体可参考 批量手册。

第三种情况使用 shape3d.image.cache 这个属性来开启面板的缓存,当我们一个场景中如果需要使用大量的类似公告板的功能,我们可以利用上面的属性对该节点设置缓存,具体使用方法可以参考 3D手册。

第四种情况我们可以在眼睛距离场景很远的时候隐藏部分细节图元,类似地图缩放到很小的时候,具体的城市会隐藏掉,放大到具体模型细节时,其它看不见的图元可以相应设置隐藏,这样可以提高不少的性能。

手机端效果

 

这篇关于基于 HTML5 WebGL 的加油站 3D 可视化监控的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120644

相关文章

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

CSS3中的字体及相关属性详解

《CSS3中的字体及相关属性详解》:本文主要介绍了CSS3中的字体及相关属性,详细内容请阅读本文,希望能对你有所帮助... 字体网页字体的三个来源:用户机器上安装的字体,放心使用。保存在第三方网站上的字体,例如Typekit和Google,可以link标签链接到你的页面上。保存在你自己Web服务器上的字

html 滚动条滚动过快会留下边框线的解决方案

《html滚动条滚动过快会留下边框线的解决方案》:本文主要介绍了html滚动条滚动过快会留下边框线的解决方案,解决方法很简单,详细内容请阅读本文,希望能对你有所帮助... 滚动条滚动过快时,会留下边框线但其实大部分时候是这样的,没有多出边框线的滚动条滚动过快时留下边框线的问题通常与滚动条样式和滚动行

Python数据分析与可视化的全面指南(从数据清洗到图表呈现)

《Python数据分析与可视化的全面指南(从数据清洗到图表呈现)》Python是数据分析与可视化领域中最受欢迎的编程语言之一,凭借其丰富的库和工具,Python能够帮助我们快速处理、分析数据并生成高质... 目录一、数据采集与初步探索二、数据清洗的七种武器1. 缺失值处理策略2. 异常值检测与修正3. 数据

使用vscode搭建pywebview集成vue项目实践

《使用vscode搭建pywebview集成vue项目实践》:本文主要介绍使用vscode搭建pywebview集成vue项目实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录环境准备项目源码下载项目说明调试与生成可执行文件核心代码说明总结本节我们使用pythonpywebv

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

JVisualVM之Java性能监控与调优利器详解

《JVisualVM之Java性能监控与调优利器详解》本文将详细介绍JVisualVM的使用方法,并结合实际案例展示如何利用它进行性能调优,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录1. JVisualVM简介2. JVisualVM的安装与启动2.1 启动JVisualVM2

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3