开篇废话:

跟之前的文章一样,开篇之前,总要写几句废话,大抵也是没啥人看仔细文字,索性我也想到啥就聊啥吧。

这次聊聊疫情,这次全国多地的疫情挺严重的,本人身处深圳,深圳这几日报导都是几十几十的新增病例,整个深圳都按下了暂停键。在此也真诚的感谢在一线辛苦抗疫的医护工作者、自愿者以及政府工作人员们。

疫情起起伏伏,着实对经济的冲击还是挺大的,大家也都切身感受到了疫情对我们的生活影响了,社会上也出现了一些质疑的声音,有质疑动态清零的,也有标榜国外放弃抗疫的。国外的国情、政治文化,我们且按下不表。

且说说我个人的观点吧,首先我也是快十年的老党员了,深知我党的宗旨:全心全意为人民服务。一切为了人民,保障人民的生命财产安全。这些年,特别是疫情这两年,也能看出我党维护宗旨的坚定与决心。

政府的任何一个决策都是经过深思熟虑,深入研究调查的,比如动态清零政策,无论从经济、政治、文化角度,我们都有充足的理由需要这样做,再从死亡率角度讲,无论死亡率有多低,发生在任何一个家庭,都是不可接受的。

加上我国人口基数大,如果放弃动态清零,病毒发生变异的可能性会增加,如果往好的方向变异也就罢了,但如果往坏的方向变异,那损失是不可计量的。

这些日子居家办公中,一时兴起,讲了些自己的观点,闲话少叙,我们进入正题

项目背景:

随着三维可视化技术越来越普及,应用的行业也是越来越多,前面的文章,我们介绍了三维园区三维机房(数据中心)三维消防模拟三维库房档案室数字孪生,等等。

鉴于可视化方案的直观可控,及时反馈,冲击力强,美观大气等特点。对于桥梁,隧道上三维可视化系统也有充分的必要性与实用性。

 一、方案设计:

针对桥梁隧道方案,初步设计以监控物联网设备为主,前置设备将数据传给中间网关,网关再将数据传给平台,平台端与三维进行数据交互

采用rest方式提供接口协议,websoket方式实时监控告警。

三维端以主动获取方式去拉去数据。对于实时性要求高的数据,比如告警、应力值等采用websoket方式保持实时性。

1.动态加载

在系统的某些场景中采用了模型动态加载技术,比如在自动巡检功能,初期方法是在点击自动巡检时加载所有设备模型到场景中,这时设备数量稍多便会造成运行卡顿,为了解决这个问题,采取即时加载即时删除的方法,设置加载阀值和移除阀值,当camera运行到接近装置设备时达到加载阀值,在这时加载此装置设备中所有的设备模型,然后装置设备打开、巡检此设备,当camera继续运行远离此装置设备,装置设备关闭后达到移除阀值,移除此装置设备中的所有设备模型,循环往复直至巡检结束。这样,既保证了巡检的功能性,也使运行更加流畅。

2.用克隆代替加载新模型

当要往场景中加载场景中有存在的模型时,用clone()方法克隆已加载模型代替加载新模型,这样能够减少内存占用率。

3.处理模型文件

 在建模时就应该注意尽量减少不必要的点边面,将能够合并的边和面进行合并操作,将相同的模型材质也进行合并,以减少模型的复杂度,导出模型后再对模型文件进行压缩。

4.模型制作技术

本系统大量采用代码模型来制作所需的设备模型,Three.js有专用的模型库,非常容易使用,在呈现复杂的几何体或场景时非常有优势。

 二、效果与代码实现:

2.1、隧道全景

按照等比例,将隧道建模,采用透明透视方式为隧道顶部建模,方便看清内部设备与结构

模型还是采用数据代码形式实现,例如添加标记模型

ModelBussiness.prototype.addMark = function (name,position,scale) {
var markjson = [{ "name": name, "objType": "picIdentification", "size": scale, "position": position, "imgurl": "../img/3dImg/qp4.png", "showSortNub": 327, "show": true, "customType1": "", "customType2": "", "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }];
}

2.2、服务机房

前置设备通过有线(稳定)方式,传输数据到服务机房的中间网关上,网关再传给本地中转平台,平台再上云台数据。

2.3、设备监控

隧道内支持多种设备类型监控,通过参数化方案,载入模型。

  DevTypes: {
"FXD": "风向袋",
"QXG": "气象仪",
"GDSXJ": "固定摄像机",
"YKSXJ": "遥控摄像机",
"ZPSXJ": "抓拍摄像机",
"WBJCY": "微波车辆检测器",
"MJSQBB": "门架式情报板",
"XBSQBB": "悬臂式情报板",
"QYKZQ": "区域控制器",
"SKBXHD": "四可变信号灯",
"CDZSD": "车道指示灯",
"XBGZ": "悬臂杆子",
"GZ1": "杆子1",
"GZ2": "杆子2",
"FJ": "风机",
"IPGB": "IP广播",
"JJDH": "紧急电话",
"KBXHD1": "单个变信号灯",
"KBXHD2": "二可变信号灯",
"KBXHD3": "三可变信号灯",
"DD": "灯带",
"HZBJQ": "火灾报警",
"QBB": "情报板",
"QBB2": "情报板2",
"XSQBB": "限速情报板",
"COVI": "covi检测器",
"QGJCQ": "光强检测器",
"FSY": "风速仪",
"JTSJJCQ": "交通事件检测器",
}

主要参数如下:

  {
show: true,
dataId:"f101",//数据id
type: "FJ",//类型 风机
name: "fj1",//唯一性
position: { x: -950, y: 55, z: -70 },//位置
scale: { x: 0.05, y: 0.05, z: 0.05 },//缩放
rotation: { x: 0, y: Math.PI/2, z: 0 }//旋转
}

设备模型支持动态调整

/*
type:类型(见TypeConfig.json文件)
name:名称(命名规则)名称+桩号 ,所有特殊符号用下划线替换
position:在三维中的位置,可通过任意添加一个位置,然后调整到合适位置,格式{x:0,y:0,z:0}
scale:模型的缩放,格式{x:1,y:1,z:1} x y z的值大于0
rotation:模型旋转,格式{x:0,y:0,z:0} x y z的值取值范围是0到Math.PI*2
show:是否显示
dataId:关联的数据id
callBack:添加成功后回调
*/
ModelBussiness.prototype.addOrUpdataModel = function (type, name, position, scale, rotation, show, dataId, callBack) {
var _this = this;
$.each(Config.DevModels, function (_index, _obj) {
if (_obj.type == type && _obj.name == name) {
_obj.position = position;
_obj.scale = scale;
_obj.rotation = rotation;
_obj.show = show;
_obj.dataid = dataid;
}
});
var obj = WT3DObj.commonFunc.findObject("dev_" + type + "_" + name);
if (obj) {
if (position) {
obj.position.x = position.x;
obj.position.y = position.y;
obj.position.z = position.z;
}
if (scale) {
obj.scale.x = scale.x;
obj.scale.y = scale.y;
obj.scale.z = scale.z;
}
if (rotation) {
obj.rotation.x = rotation.x;
obj.rotation.y = rotation.y;
obj.rotation.z = rotation.z;
}
obj.visible = show; } else {
Config.DevModels.push({
show: show,
dataId: dataId,//数据id
type: type,//类型
name: name,//唯一性
position: position,//位置
scale: scale,//缩放
rotation: rotation//旋转
});
var json = _this.createModel(type, name, position, scale, rotation, show);
WT3DObj.commonFunc.loadModelsByJsons([json], { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true, true, function () {
if (callBack) {
callBack();
}
});
} }

设备模型快速定位

/*
type:类型(见TypeConfig.json文件)
name:名称(命名规则)名称+桩号 ,所有特殊符号用下划线替换
callBack:定为完成后回调函数
*/
ModelBussiness.prototype.LocationObj = function (type, name, callBack) {
var obj = WT3DObj.commonFunc.findObject("dev_" + type + "_" + name);
if (obj) {
CloseDistance(obj, function () {
if (callBack) {
callBack();
}
});
}
return obj;
}

2.3、通用隧道

增加通用隧道模型,以用来适配不同场景下,匹配大部分隧道场景。既直观展示,又模拟场景。

同时提供通用方法,比如通用数据弹窗回调等:

//////////////////////回调方法/////////////////////////////
/*
单击回调配置
model:模型对象
dataInfo 包含了关联的业务数据 比如数据dataId
*/
function clickDevCallBack(model, dataInfo) {
var showHtml = "<div >此处显示自定义内容</div>";
layer.tips(showHtml, '#MarkMessageHelper', {
closeBtn: 1,
shade: 0.1,
shadeClose: true,
area: ["300px", "300px"],
maxWidth: 1000,
maxHeight: 350,
skin: 'louBox',
time: 0,//是否定时关闭,0表示不关闭
cancel: function (index, layero) { },
success: function () { },
tips: [1, "rgba(14, 188, 255,1)"] //还可配置颜色
});
}
/*
双击回调配置
model:模型对象
dataInfo 包含了关联的业务数据 比如数据dataId
*/
function dbClickDevCallBack(model,dataInfo) { //举例
var showHtml = "<div >此处显示自定义内容</div>";
layer.open({
type: 1,
title: model.name+"自定义弹窗案例【"+dataInfo.dataId+"】",
shade: [0.1],
area: ['500px', '500px'],
anim: 2,
content: showHtml, //iframe的url,no代表不显示滚动条
end: function () { //此处用于演示
}
});
}

 三、桥隧一体

3.1、桥梁隧道全景

此场景包含两座大桥,中间夹着一座隧道,比较经典的桥隧场景

由于场景涉及范围较广,为提升适配机器性能,在大场景下,我们采用大模,涵盖主体建筑。概况监测。

3.2、单独展示桥梁模型

双击单个主体后,进入主体细模,详细展示模型与模型上所监控的设备单体。

//双击选中
ModelBussiness.prototype.dbClickSelectCabinet = function (_obj, _face) {
if (!_obj.visible) {
return;
}
// layer.msg("【双击设备接口】设备名称" + _obj.name);
//datainfo表示配置的数据 可以根据datainfo.dataId获取与数据的关联关系
var datainfo = getInfoByModelName(_obj.name);
console.log(datainfo);
dbClickDevCallBack(_obj, datainfo);
}

 3.3、桥梁设备监管

另一座桥梁细模设备监测。

设备模型状态修改

//修改模型状态
/*
type:类型(见TypeConfig.json文件)
name:名称(命名规则)"dev_"+类型+"_"+名称+桩号 ,所有特殊符号用下划线替换
state:字符串 在线:1 离线:0 故障:-1
风向袋的状态值:1_度数 度数的取值范围0到Math.PI*2
四可变信号灯:10000 第一位表示在线 离线 故障
后面四位分别表示每个灯的亮和灭
*/
ModelBussiness.prototype.changeDevCtrlState = function (type,name, state) {
var _this = this;
var modelJson = "";
var obj = WT3DObj.commonFunc.findObject("dev_" + type + "_" + name);
if (!obj&&obj.name.indexOf("dev_")!=0) {
return;
} switch (type) {
case "XSQBB"://可变限速标志 状态:30、40、50、60、80、100、120、异常、故障 130、140、150、160、180、1100、1120 、 0 -1
state = parseInt(state);
if (state > 0) {
if (state > 100) {
obj.children[0].freshData(state);
obj.children[0].position.z = -5;
obj.children[0].matrixAutoUpdate = true;
} else {
obj.children[0].freshData(state);
obj.children[0].position.z = -30;
obj.children[0].matrixAutoUpdate = true;
}
} else {
obj.children[0].freshData("")
}
break;
case "CDZSD"://车道指示灯 正绿背头 正红背绿 正红背红 1 2 3
{
if (parseInt(state) == 1) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/go.png");
WT3DObj.commonFunc.setObjSkinImg(obj, 1, "../img/3dImg/stop.png");
} else if (parseInt(state) == 2) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/stop.png");
WT3DObj.commonFunc.setObjSkinImg(obj, 1, "../img/3dImg/go.png");
} else if (parseInt(state) == 3) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/stop.png");
WT3DObj.commonFunc.setObjSkinImg(obj, 1, "../img/3dImg/stop.png");
}
}
break;
case "KBXHD1"://单个变信号灯 红、黄、绿 黑 左 右1 2 3 4 5 6
{
if (parseInt(state) == 1) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/redlight.png");
} else if (parseInt(state) == 2) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/yellowlight.png");
} else if (parseInt(state) == 3) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/golight.png");
} else if (parseInt(state) == 4) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/nolight.png");
} else if (parseInt(state) ==5) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/left.png");
} else if (parseInt(state) ==6) {
WT3DObj.commonFunc.setObjSkinImg(obj, 0, "../img/3dImg/right.png");
}
}
break;
case "KBXHD2":
{
var stateArray = (state + "").split(""); if (stateArray[0] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/redlight.png");
} else if (stateArray[0] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[0] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/golight.png");
} else if (stateArray[0] == "4"){
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/nolight.png");
} else if (stateArray[0] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/left.png");
} else if (stateArray[0] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/right.png");
} if (stateArray[1] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/redlight.png");
} else if (stateArray[1] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[1] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/golight.png");
} else if (stateArray[1] == "4") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/nolight.png");
} else if (stateArray[1] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/left.png");
} else if (stateArray[1] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/right.png");
}
}
break;
case "KBXHD3":
{
var stateArray = (state + "").split(""); if (stateArray[0] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/redlight.png");
} else if (stateArray[0] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[0] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/golight.png");
} else if (stateArray[0] == "4"){
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/nolight.png");
} else if (stateArray[0] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/left.png");
} else if (stateArray[0] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/right.png");
} if (stateArray[1] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/redlight.png");
} else if (stateArray[1] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[1] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/golight.png");
} else if (stateArray[1] == "4"){
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/nolight.png");
} else if (stateArray[1] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/left.png");
} else if (stateArray[1] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[5], 1, "../img/3dImg/right.png");
}
if (stateArray[2] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/redlight.png");
} else if (stateArray[2] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[2] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/golight.png");
} else if (stateArray[2] == "4"){
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/nolight.png");
} else if (stateArray[2] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4],1, "../img/3dImg/left.png");
} else if (stateArray[2] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/right.png");
}
}
break; case "SKBXHD"://四可变信号灯 在线 离线 故障 4种信号灯单独显示(灭/亮) 1 0 -1 10000(后面四位表示每个信号灯状态)
{
var stateArray = (state + "").split(""); if (stateArray[0] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/redlight.png");
} else if (stateArray[0] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[0] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/golight.png");
} else if (stateArray[0] == "4") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/nolight.png");
} else if (stateArray[0] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/left.png");
} else if (stateArray[0] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[2], 1, "../img/3dImg/right.png");
} if (stateArray[1] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/redlight.png");
} else if (stateArray[1] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[1] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/golight.png");
} else if (stateArray[1] == "4") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/nolight.png");
} else if (stateArray[1] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/left.png");
} else if (stateArray[1] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[0], 1, "../img/3dImg/right.png");
}
if (stateArray[2] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/redlight.png");
} else if (stateArray[2] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[2] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/golight.png");
} else if (stateArray[2] == "4") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/nolight.png");
} else if (stateArray[2] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/left.png");
} else if (stateArray[2] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[3], 1, "../img/3dImg/right.png");
}
if (stateArray[3] == "1") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/redlight.png");
} else if (stateArray[3] == "2") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/yellowlight.png");
} else if (stateArray[3] == "3") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/golight.png");
} else if (stateArray[3] == "4") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/nolight.png");
} else if (stateArray[3] == "5") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/left.png");
} else if (stateArray[3] == "6") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[4], 1, "../img/3dImg/right.png");
}
}
break;
case "DD"://照明灯带(1亮、2正常、3暗)
{
obj.children[2].visible = true;
if ((state) == 1) {
obj.children[2].material.opacity = 0.6;
// obj.children[2]
} else if ((state) == 2) {
obj.children[2].material.opacity = 0.3;
} else if ((state) == 3) {
obj.children[2].material.opacity = 0.1;
}
}
break;
case "HZBJQ"://火灾报警 有声音、无声音)
{
if ((state) == 1) {
obj.children[1].visible = true;
} else if ((state) == 2) {
obj.children[1].visible = false;
}
}
break;
case "IPGB"://广播 (有声音 1、无声音 2)
{
if ((state) == 1) {
obj.children[0].visible = true;
} else if ((state) == 2) {
obj.children[0].visible = false;
}
}
break;
case "JJDH"://紧急电话 (有声音 1、无声音 2)
{
if ((state) == 1) {
obj.children[1].visible = true;
} else if ((state) == 2) {
obj.children[1].visible = false;
}
}
break; case "FJ"://风机 停止、正转、反转 1 2 3
{
if (obj.runInterval) {
clearInterval(obj.runInterval);
}
if ((state) == 1) {
obj.children[0].rotation.z = 0;
obj.children[1].rotation.z = 0;
obj.children[0].matrixAutoUpdate = true;
obj.children[1].matrixAutoUpdate = true;
setTimeout(function () {
obj.children[0].matrixAutoUpdate = false;
obj.children[1].matrixAutoUpdate = false;
}, 100);
} else if ((state) == 2) {
obj.children[0].matrixAutoUpdate = true;
obj.children[1].matrixAutoUpdate = true;
obj.runInterval = setInterval(function () {
obj.children[0].rotation.z += 0.5;
obj.children[1].rotation.z += 0.5;
}, 50);
} else if ((state) ==3) {
obj.children[0].matrixAutoUpdate = true;
obj.children[1].matrixAutoUpdate = true;
obj.runInterval = setInterval(function () {
obj.children[0].rotation.z -= 0.5;
obj.children[1].rotation.z -= 0.5;
}, 50);
} }
break; case "FXD"://风向袋 参照实际,三维图上示意处理 1_度数
{
var stateArray = state.split("_");
var degree = parseFloat(stateArray[1]);//y轴旋转度数
obj.rotation.y = degree;
}
break;
case "QBB"://情报板 state:文字图片地址
case "QBB2":
{
if (state!="") {
WT3DObj.commonFunc.setObjSkinImg(obj.children[1], 5, state);
}
}
break; }
}

 3.5、隧道分离展示

 3.6、隧道内设备展示

/*
//显示设备状态
type: 设备类型 见Config.DevTypes
name: 设备名称
state: 1:停用(灰色)
   2:故障(红色)
   3:正常(自身颜色)
*/
ModelBussiness.prototype.setDevState = function (type, name, state) {
var _this = this;
var obj = WT3DObj.commonFunc.findObject("dev_" + type + "_" + name);
if (obj) {
var box = new THREE.Box3();
box.setFromObject(obj);
var positionY = obj.position.y+30;
if (box&&box.max) {
positionY = box.max.y + 18;
}
var objStateMarkModelName = "dev_" + type + "_" + name + "_stateMark";
var objStateMark = WT3DObj.commonFunc.findObject(objStateMarkModelName);
if (objStateMark) {
WT3DObj.destoryObj(objStateMarkModelName);
}
if (state == 1 || state == 2) {
var mark = {
"name": objStateMarkModelName,
"objType": "picIdentification",
"size": { "x": 30, "y": 30 },
"position": { "x": obj.position.x, "y": positionY, "z": obj.position.z },
"imgurl": "../img/3dImg/" + (state == 1 ? "qp3.png" : "qp4.png"),
"showSortNub": 1
};
var temObj = WT3DObj.createObjByJson(mark);
temObj.material.depthTest = false;
temObj.visible = obj.visible;
WT3DObj.addObject(temObj);
}
WT3DObj.commonFunc.flashObjs([obj], obj.name + "_flashanimation_", 0x000000, -1, 200, 0);
if (state == 1) {
setTimeout(function () {
WT3DObj.commonFunc.flashObjs([obj], obj.name + "_flashanimation_", 0x333333, 0, 200, 0);
_this.flashObjsNames.push(obj.name);
}, 500);
} else if (state == 2) {
setTimeout(function () {
WT3DObj.commonFunc.flashObjs([obj], obj.name + "_flashanimation_", 0xff0000, 0, 200, 0);
_this.flashObjsNames.push(obj.name);
}, 500);
} else if (state==3) {
var _index = _this.flashObjsNames.indexOf(obj.name);
if (_index >= 0) {
_this.flashObjsNames.splice(_index, 1);
WT3DObj.commonFunc.flashObjs([obj], obj.name + "_flashanimation_", 0x000000, -1, 200, 0);
}
} }
}

技术交流 1203193731@qq.com

交流微信:

    

如果你有什么要交流的心得 可邮件我

其它相关文章:

如何用three.js实现数字孪生、3D工厂、3D工业园区、智慧制造、智慧工业、智慧工厂-第十课

使用webgl(three.js)创建3D机房,3D机房微模块详细介绍(升级版二)

如何用webgl(three.js)搭建一个3D库房-第一课

如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课

使用webgl(three.js)搭建一个3D建筑,3D消防模拟——第三课

使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课

如何用webgl(three.js)搭建不规则建筑模型,客流量热力图模拟

使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课(炫酷版一)

使用webgl(three.js)搭建3D智慧园区、3D大屏,3D楼宇,智慧灯杆三维展示,3D灯杆,web版3D,bim管理系统——第六课

如何用webgl(three.js)搭建处理3D园区、3D楼层、3D机房管线问题(机房升级版)-第九课(一)

如何用webgl(three.js)搭建处理3D隧道、3D桥梁、3D物联网设备、3D高速公路、三维隧道桥梁设备监控-第十一课的更多相关文章

  1. 如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室(升级版)

    很长一段时间没有写3D库房,3D密集架相关的效果文章了,刚好最近有相关项目落地,索性总结一下 与之前我写的3D库房密集架文章<如何用webgl(three.js)搭建一个3D库房,3D密集架,3 ...

  2. 如何用webgl(three.js)搭建处理3D园区、3D楼层、3D机房管线问题(机房升级版)-第九课(一)

    写在前面的话: 说点啥好呢?就讲讲前两天的小故事吧,让我确实好好反省了一下. 前两天跟朋友一次技术对话,对方问了一下Geometry与BufferGeometry的具体不同,我一下子脑袋短路,没点到重 ...

  3. 如何用webgl(three.js)搭建一个3D库房,3D仓库,3D码头,3D集装箱可视化孪生系统——第十五课

    序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...

  4. 如何用webgl(three.js)搭建一个3D库房,3D仓库3D码头,3D集装箱,车辆定位,叉车定位可视化孪生系统——第十五课

    序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...

  5. 如何用webgl(three.js)搭建不规则建筑模型,客流量热力图模拟

    本节课主要讲解如何用webgl(three.js)搭建一个建筑模型,客流量热力图模拟 使用技术说明: 这里主要用到了three.js,echart.js以及一些其它的js 与css技术,利用webso ...

  6. 如何用webgl(three.js)搭建一个3D库房-第一课

    今天我们来讨论一下如何使用当前流行的WebGL技术搭建一个库房并且实现实时有效交互 第一步.搭建一个3D库房首先你得知道库房长啥样,我们先来瞅瞅库房长啥样(这是我在网上找的一个库房图片,百度了“库房” ...

  7. 如何用webgl(three.js)搭建一个3D库房-第二课

    闲话少叙,我们接着第一课继续讲(http://www.cnblogs.com/yeyunfei/p/7899613.html),很久没有做技术分享了.很多人问第二课有没有,我也是抽空写一下第二课. 第 ...

  8. 如何用webgl(three.js)搭建一个3D库房,3D密集架,3D档案室,-第二课

    闲话少叙,我们接着第一课继续讲(http://www.cnblogs.com/yeyunfei/p/7899613.html),很久没有做技术分享了.很多人问第二课有没有,我也是抽空写一下第二课. 第 ...

  9. 使用webgl(three.js)搭建3D智慧园区、3D大屏,3D楼宇,智慧灯杆三维展示,3D灯杆,web版3D,bim管理系统——第六课

    前言: 今年是建国70周年,爱国热情异常的高涨,为自己身在如此安全.蓬勃发展的国家深感自豪. 我们公司楼下为庆祝国庆,拉了这样的标语,每个人做好一件事,就组成了我们强大的祖国. 看到这句话,深有感触, ...

随机推荐

  1. Callable接口及Futrue接口详解

    Callable接口 有两种创建线程的方法-一种是通过创建Thread类,另一种是通过使用Runnable创建线程.但是,Runnable缺少的一项功能是,当线程终止时(即run()完成时),我们无法 ...

  2. git每次操作都要输入账号密码 解决方案

    1.执行命令: git config --global credential.helper store git pull 2.输入用户名密码,以后就不会再次要求用户名密码了

  3. CSS网页使用Font Awesome图标字体时,css定义 content 属性

    原文地址: http://blog.csdn.net/laurel_y/article/details/70842157

  4. 利用系统APP实现导航---By张秀清

    苹果系统本身自带一个地图APP,但是功能并不是很强大,但是一些简单的导航功能还是能做出来的,下面贴上我的代码 // // ViewController.m // 系统APP导航 // // Creat ...

  5. mybatis的一对多(collection)

    使用图解: 低效率查询: 高效率查询: 1 查询用联合查询 2<collection 里面不写column

  6. 从 MMU 看内存管理

    在计算机早期的时候,计算机是无法将大于内存大小的应用装入内存的,因为计算机读写应用数据是直接通过总线来对内存进行直接操作的,对于写操作来说,计算机会直接将地址写入内存:对于读操作来说,计算机会直接读取 ...

  7. 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件

    jQuery简介 宗旨:Write less, do more. 内部封装了js代码 是编程更加简单并且兼容所有的主流浏览器 版本:1.x 2.x 3.x # 可以使用3.x最新版 是第三方的类库:使 ...

  8. Zookeeper应用之一:数据发布与订阅初体验

    Zookeeper到底是什么?可以从Zookeeper提供的功能来理解.本篇小作文就是使用其提供的功能之一:数据发布与订阅. 需求:服务端开启多个实例提供服务,客户端使用服务.如果服务端某个服务下线或 ...

  9. 部署Zabbix 6.0 LTS

    Blog:博客园 个人 本部署文档适用于CentOS 8.X/RHEL 8.X/Anolis OS 8.X/AlmaLinux 8.X. Zabbix 6.0 LTS于2022年2月15日发布,本次大 ...

  10. 【Java8新特性】Optional类在处理空值判断场景的应用 回避空指针异常 编写健壮的应用程序

    一.序言 空值异常是应用运行时常见的异常,传统方式为了编写健壮的应用,常常使用多层嵌套逻辑判断回避空指针异常.Java8新特性之Optional为此类问题提供了优雅的解决方式. 广大程序员朋友对空值异 ...