前言现代工业化的推进大大加快了现代化进程,也带来了相应的安全隐患。在传统的视觉监控领域,一般都是基于WebSCADA技术的前端来实现2D视觉监控。本系统使用Hightopo的HTforWeb产品构建轻量级的3D视觉场景。3D场景从正面展示了现代化工厂的实景,包括工厂工人的实时位置和电子围栏的范围。、现场安全状况等,帮助我们直观了解工厂人员目前的安全状况。本文通过讲解工厂可视化场景搭建及模型加载、人物实时定位代码实现、电子围栏实现和轨迹图。以下是项目地址:基于HTML5WebGL的工业化3D电子围栏,轨迹图效果预览工厂人员实时定位效果及电子围栏效果轨迹图效果图代码实现人物模型及场景项目中使用的人物模型通过3dMax建模生成,建模工具可以导出obj和mtl文件,通过解析HT中的obj和mtl文件可以生成3d场景中的相机模型。项目中的场景是通过HT的3d编辑器搭建的。场景中有的模型是通过HT建模的,有的是通过3dMax建模的,然后导入到HT中。绘制电子围栏场景中的电子围栏并不是用3dMax搭建的模型。HT提供了多种基本形状类型供用户建模。与传统的3D建模方法不同,HT的建模核心是基于API接口,通过设置预定义的图元类型和参数接口即可构建3D模型。根据形状,我将电围栏分为圆柱体、长方体和底部多边形的棱柱体。以下是绘制电子围栏的相关伪代码:G.makeShapes=function(data,typeName,color,lastColor,g3dDm){//data是一个包含电子围栏图形信息的json对象数组letshapes=数据;for(leti=0;i{if(data.getTag()&&data.getTag().substring(0,4)===fenceName){if(data.s('所有.opacity')==='0'){data.s('all.opacity','0.3');}else{data.s('shape3d.visible',true);data.s('all.visible',true);data.s("2d.visible",true);data.s("3d.visible",true);}}});角色模型是实时定位的,因为项目使用http协议获取数据,所以使用定时器定时刷新角色数据信息。HT有个setPosition3d方法设置节点位置,就不多介绍了,但是人物节点位置的刷新也包含了人物的朝向,所以每次人物移动都需要和上次做比较比较位置并计算偏移角。相关伪代码如下://如果刷新数据的字符节点与原字符节点有相同的标签,则有位置更新if(realInfoData.tagId===tag.getTag()){//计算位置方向偏移参数letangleNumber=Math.atan2(((-p3[2])-(-tag.p3()[2])),((-p3[0])-(-tag.p3()[0])));//如果没有转到位,判断人物的位置是否在平面发生变化if(p3[0]!==tag.p3()[0]||p3[2]!==tag.p3()[2]){if(angleNumber>0){angleNumber=Math.PI-angleNumber;}else{angleNumber=-Math.PI-angleNumber;}//设置角色的方向tag.setRotation3d(0,angleNumber+Math.PI/2,0);}//设置角色标签的位置.p3(p3);}当角色触发报警时,同时有两种方式提醒系统用户。一个是角色头部面板的颜色发生变化,并显示一条警报消息。相关代码如下:switch(obj.alarmType){casenull:if(panel){//无报警面板.a('alarmContent','');panel.a('bg','rgba(6,13,36,0.80)');}休息;case'0':panel.a('alarmContent','进入围栏');panel.a('bg','rgb(212,0,0)');休息;case'1':panel.a('alarmContent','SOS');panel.a('bg','rgb(212,0,0)');休息;case'2':panel.a('alarmContent','');//离开栅栏面板.a('bg','rgba(6,13,36,0.80)');休息;case'3':panel.a('alarmContent','很久没动过');panel.a('bg','rgb(212,0,0)');break;}二是页面右侧面板会增加告警信息。相关代码如下:data.a('text',info);list.dm().add(data);TrackMapTrack实现原理报警发生后,需要追溯来龙去脉根据角色的轨迹图发出警报。如果使用每一步都根据点集绘制一个canvas足迹节点的方式重现轨迹,很容易导致绘制过多节点导致页面卡顿,所以我用了一整条pipeline来替换所有的footsofacharacterNode,使用pipeline的好处是每个人物的轨迹图从头到尾只有一个pipeline的原始信息,所以页面的渲染更加友好流畅。生成管道轨迹的代码如下://生成轨迹this.ployLines[i]=newht.Polyline();this.ployLines[i].setParent(node);this.points[i]=[];this.points[i].push({x:p3[0],y:p3[2],e:p3[1]-50});this.ployLines[i].setPoints(this.points[i]);this.ployLines[i].s({'shape.border.color':'red'});g3dDm.add(this.ployLines[i]);当角色向前移动时,一个点的坐标会被推进到管道的点集中,同时绘制新的管道截面。同理,如果角色后退一步,则当前最后一个点的坐标将从管道的点中导出,同时管道会丢失最后两个点连接的部分。此外,通过使用定时器,我分别快进和快退了轨迹图的向前和向后。下面是轨迹图的运行效果: