基于 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

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo