基于WebGL架构的3D可视化平台—三维设备管理(ThingJS实现楼宇设备管理3D可视化)

简介: 国内高层建筑不断兴建,它的特点是高度高、层数多、体量大。面积可达几万平方米到几十万平方米。这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑设备也是大量的。为了提高设备利用率,合理地使用能源,加强对建筑设备状态的监视等,自然地就提出了楼宇自动化控制系统。

国内高层建筑不断兴建,它的特点是高度高、层数多、体量大。面积可达几万平方米到几十万平方米。这些建筑都是一个个庞然大物,高高的耸立在地面上,这是它的外观,而随之带来的内部的建筑设备也是大量的。为了提高设备利用率,合理地使用能源,加强对建筑设备状态的监视等,自然地就提出了楼宇自动化控制系统。下面我们将用ThingJS平台来模拟一个设备管理系统。

第一步,利用CampusBuilder搭建模拟场景。CampusBuilder的模型库有各种各样的模型,使我们搭建出的场景更逼真。使用CampusBuilde创建层级,之后再给层级加外立面就出现了当前的效果。详情移步:CampusBuilder3D场景制作工具

先看结果:演示地址

第二步,创建Equipment类,这里创建。switchControl方法主要一个完成一个计时器的功能来模拟设备警报。

class Equipment extends THING.Thing {
    constructor(app, name, obj, url) {
        super(app);
        this.name = name;
        this.obj = obj;
        this.url = url;
        this.interval = null;
        this.localPosition = [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)];
    }
    createSelf() {
        app.create({
            type: 'Equipment',
            name: this.name,
            url: this.url,
            parent: this.obj,
            localPosition: this.localPosition,
            angle: 0
        });
    }
    switchControl(ev) {
        var flag;
        var equipment = app.query(this.name)[0];
        app.level.change(equipment);
        if (ev) {
            this.interval = setInterval(function () {
                if (flag) {
                    equipment.style.color = '#FF0000';
                    flag = false;
                } else {
                    flag = true;
                    equipment.style.color = '';
                }
            }, 500);
            console.log(this.interval + "查看是否创建了定时器");
        } else {
            console.log(this.interval);
            clearInterval(this.interval);
            if (equipment.style.color == '#FF0000')
                equipment.style.color = '';
        }
    }
}
THING.factory.registerClass('Equipment', Equipment);

  第三步,创建摄像机面板,烟感报警面板以及控制设备的开关,这里简单调整一下面板位置之后会增加两个创建设备的按钮。

//创建主面板
var panel1 = new THING.widget.Panel({
    titleText: '摄像机列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel1.position = [80, 0];

var panel2 = new THING.widget.Panel({
    titleText: '烟感报警列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel2.position = [80, 320];

// 创建任意对象
var dataObj1 = {
    open1: false,
    open2: false,
    open3: false,
    open4: false,
}
var dataObj2 = {
    open5: false,
    open6: false,
    open7: false,
    open8: false,
};

// 动态绑定物体
var open1 = panel1.addBoolean(dataObj1, 'open1').caption('设备01');
var open2 = panel1.addBoolean(dataObj1, 'open2').caption('设备02');
var open3 = panel1.addBoolean(dataObj1, 'open3').caption('设备03');
var open4 = panel1.addBoolean(dataObj1, 'open4').caption('设备04');
var open5 = panel2.addBoolean(dataObj2, 'open5').caption('设备01');
var open6 = panel2.addBoolean(dataObj2, 'open6').caption('设备02');
var open7 = panel2.addBoolean(dataObj2, 'open7').caption('设备03');
var open8 = panel2.addBoolean(dataObj2, 'open8').caption('设备04');

  第四步,开启场景层级切换,创建摄像机和烟感报警器各四个,创建一个数字标识index和保存equipment对象的数组equipmentGroup。

//创建equipment对象数组,以及数组标识
var equipmentGroup = [];
var index = 0;

app.on('load', function (ev) {

    app.level.change(ev.campus);

    for (var i = 0; i < 8; i++) {
        var type = null;
        if (i < 4) {
            type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/';
        } else {
            type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
        }
        var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type);
        equipment.createSelf();
        equipmentGroup.push(equipment);
    }
});

  第五步,为每个设备对应的创建控制开关。

open1.on('change', function (ev) {
        equipmentGroup[0].switchControl(ev);
    });
    open2.on('change', function (ev) {
        equipmentGroup[1].switchControl(ev);
    });
    open3.on('change', function (ev) {
        equipmentGroup[2].switchControl(ev);
    });
    open4.on('change', function (ev) {
        equipmentGroup[3].switchControl(ev);
    });
    open5.on('change', function (ev) {
        equipmentGroup[4].switchControl(ev);
    });
    open6.on('change', function (ev) {
        equipmentGroup[5].switchControl(ev);
    });
    open7.on('change', function (ev) {
        equipmentGroup[6].switchControl(ev);
    });
    open8.on('change', function (ev) {
        equipmentGroup[7].switchControl(ev);
    });

  最后一步,创建两个按钮来控制创建设备。

new THING.widget.Button('创建烟感报警', function () {
    var type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
    var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

new THING.widget.Button('创建摄像头', function () {
    var type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/';
    var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

  

在编写过程还是走了不少弯路的,最主要的就是计时器的卸载问题,最初的版本写来写去发现不能控制警报的关闭,后来才 发现计时器没有卸载,警报不但不会关闭而且闪动的频率越来越快。更改之后创建了Equipment这个类来控制所有设备,通过创建这个类的对象给他赋id,父物体,模型地址。这里控制器在开关被触发的时候创建一个新的计时器并赋给的这个对象,再次触发时清除这个计时器,警报的动画就关闭了。演示地址

最后附上完整代码:

/**
 * 说明:创建App,url为场景地址(可选)
 */
var app = new THING.App({
    url: "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/CampusBuilder20181126134710",    // 场景地址
    "skyBox": "BlueSky"
});

//创建主面板
var panel1 = new THING.widget.Panel({
    titleText: '设备列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: 'https://www.thingjs.com/static/images/example/icon.png'
});
panel1.position = [80, 0];

var panel2 = new THING.widget.Panel({
    titleText: '设备列表',
    closeIcon: false, // 是否有关闭按钮
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: 'https://www.thingjs.com/static/images/example/icon.png'
});
panel2.position = [80, 320];
// 创建任意对象
var dataObj1 = {
    open1: false,
    open2: false,
    open3: false,
    open4: false,
}
var dataObj2 = {
    open5: false,
    open6: false,
    open7: false,
    open8: false,
};

// 动态绑定物体
var open1 = panel1.addBoolean(dataObj1, 'open1').caption('设备01');
var open2 = panel1.addBoolean(dataObj1, 'open2').caption('设备02');
var open3 = panel1.addBoolean(dataObj1, 'open3').caption('设备03');
var open4 = panel1.addBoolean(dataObj1, 'open4').caption('设备04');
var open5 = panel2.addBoolean(dataObj2, 'open5').caption('设备01');
var open6 = panel2.addBoolean(dataObj2, 'open6').caption('设备02');
var open7 = panel2.addBoolean(dataObj2, 'open7').caption('设备03');
var open8 = panel2.addBoolean(dataObj2, 'open8').caption('设备04');

new THING.widget.Button('创建烟感报警', function () {
    var type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
    var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

new THING.widget.Button('创建摄像头', function () {
    var type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/';
    var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});
//创建equipment对象数组,以及数组标识
var equipmentGroup = [];
var index = 0;


app.on('load', function (ev) {

    app.level.change(ev.campus);

    for (var i = 0; i < 8; i++) {
        var type = null;
        if (i < 4) {
            type = 'http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/';
        } else {
            type = 'http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/';
        }
        var equipment = new Equipment(app, 'equipment' + index++, app.query('floor' + (Math.floor(Math.random() * 5) + 1))[0], type);
        equipment.createSelf();
        equipmentGroup.push(equipment);
    }

    open1.on('change', function (ev) {
        equipmentGroup[0].switchControl(ev);
    });
    open2.on('change', function (ev) {
        equipmentGroup[1].switchControl(ev);
    });
    open3.on('change', function (ev) {
        equipmentGroup[2].switchControl(ev);
    });
    open4.on('change', function (ev) {
        equipmentGroup[3].switchControl(ev);
    });
    open5.on('change', function (ev) {
        equipmentGroup[4].switchControl(ev);
    });
    open6.on('change', function (ev) {
        equipmentGroup[5].switchControl(ev);
    });
    open7.on('change', function (ev) {
        equipmentGroup[6].switchControl(ev);
    });
    open8.on('change', function (ev) {
        equipmentGroup[7].switchControl(ev);
    });

});

class Equipment extends THING.Thing {
    constructor(app, name, obj, url) {
        super(app);
        this.name = name;
        this.obj = obj;
        this.url = url;
        this.interval = null;
    }
    createSelf() {
        app.create({
            type: 'Equipment',
            name: this.name,
            url: this.url,
            parent: this.obj,
            localPosition: [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)],
            angle: 0
        });
    }
    switchControl(ev) {
        var flag;
        var equipment = app.query(this.name)[0];
        app.level.change(equipment);
        if (ev) {
            this.interval = setInterval(function () {
                if (flag) {
                    equipment.style.color = '#FF0000';
                    flag = false;
                } else {
                    flag = true;
                    equipment.style.color = '';
                }
            }, 500);
            console.log(this.interval + "查看是否创建了定时器");
        } else {
            console.log(this.interval);
            clearInterval(this.interval);
            if (equipment.style.color == '#FF0000')
                equipment.style.color = '';
        }
    }
}

THING.factory.registerClass('Equipment', Equipment);

  

目录
相关文章
|
17天前
|
SQL 存储 分布式计算
ODPS技术架构深度剖析与实战指南——从零开始掌握阿里巴巴大数据处理平台的核心要义与应用技巧
【10月更文挑战第9天】ODPS是阿里巴巴推出的大数据处理平台,支持海量数据的存储与计算,适用于数据仓库、数据挖掘等场景。其核心组件涵盖数据存储、计算引擎、任务调度、资源管理和用户界面,确保数据处理的稳定、安全与高效。通过创建项目、上传数据、编写SQL或MapReduce程序,用户可轻松完成复杂的数据处理任务。示例展示了如何使用ODPS SQL查询每个用户的最早登录时间。
54 1
|
14天前
|
机器学习/深度学习 自然语言处理 搜索推荐
大厂 10Wqps智能客服平台,如何实现架构演进?
40岁老架构师尼恩,凭借深厚的架构功力,指导众多小伙伴成功转型大模型架构师,实现职业逆袭。尼恩的《LLM大模型学习圣经》系列PDF,从基础理论到实战应用,全面覆盖大模型技术,助力读者成为大模型领域的专家。该系列包括《从0到1吃透Transformer技术底座》《从0到1吃透大模型的基础实操》《从0到1吃透大模型的顶级架构》等,内容详实,适合不同水平的读者学习。此外,尼恩还分享了多个智能客服平台的实际案例,展示了大模型在不同场景中的应用,为读者提供了宝贵的实践经验。更多技术资料和指导,请关注尼恩的《技术自由圈》公众号。
大厂 10Wqps智能客服平台,如何实现架构演进?
|
21天前
|
消息中间件 缓存 Java
亿级流量电商平台微服务架构详解
【10月更文挑战第2天】构建一个能够处理亿级流量的电商平台微服务架构是一个庞大且复杂的任务,这通常涉及到多个微服务、数据库分库分表、缓存策略、消息队列、负载均衡、熔断降级、分布式事务等一系列高级技术和架构模式。
68 3
|
2月前
|
Cloud Native Java 编译器
将基于x86架构平台的应用迁移到阿里云倚天实例云服务器参考
随着云计算技术的不断发展,云服务商们不断推出高性能、高可用的云服务器实例,以满足企业日益增长的计算需求。阿里云推出的倚天实例,凭借其基于ARM架构的倚天710处理器,提供了卓越的计算能力和能效比,特别适用于云原生、高性能计算等场景。然而,有的用户需要将传统基于x86平台的应用迁移到倚天实例上,本文将介绍如何将基于x86架构平台的应用迁移到阿里云倚天实例的服务器上,帮助开发者和企业用户顺利完成迁移工作,享受更高效、更经济的云服务。
将基于x86架构平台的应用迁移到阿里云倚天实例云服务器参考
|
2月前
|
缓存 物联网 数据库
如何帮助我们改造升级原有架构——基于TDengine 平台
一、简介 TDengine 核心是一款高性能、集群开源、云原生的时序数据库(Time Series Database,TSDB),专为物联网IoT平台、工业互联网、电力、IT 运维等场景设计并优化,具有极强的弹性伸缩能力。同时它还带有内建的缓存、流式计算、数据订阅等系统功能,能大幅减少系统设计的复杂度,降低研发和运营成本,是一个高性能、分布式的物联网IoT、工业大数据平台。 二、TDengine 功能与组件 TDengine 社区版是一开源版本,采用的是 AGPL 许可证,它具备高效处理时序数据所需要的所有功能,包括: SQL 写入、无模式写入和通过第三方工具写入 S标准 SQL 查
70 13
|
2月前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
66 6
|
2月前
|
编解码 Linux 开发工具
Linux平台x86_64|aarch64架构RTMP推送|轻量级RTSP服务模块集成说明
支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib–2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。
|
3月前
|
JSON 数据可视化 数据格式
【Azure 环境】中国区Azure是否可以根据资源组的模板,生成一个可视化的架构图呢?
【Azure 环境】中国区Azure是否可以根据资源组的模板,生成一个可视化的架构图呢?
【Azure 环境】中国区Azure是否可以根据资源组的模板,生成一个可视化的架构图呢?
|
3月前
|
编解码 Linux 数据安全/隐私保护
Linux平台x86_64|aarch64架构如何实现轻量级RTSP服务
为满足在Linux平台(x86_64与aarch64架构)上实现轻量级RTSP服务的需求,我们开发了一套解决方案。该方案通过调用`start_rtsp_server()`函数启动RTSP服务,并设置端口号及认证信息。支持AAC音频和H.264视频编码,可推送纯音频、纯视频或音视频流。此外,还支持X11屏幕采集、部分V4L2摄像头采集、帧率/GOP/码率调整、摄像头设备选择与预览等功能。对于音频采集,支持alsa-lib和libpulse接口。整体设计旨在提供150-400ms的低延迟体验,适用于多种应用场景。
|
4月前
|
消息中间件 负载均衡 数据管理
微服务架构在电商平台中的应用与实践
在现代电商平台的开发和运维中,微服务架构成为了提升系统灵活性和可扩展性的关键技术。本篇文章从实践出发,深入探讨了微服务架构在电商平台中的具体应用,包括服务拆分策略、通信机制、数据管理、以及常见的挑战和解决方案。通过真实的案例分析和代码示例,帮助读者全面了解微服务架构的优势和实施方法,提供在实际项目中的实践指导。

热门文章

最新文章