基于H5与webGL的 3d 电子围栏展示

前言

现代工业化的推进在极大加速现代化进程的同时也带来的相应的安全隐患,在传统的可视化监控领域,一般都是基于 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]);

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

?

原文地址:https://www.cnblogs.com/xhload3d/p/12297836.html

时间: 2024-08-02 19:49:00

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

基于 H5 和 webGL 的 3D 智慧城市

前言 中共中央.国务院在今年12月印发了<长江三角洲区域一体化发展规划纲要>(下文简称<纲要>),并发出通知,要求各地区各部门结合实际认真贯彻落实. <纲要>强调,要提升基础设施互联互通水平,打造数字长三角,协同建设新一代信息基础设施,共同推动重点领域智慧应用.大力发展基于物联网.大数据.人工智能的专业化服务,提升各领域融合发展.信息化协同和精细化管理水平.围绕城市公共管理.公共服务.公共安全等领域,支持有条件的城市建设基于人工智能和 5G 物联的城市大脑集群. 城市治

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

前言 许多世纪以来,风力机同水力机械一样,作为动力源替代人力.畜力,对生产力的发展发挥过重要作用.近代机电动力的广泛应用以及二十世纪50年代中东油田的发现,使风机发电机的发展缓慢下来. 70年代初期,由于“石油危机”,出现了能源紧张的问题,人们认识到常规矿物能源供应的不稳定性和有限性,于是寻求清洁的可再生能源遂成为现代世界的一个重要课题.风能作为可再生的.无污染的自然能源又重新引起了人们重视. 现在我希望可以通过这个风机 demo 使风力发电机的各个功能近距离的展示给大家,使大家能更了解风力发电

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

前言 低碳工业园区的建设与推广是我国推进工业低碳转型的重要举措,低碳工业园区能源与碳排放管控平台是低碳工业园区建设的关键环节.如何对园区内的企业的能源量进行采集.计量.碳排放核算,如何对能源消耗和碳排放进行实时动态监测等问题,涉及多个技术领域,专业性强.其数据不仅要求准确,更要求真实可靠(即可核查.可溯源).这是低碳工业园区“管控平台”建设的核心任务,也是当前我国工业园区建设中需要迫切解决的主要问题之一. http://www.hightopo.com/demo/HTBuilding/index

使用WebGL 自定义 3D 摄像头监控模型

前言 随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的同时,在监控系统中面临着严峻的现状问题:海量视频分散.孤立.视角不完整.位置不明确等问题,始终围绕着使用者.因此,如何更直观.更明确的管理摄像机和掌控视频动态,已成为提升视频应用价值的重要话题.所以当前项目正是从解决此现状问题的角度,应运而生.围绕如何提高.管理和有效利用前端设备采集的海量信息为公共安全服务,特别是在技术融合大趋势下,

基于HTML5 WebGL的工业化3D电子围栏

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

基于HTML5的WebGL呈现A星算法的3D可视化

http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.com/bgrins/javascript-astar 的javascript实现,其实作者也有个不错的2D例子实现 http://www.briangrinstead.com/files/astar/ ,只不过觉得所有A*算法的可视化实现都是平面的不够

基于 HTML5 WebGL 的 3D 网络拓扑图

在数据量很大的2D 场景下,要找到具体的模型比较困难,并且只能显示出模型的的某一部分,显示也不够直观,这种时候能快速搭建出 3D 场景就有很大需求了.但是搭建 3D 应用场景又依赖于通过 3ds Max 或 Maya 的专业 3D 设计师来建模,Unity 3D 引擎做图形渲染等,这对用户来说都是挑战!不过,HT 一站式的提供了从建模到渲染,包括和 2D 组件呈现和数据融合的一站式解决方案.HT 基于 WebGL 的 3D 技术的图形组件 ht.graph3dView 组件通过对 WebGL 底

【转】使用 WebGL 进行 3D 开发,第 1 部分: WebGL 简介

转自HTML5游戏开发者社区 使用 WebGL 进行 3D 开发,第 1 部分: WebGL 简介使用 WebGL 进行 3D 开发,第 2 部分: 使用 WebGL 库以更少的编码做更多的事情使用 WebGL 进行 3D 开发,第 3 部分: 添加用户交互 WebGL API 让 JavaScript 开发人员能够直接利用如今的 PC 及移动设备硬件中强大的内置 3D 图形加速功能.现代浏览器透明地支持 WebGL,它使人们可以为主流 Web 用户创建高性能的 3D 游戏.应用程序以及 3D

基于C/S架构的3D对战网络游戏C++框架 _03服务器端详细设计

本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): 1.实现基本通信框架,包括对游戏的需求分析.设计及开发环境和通信框架的搭建: 2.实现网络底层操作,包括创建线程池.序列化网络包等: 3.实战演练,实现类似于CS反恐精英的3D对战网络游戏: 技术要点:C++面向对象思想.网络编程.Qt界面开发.Qt控件知识.Boost智能指针.STL算法.STL.