2

如何使用webgl(three.js)实现3D储能,3D储能站,3D智慧储能、储能柜的三维可视化解决方...

 1 year ago
source link: https://www.cnblogs.com/yeyunfei/p/16661071.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何使用webgl(three.js)实现3D储能,3D储能站,3D智慧储能、储能柜的三维可视化解决方案——第十七课

前言

上节课我们讲了《3D光伏发电》,与之配套的就是能量存储

这节课我们主要讲讲储能,储能站,在分布式能源系统中起到调节用对电的尖峰平谷进行削峰填谷的作用。特别是小型储能站,更加灵活,因地适宜。能够很好的解决电力在时空上的不平衡。储能电站技术的应用贯穿于电力系统发电、输电、配电、用电的各个环节。

储能站可视化解决方案,有效直观的提升储能调节效率。对设备进行状态告警监控,储能监控。

定义介绍:

  储能站:电能存储、转换及释放的设备集合站点

  储能柜:电能储存的基础单元,通常单个柜每日的储电量达到了几千度,类似大型充电宝

  阵列模块:一组储能柜,通过逻辑电路进行连接,实现统一充电放电。

  应用系统:是一套对设备状态、设备储能、工作状态,历史数据、预判调节等综合管理的软件,尽量减少人工的接入与实现全自动化。

言归正传,我们这篇主要讲解储能系统的可视化解决方案。从应用层解析储能站工作原理,储能站+物联网+可视化模式,监控储能设备状态,统计储能情况,有效调配用电效能。

一、效果展示

1.1、储能站整体风貌

800616-20220906110054117-626761942.gif

 整体界面主要是三维+图表,两边的图表通过echart实现即可。

天气预报调用天气接口:

   <iframe width="100%" style="margin-left:1.02vh;height:9vh" scrolling="no" frameborder="0" allowtransparency="true"
                            src="https://i.tianqi.com/?c=code&a=getcode&id=9&py=changshou&icon=1&color=white"></iframe>

 1.2、储能柜内部结构

双击储能柜,虚化其它建筑,展示储能柜内部结构

