前言

现代工业化的推进在极大加速现代化进程的同时也带来的相应的安全隐患,在传统的可视化监控领域,一般都是基于 Web SCADA 的前端技术来实现 2D 可视化监控,本系统采用 Hightopo 的 HT for Web 产品来构造轻量化的 3D 可视化场景,该 3D 场景从正面展示了一个现代化工厂的现实场景,包括工厂工人的实时位置、电子围栏的范围、现场的安全情况等等,帮助我们直观的了解当前工厂人员的安全状况。

本篇文章通过对工厂可视化场景的搭建和模型的加载,人物实时定位代码的实现、电子围栏和轨迹图的实现进行阐述,帮助我们了解如何通过使用HT实现一个简单的3D电子围栏可视化。

以下是项目地址:基于HTML5 WebGL的工业化3D电子围栏轨迹图

效果预览

工厂人员实时定位效果及电子围栏效果

轨迹图效果图

代码实现

人物模型及场景

项目中使用的人物模型是通过 3dMax 建模生成的,该建模工具可以导出 obj 与 mtl 文件,在 HT 中可以通过解析 obj 与 mtl 文件来生成 3d 场景中的摄像头模型。

项目中场景通过 HT 的 3d 编辑器进行搭建,场景中的模型有些是通过 HT 建模,有些通过 3dMax 建模,之后导入 HT 中。

绘制电子围栏

场景中的电子围栏并不是使用3dMax搭建的模型,HT提供了多种基础形体类型供用户建模使用,不同于传统的3D建模方式,HT的建模核心都是基于API的接口方式, 通过预定义的图元类型和参数接口,进行设置达到三维模型的构建。根据形状,我将电子围栏分成圆柱、长方体和底部为多边形的棱柱。

以下是我绘制电子围栏的相关伪代码:

  1 G.makeShapes = function (data, typeName, color, lastColor, g3dDm) {
2 //data是包含电子围栏图形信息的json对象数组
3 let shapes = data;
4 for (let i = 0; i < shapes.length; i++) {
5 let shape = shapes[i];
6 let type = Number(shape['type']);
7 let x = Number(shape['x']);
8 let y = Number(shape['y']);
9 let z = Number(shape['z']);
10 let width = Number(shape['width']);
11 let height = Number(shape['height']);
12 let tall = Number(shape['tall']);
13 let radius = Number(shape['radius']);
14 let vertexX = shape['vertexX'];
15 let vertexY = shape['vertexY'];
16 let nodePoints = [];
17 let p3 = [];
18 let s3 = [];
19 let centerX = 0;
20 let centerY = 0;
21 let centerZ = 0;
22 let node = new ht.Node();
23 node.setTag(typeName + i);
24 switch (type) {
25 //第一种形状:圆柱
26 case 1:
27 p3 = [-x, tall / 2, -y];
28 s3 = [radius, tall, radius];
29 //定义电子围栏样式
30 node.s({
31 "shape3d": "cylinder",
32 "shape3d.color": color,
33 "shape3d.transparent": true,
34 "shape3d.reverse.color": color,
35 "shape3d.top.color": color,
36 "shape3d.top.visible": false,
37 "shape3d.bottom.color": color,
38 "shape3d.from.color": color,
39 "shape3d.to.color": color
40 });
41 node.p3(p3); //设置三维坐标
42 node.s3(s3); //设置形状信息
43 break;
44 //第二种形状:长方体
45 case 2:
46 centerX = x - width / 2;
47 centerY = y - height / 2;
48 centerZ = z + tall / 2;
49 p3 = [-Number(centerX) - width, Number(centerZ), -Number(centerY) - height];
50 s3 = [width, tall, height];
51 node.s({
52 "all.color": color,
53 "all.reverse.color": color,
54 "top.visible": false,
55 "all.transparent": true
56 });
57 node.p3(p3);
58 node.s3(s3);
59 break;
60 //第三种形状:底部为不规则形状的等高体
61 case 3:
62 let segments = [];
63 for (let i = 0; i < vertexX.length; i++) {
64 let x = -vertexX[i];
65 let y = -vertexY[i];
66 let newPoint = { x: x, y: y };
67 nodePoints.push(newPoint);
68 //1: moveTo,占用1个点信息,代表一个新路径的起点
69 if (i === 0) {
70 segments.push(1);
71 }
72 else {
73 //2: lineTo,占用1个点信息,代表从上次最后点连接到该点
74 segments.push(2);
75 if (i === vertexX.length - 1) {
76 //5: closePath,不占用点信息,代表本次路径绘制结束,并闭合到路径的起始点
77 segments.push(5);
78 }
79 }
80 }
81 node = new ht.Shape();
82 node.setTag(typeName + i);
83 node.s({
84 'shape.background': lastColor,
85 'shape.border.width': 10,
86 'shape.border.color': lastColor,
87 'all.color': lastColor,
88 "all.transparent": true,
89 'all.opacity': 0.3,
90 });
91 p3 = [nodePoints[0]['x'], tall / 2, nodePoints[0]['y']];
92 node.p3(p3);
93 node.setTall(tall);
94 node.setThickness(5);
95 node.setPoints(nodePoints); //node设置点集位置信息
96 node.setSegments(segments); //node设置点集连接规则
97 break;
98 }
99 g3dDm.add(node);
100 }
101 }
 

考虑到电子围栏在某些情况下可能会影响到对人物位置的观察,设置了隐藏电子围栏的功能。在HT中用户可以自定义设置标签Tag作为模型唯一的标识,我将所有的电子围栏模型的标签前缀都统一并且保存在fenceName中,需要隐藏的时候则遍历所有标签名称前缀为fenceName的模型,并且根据模型种类的不同设置不同的隐藏方式。

以下是相关伪代码:

 1 g3dDm.each((data) => {
2 if (data.getTag() && data.getTag().substring(0, 4) === fenceName) {
3 if (data.s('all.opacity') === '0') {
4 data.s('all.opacity', '0.3');
5 }
6 else {
7 data.s('shape3d.visible', true);
8 data.s('all.visible', true);
9 data.s("2d.visible", true);
10 data.s("3d.visible", true);
11 }
12 }
13 });

人物模型实时定位

因为项目使用的是http协议获取数据,因此使用定时器定时刷新人物数据信息,HT有设置节点位置的setPosition3d方法,因此不做过多介绍,但是人物节点的位置的刷新还包括人物的朝向,因此每次人物移动都需要和上次位置进行比对,计算出偏移的角度。

相关伪代码如下:

 1 // 刷新数据的人物结点与原来的人物节点标签相同,则存在做位置更新
2 if (realInfoData.tagId === tag.getTag()) {
3 //计算位置朝向偏移参数
4 let angleNumber = Math.atan2(((-p3[2]) - (-tag.p3()[2])), ((-p3[0]) - (-tag.p3()[0])));
5 //如果在原地就不转向,判断人物在平面位置是否发生变化
6 if (p3[0] !== tag.p3()[0] || p3[2] !== tag.p3()[2]) {
7 if (angleNumber > 0) {
8 angleNumber = Math.PI - angleNumber;
9 } else {
10 angleNumber = -Math.PI - angleNumber;
11 }
12 //设置人物朝向
13 tag.setRotation3d(0, angleNumber + Math.PI / 2, 0);
14 }
15 //设置人物位置
16 tag.p3(p3);
17 }

人物触发警报

当人物触发警报时,有2种方式同时提醒系统使用者。一是人物头上的面板颜色发生改变,并且显示报警信息。

相关代码如下:

 1 switch(obj.alarmType){
2 case null:
3 if(panel){//无警报
4 panel.a('alarmContent','');
5 panel.a('bg','rgba(6,13,36,0.80)');
6 }
7 break;
8 case '0':
9 panel.a('alarmContent','进入围栏');
10 panel.a('bg','rgb(212,0,0)');
11 break;
12 case '1':
13 panel.a('alarmContent','SOS');
14 panel.a('bg','rgb(212,0,0)');
15 break;
16 case '2':
17 panel.a('alarmContent',''); //离开围栏
18 panel.a('bg','rgba(6,13,36,0.80)');
19 break;
20 case '3':
21 panel.a('alarmContent','长时间未动');
22 panel.a('bg','rgb(212,0,0)');
23 break;
24 }

二是页面的右侧面板会增加警报信息。

相关代码如下:

1 data.a('text', info);
2 list.dm().add(data);

轨迹图轨迹实现原理

在发生警报后,需要根据人物的轨迹图回溯发生警报的来龙去脉。如果使用根据点集每走一步就绘制一个canvas脚步节点的方式去重现轨迹,很容易造成节点绘制过多,页面卡顿的情况,因此我使用一整条管道的方式代替一个人物的所有脚步节点,使用管道的好处是,每个人物的轨迹图从开始到结束只有一个管道的图元信息,因此对页面的渲染更加友好和流畅。

生成管道轨迹的代码如下:

 1 //生成轨迹
2 this.ployLines[i] = new ht.Polyline();
3 this.ployLines[i].setParent(node);
4 this.points[i] = [];
5 this.points[i].push({ x: p3[0], y: p3[2], e: p3[1] -50 });
6 this.ployLines[i].setPoints(this.points[i]);
7 this.ployLines[i].s({
8 'shape.border.color': 'red'
9 });
10 g3dDm.add(this.ployLines[i]);

人物前进一步,则往管道的点集中推进一个点的坐标,同时绘制新的管道部分。同理,人物后退一步,则管道的点集中推出当前最后一个点的坐标,同时管道失去最后两点连接的部分。另外我通过使用定时器,对轨迹图的前进和后退分别做了快进和快退的处理。以下为轨迹图的运行效果:

基于H5与webGL的 3d 电子围栏展示的更多相关文章

  1. 基于 H5 和 webGL 的 3d 智慧城市

    前言 中共中央.国务院在今年12月印发了<长江三角洲区域一体化发展规划纲要>(下文简称<纲要>),并发出通知,要求各地区各部门结合实际认真贯彻落实. <纲要>强调, ...

  2. 基于 HTML5 的 WebGL 自定义 3D 摄像头监控模型

    前言 随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的同时,在监控系统中面临着严峻的现状问 ...

  3. 基于 H5与WebGL 的科幻风机 3D 展示

    前言 许多世纪以来,风力机同水力机械一样,作为动力源替代人力.畜力,对生产力的发展发挥过重要作用.近代机电动力的广泛应用以及二十世纪50年代中东油田的发现,使风机发电机的发展缓慢下来. 70年代初期, ...

  4. 使用H5与webGL的3D 可视化地铁展示

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  5. 基于 HTML5 + WebGL 的3D无人机 展示

    前言 近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”.但作为军事使用,无人机的各项性能要求更加严格.重要.本系统则是通过 Hightopo 的   ...

  6. 基于HTML5和WebGL的3D网络拓扑结构图

    现在,3D模型已经用于各种不同的领域.在医疗行业使用它们制作器官的精确模型:电影行业将它们用于活动的人物.物体以及现实电影:视频游戏产业将它们作为计算机与视频游戏中的资源:在科学领域将它们作为化合物的 ...

  7. 基于HTML5的WebGL经典3D虚拟机房漫游动画

    第一人称在 3D 中的用法要参考第一人称在射击游戏中的使用,第一人称射击游戏(FPS)是以第一人称视角为中心围绕枪和其他武器为基础的视频游戏类型 ; 也就是说,玩家通过主角的眼睛来体验动作.自从流派开 ...

  8. 基于 H5与webGL 的低碳工业园区监控系统

    前言 低碳工业园区的建设与推广是我国推进工业低碳转型的重要举措,低碳工业园区能源与碳排放管控平台是低碳工业园区建设的关键环节.如何对园区内的企业的能源量进行采集.计量.碳排放核算,如何对能源消耗和碳排 ...

  9. 基于 HTML5 的 WebGL 和 VR 技术的 3D 机房数据中心可视化

    前言 在 3D 机房数据中心可视化应用中,随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的 ...

随机推荐

  1. 跟我一起学QT_QT标准对话框_字体选择框

    标准对话框 QT的标准对话框分为以下几种 颜色对话框 文件对话框 字体对话框 输入对话框 消息对话框 进度对话框 错误信息对话框 向导对话框 字体选择框 字体选择框位于 QFontDialog 类中 ...

  2. 大数据学习之路-Centos6安装python3.5

    Centos 6.8安装python3.5.2 因为学习所需,需要用到python3.x的环境,目前Linux系统默认的版本都是python2.x的,还有一些自带的工具需要用到python2.6版本, ...

  3. java实现单向循环链表

    链表图解 带头结点的链表: 不带头结点的链表: 区别 带头结点的链表容易代码实现 不带头结点的容易实现循环链表和双向链表 代码的实现 (增减 删除) 节点实现: public class node { ...

  4. POJ3252 Round Numbers 题解 数位DP

    题目大意: 求区间 \([x,y]\) 范围内有多少数的二进制表示中的'0'的个数 \(\ge\) '1'的个数. 解题思路: 使用 数位DP 解决这个问题. 我们设状态 f[pos][num0][n ...

  5. 「SP25784」BUBBLESORT - Bubble Sort 解题报告

    SP25784 BUBBLESORT - Bubble Sort 题目描述 One of the simplest sorting algorithms, the Bubble Sort, can b ...

  6. 无聊读论文:视觉注意力模型RARE2012

    Riche, N., Mancas, M., Duvinage, M., Mibulumukini, M., Gosselin, B., & Dutoit, T. (2013). RARE20 ...

  7. [Windows10]记一次修复注册表相关血案:该文件没有与之关联的应用来执行该操作。请安装应用,若已经安装应用,请在“默认应用设置”页面中创建关联。

    今天闲得蛋疼清理了一下右键菜单,于是在之后某时刻使用Everything的“双击路径列打开目录”功能时发现异常: [Window Title] Everything.exe [Content] 该文件 ...

  8. 浅谈Java三大特性之封装

    目录 前言 好处 介绍(实现方式) 示例 小结 感谢阅读!!! 三大特性之浅谈封装 前言 英语:Encapsulation--封装,包装. 面向对象的封装与真实世界的目的是一样的.封装能够使外部访问者 ...

  9. Java HashSet集合的子类LinkedHashSet集合

    说明 HashSet保证元素的唯一性,可是元素存放进去是没有顺序的. 在HashSet下面有一个子类java.util.LinkedHashSet,它是 链表 + 哈希表(数组+链表 或者 数组+红黑 ...

  10. Java BIO NIO 与 AIO

    回顾 上一章我们介绍了操作系统层面的 IO 模型. 阻塞 IO 模型. 非阻塞 IO 模型. IO 复用模型. 信号驱动 IO 模型(用的不多,知道个概念就行). 异步 IO 模型. 并且介绍了 IO ...