800616-20220906110315377-1295696504.gif

 实现代码如下:

        httpGet("../js/models/pdxinner.json", function (res) {//请求模型代码
            res[0].position.x = _obj.position.x;
            res[0].position.y = _obj.position.y - 70;
            res[0].position.z = _obj.position.z;
            res[0].scale.x = 0.75;
            res[0].scale.y = 0.75;
            res[0].scale.z = 0.75;
            //解析代码
            WT3DObj.commonFunc.loadModelsByJsons(res, { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true, function () {
                setInterval(function () {
                    var s1 = WT3DObj.commonFunc.findObject("dev_pdx_innerOBJCREN3");
                    var s2 = WT3DObj.commonFunc.findObject("dev_pdx_innerOBJCREN24");
                    var b1 = WT3DObj.commonFunc.findObject("dev_pdx_innerOBJCREN23");
                    var b2 = WT3DObj.commonFunc.findObject("dev_pdx_innerOBJCREN4");
                    var yh = { y: 1 };
                    new TWEEN.Tween(yh).to({//补间动画
                        y: 130
                    }, 3500).onUpdate(function (a) {
                        s1.scale.z = this.y;
                        s2.scale.z = this.y;
                        b1.scale.z = 1.01 - this.y / 130;
                        b2.scale.z = 1.01 - this.y / 130;
                    }).onComplete(function () {
                    }).start();
                }, 5000);
                dev_pdx_inner = WT3DObj.commonFunc.findObject("dev_pdx_inner");
                var dev_pdx_innerJson = WT3DObj.commonFunc.findJsonObject("dev_pdx_inner");
                var flash1 = [];
                var flash2 = [];
                var flash3 = [];
                var flashobjs = [];
                WT3DObj.commonFunc.flashObjs(flash1, "flash1",0x00ffff,0,200,0);
                WT3DObj.commonFunc.flashObjs(flash2, "flash2",0xffff00,0,200,0);
                WT3DObj.commonFunc.flashObjs(flash3, "flash3", 0x00ffff, 0, 200, 0);

            });
        })

 1.3、储能组阵列模块

展示阵列模块,同样是虚化建模模型,展示电池特效模型,并且在内部动态绘制echart图表

800616-20220906110115360-1641933534.gif
/*
 ==========================阵列模块.================================================
 */
ModelBussiness.prototype.showZLModels = function (callBack) {
    var _this = this;
    modelBussiness.hideInnerSkyBox(function () {
        modelBussiness.hideVitureDevs(null, function () {
            modelBussiness.showDCZLModels(function () {
                modelBussiness.doFlashChart = true;
                modelBussiness.flashChartModelData();
                if (callBack) {
                    callBack();
                }
            })
            
        });
        WT3DObj.commonFunc.changeCameraPosition({ x: -532.5470423260246, y: 2444.1589706386885, z: -5571.336446992522 }, { x: -679.5755451729872, y: 1118.7031210696823, z: -2501.040851792915 }, 1000,
            function () {


            });
    });
}

解析模型代码

    httpGet("../js/models/dczlmodel.json", function (res) {
            WT3DObj.commonFunc.loadModelsByJsons(res, { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true, function () {
                $.each(WT3DObj.scene.children, function (_index, _obj) {
                    if (_obj.name.indexOf("dcChart_") >= 0) {
                        _obj.oldPositionY = _obj.position.y;
                        modelBussiness.DCZLModels.push(_obj);

                        modelBussiness.addChartModel(_obj);
                    }
                });
                if (callBack) {
                    callBack();
                }
            });
        })

 1.4、储能柜上的光伏模块

只是简单的展示光伏板模型即可

 

800616-20220906110140545-2116271301.gif
ModelBussiness.prototype.showGFModels = function (callBack) {
    var _this = this;
    modelBussiness.hideInnerSkyBox(function () {
        modelBussiness.hideVitureDevs(null, function () {
            $.each(WT3DObj.scene.children, function (_index, _obj) {
                if (_obj.name.indexOf("dev_tynb_") >= 0 || _obj.name.indexOf("cqflows") >= 0) {
                    _obj.visible = true;
                    _obj.position.y = _obj.oldPositionY-1000000;
                    WT3DModel.commonFunc.changeObjsOpacity([_obj], 0.05, 1, 500, function (obj) {
                        if (callBack) {
                            callBack();
                        }
                    });
                }
            })
        });
    //切换视角 WT3DObj.commonFunc.changeCameraPosition({ x: 1737.2455427937452, y: 1127.7194462714513, z: -3801.9030092440707 },{ x: -1848.0785539202511, y: -472.5583563217438, z: -1257.736308515966 }, 1000, function () { }); }); }

 1.5、温度云图

根据实时数据,展示温度分布情况

 

800616-20220906110217771-240399989.gif
//创建热力图
ModelBussiness.prototype.createHeatMapModels = function (name, callBack) {
    var _this = this;
    _this.getHeatMapDataValue(function (_data) {
        var modeljson = {
            show: true,
            name: name,
            showSortNub: 700001,
            id: "",
            objType: "CloudChart",
            size: { x: 500, y: 500, z: 0 },
            position: {
                x: config.roomConfig.centerx,
                y: config.roomConfig.minheight,
                z: config.roomConfig.centerz,
            },
            scale: {
                x: config.roomConfig.length / 500,
                y: config.roomConfig.width / 500,
                z: 0
            },
            rotation: { x: -Math.PI / 2, y: 0, z: 0 },
            pictype: "rectangle", //arc圆 rectangle矩形 triangle三角形
            side: 1,
            opacity: 0.3,
            maxValue: 45,
            minValue: 0,
            materialType: "basic",
            panelColor: 0x00ffff,
            background: {
                color: 0xffffff,
                size: {
                    x: 100, y: 100,//画布大小
                    r: 20,//圆半径
                    start: 0,
                    end: 360,
                    angle_r: 10, x1: 0, y1: 0, x2: 100, y2: 100, x3: 100, y3: 0
                },
                imgurl: "",
                type: "arc", //arc圆 rectangle矩形 triangle三角形
                border: {
                    color: 0xff0000,
                    width: 1
                }
            },
            values: _data.data,
        };
            //var mesh=WT3DObj.createCloudChart(WT3DObj,modeljson);
            //  WT3DObj.addObject(mesh);
        for (var i = 0; i < 10; i++) {
            modeljson.position.y += (config.roomConfig.maxheight - config.roomConfig.minheight) / 10;
            modeljson.name = name + "_" + i;
            modeljson.showSortNub += i;

            modeljson.values = _data.data;

            var mesh=WT3DObj.createCloudChart(WT3DObj,modeljson);
            WT3DObj.addObject(mesh);
        }
    }, callBack);
};

 1.6、设备巡检

每一个储能柜进行状态巡检

重点在于创建巡检路径,路径上添加巡检设备,对每一个设备进行数据请求。

800616-20220906110243287-1355638750.gif
ModelBussiness.prototype.doRoute = function (routeId) {
    var _this = this;
    _this.routeDev = 0;
    _this.normalDev = 0;
    _this.exceptionDev = 0;
    _this.routeState = 1;
  //修改右侧html列表 $("#d24value1").html(modelBussiness.routeDev + " <font>台</font>"); $("#d24value2").html(modelBussiness.normalDev + " <font>台</font>"); $("#d24value3").html(modelBussiness.exceptionDev + " <font>台</font>"); $("#routeDataList").html(""); //创建巡检路径 var points = [{"position":{"x":298,"y":2851,"z":-6347},"target":{"x":81,"y":195,"z":-920}},...,{"position":{"x":3785,"y":191,"z":-316},"target":{"x":2782,"y":100,"z":-230}}]; //开始回调巡检 function doMove(index) { var _obj = points[index]; if (_obj && modelBussiness.routeState == 1) { WT3DObj.commonFunc.changeCameraPosition(_obj.position, _obj.target, 1000, function () { if (_obj.addtion_name) { modelBussiness.showDevDetail(_obj.addtion_name, function () {
              //递归 doMove(index + 1); }); } else {
            //递归实现 doMove(index + 1); } }); } else { layer.msg("巡检已结束!") } } doMove(0) }

 二、实现逻辑

2.1、模型创建

2.1.1、地基模型

跟其它项目一样,首先根据图纸,创建基础地基模型,这里的地基模型还是以代码实现方式为主,这样一个场景,代码实现模型后,也就几kb的占用,很适合网络传输。

800616-20221111164059831-680632459.png

模型代码如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.2、配电室模型

配电室模型,我们主要实现外部接口,需求中没有需要实现内部的要求,这样只是实现外皮结构即可

800616-20221111163216817-1021257267.png

模型代码如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.3、储能箱模型

储能箱模型比较简单,主要分为4个部分组合,头部,门、箱体,以及后面的空调部分

800616-20221111163318166-250587145.png

模型代码如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

 2.1.4、储能箱内部结构特效

  2.1.4.1、储能箱内部底盘,加上后部空调

  这里的空调冷气特效可以用粒子模型实现

  

800616-20221111163352511-1301667674.png

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.4.2、储能箱蓄电池部分

 

800616-20221111163427014-1797957492.png

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.4.3、储能箱 外部箱体虚化结构

为了更好的展示内部结构,又能体现箱体的完整性,我们将箱壳半透明化

 

800616-20221111163446565-658469994.png

实现如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.5、阵列模型特效模型

整列模块电池特效主要是模型+echart数据在内部展示,首先我们通过代码实现模型以及电池特效,然后结合echart图表在场景内绘制

800616-20221111163605059-388203263.png

实现如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.1.6、变压器模型

变压器模型在项目中只是展示,这个模型也通过代码方式实现即可

 

800616-20221111163929193-1865461709.png

实现如下:

ContractedBlock.gifExpandedBlockStart.gif

View Code

2.2、数据接入

2.2.1、基于ajax请求封装

var httpInvoke = function (url, type, data, successCb, failedCb, userData, async) {
    return $.ajax({
        url: url,
        type: type,
        data: data,
        headers: {
        },
        async: async,
        times: 0,
        beforeSend: function (request) { },
        success: function (response, status, hreq) {if (successCb != null) {
                successCb(response, status, userData);
            }
        },
        error: function (err) {
            console.log(err);
            if (failedCb != null) {
                failedCb(err.statusCode(), userData);
            }
        }

    })
}

2.2.2、接口api封装

function WebAPI() {
    this.serverHead = "";
    this.serverHead2 = "";
    /*站点介绍    /station
    空调系统    /air?name=1-1
    消防系统    /fire-ctrl?name=1-1
    PCS系统    /pcs?name=1-1
    电池柜基本信息    /battery-basic?name=1-1
    月电量趋势图    /electric-month
    充放电功率    /dis-charge
    SOC    /soc
    月收益趋势图    /profit-month
    日负荷曲线    /load
    */
    this.urls = {
        station: this.serverHead2+"/station",
        airConditioner: this.serverHead2+"/air",
        fireControl: this.serverHead2 +"/fire-ctrl",
        pcs: this.serverHead2+"/pcs",
        batteryCabinetBasic: this.serverHead2 + "/battery-basic",
        batteryPower: this.serverHead2 + "/battery-power",

        powerMonth: this.serverHead2 + "/electric-month",
        chargeDischarge: this.serverHead2 + "/dis-charge",
        so: this.serverHead2 + "/soc",
        profitmonth: this.serverHead2 + "/profit-month",
        load: this.serverHead2 + "/load",
        surplus: this.serverHead2 + "/surplus-power/",
        hostPowerMonth: this.serverHead2+"/ac/host-power-month",
        powerYear: this.serverHead2+"/ac/power-year",
        abstract: this.serverHead2+"/ac/abstract",
        consumptionDay: this.serverHead2+"/consumption-day/    ",
        chargeDay: this.serverHead2+"/charge-day/",
        temperatures: "../demoData/tempTureData.json",//
    }
}
WebAPI.prototype.getairConditioner = function (name,sunFunc) {
    var _this = this;
    var url = this.serverHead + this.urls.airConditioner + "?name=" + name;
    httpGet(url, function (response) {
        if (response && response.data && sunFunc) {

            sunFunc(response.data);
        }
    }, function () {
        layer.msg("获取数据异常");

    });
}

2.2.3、数据展示调用

IndexPage.prototype.showXDCData = function (id) {
    webapi.getairConditioner(id, function (data) {
        $.each(data, function (_i, _o) {
            if (_o.value=="开启"){
                _o.value = '开启<img src="../img/online.png" style="height:3vh;" />';
            } else if (_o.value == "关闭") {
                _o.value = '关闭<img src="../img/outLine.png" style="height:3vh;" />';
            }
            $("#air_" + _o.key).html(_o.value);
        })
    })
    webapi.getfireControl(id, function (data) {
        $.each(data, function (_i, _o) {
            $("#fire_" + _o.key).html(_o.value);
        })
    })
    webapi.getpcs(id, function (data) {
        $.each(data, function (_i, _o) {
            $("#psc_" + _o.key).html(_o.value);
        })
    })
    webapi.getbatteryCabinetBasic(id, function (data) {
        $.each(data, function (_i, _o) {
            $("#station_" + _o.key).html(_o.value);
        })
    })
}

2.3、逻辑控制

  三维的逻辑控制主要总结如下几点:特效展示、模型隐藏、模型展示、模型分解、模型事件绑定、模型控制

2.3.1、操作按钮事件绑定

 $(".navli").click(function () {
        if (modelBussiness.doAnimation) {
            layer.msg("场景动画执行中....");
            return;
        }
        var dataid = $(this).attr("data-id");
        $(".navli").attr("class", "navli");
        $(this).attr("class", "navli activeBg");
        modelBussiness.changeSceneModel(dataid);
        indexPage.hideCKB();
    });

2.3.2、三维场景切换

  场景切换时特别注意状态的改变与内存回收释放资源

//切换场景
changeSceneModel = function (dataid,_obj) {
    var _this = this;
    modelBussiness.doAnimation = true;
    switch (_this.currentSceneState) {//回收状态
        case "showCDX":
        indexPage.hideCNGChart();
            WT3DObj.commonFunc.changeCameraPosition(config.default.camera, config.default.target, 1000,
                function () {
                    modelBussiness.hideInnderCube(function () {
                        modelBussiness.showVitureDevs(function () {
                            modelBussiness.showInnerSkyBox(function () {
                                doModel(dataid);
                            })
                        })
                    });
                });
            break;
        case "zlmk":
            modelBussiness.hideZLModels(function () {
                doModel(dataid);
            })
            break;
        case "gfmk":
            indexPage.hideGFChart();
            
            modelBussiness.hideGFModels(function () {
                doModel(dataid);
            });
            break;
        case "wdc":
            modelBussiness.showTemptureMap(function () {
                    $("#cubeColorDescri").hide();
                doModel(dataid);
            })
            break;
        case "xlms":
            layer.confirm("是否确认关闭巡检", function () {
                $("#routeBtn").attr("class", "routebtn");
                $("#routeBtn").html("开始巡检");
                layer.closeAll();
                //修改见面布局
                {
                    //隐藏左右看板 初始化状态
                   ...
                }

                modelBussiness.closeRoute(function () {
                    doModel(dataid);
                });
            }, function () {
                modelBussiness.doAnimation = false;
            })
            break;
        default: doModel(dataid);break;
    }
    _this.currentSceneState = dataid;//当前场景状态
    function doModel(dataid) {switch (dataid) {
            case "showCDX":
                indexPage.hideCKB();
                indexPage.showCNGChart(_obj);
                modelBussiness.hideInnerSkyBox(function () {
                    modelBussiness.hideVitureDevs(_obj, function () {
                     modelBussiness.doAnimation = false;
                    });
                    modelBussiness.showInnderCube(_obj);
                    modelBussiness.nearCameraPostion(_obj, null, function () {
                    })
                });
                break;
            case "zlmk":
                modelBussiness.showZLModels(function () {
                    modelBussiness.doAnimation = false;
                })
                 break;
            case "gfmk":
                indexPage.showGFChart();
                 modelBussiness.showGFModels(function () {
                     modelBussiness.doAnimation = false;
                 });
                break;
            case "wdc"://温度场
                modelBussiness.showTemptureMap(function () {
                    modelBussiness.doAnimation = false;
                });
                 break;
            case "xlms":
                 modelBussiness.doAnimation = false;
                indexPage.doRouteDetail();
                 break;
            default:
                 modelBussiness.doAnimation = false;
                 break;
         }
    }
   
}

2.3.3、模型事件绑定

{
            dbclick: [
                {
                    obj_name: "ALL",
                    obj_event: function (_obj, face,objs) { // 被选中的对象 被选中的面
                        // 此处设置双击聚焦
                        {
                            modelBussiness.dbClickSelectCabinet(_obj, face, objs)
                            console.log(objs);
                        }
                    }
                },
            ],
           mouseDown: [
               {
                   obj_name: "ALL",
                   obj_event: function (_obj, face, objs) { // 被选中的对象 被选中的面
                       // 此处设置双击聚焦
                       {
                           modelBussiness.ClickSelectCabinet(_obj, face, objs)
                           console.log(objs);
                       }
                   }
               },
            ],
            mouseMove: [{
                obj_name: "doorLeft",
                obj_event: function (_obj, face, objs) {
                    console.log(_obj.name);
                    return true;//返回true表示移动
                }
            },
            ]
        }

由于篇幅原因,我们本节课先到这里,

下节课主要介绍3D实现配电站、变电所

技术交流 [email protected]

交流微信:

    800616-20190306111130020-1677299606.png

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

其它相关文章:

webgl(three.js)3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决方案——第十六课

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

webgl(three.js)实现室内三维定位,3D定位,3D楼宇bim、实时定位三维可视化解决方案——第十四课(定位升级版)

使用three.js(webgl)搭建智慧楼宇、设备检测、数字孪生——第十三课

如何用three.js(webgl)搭建3D粮仓、3D仓库、3D物联网设备监控-第十二课

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

如何用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机房管线问题(机房升级版)-第九课(一)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK