webgl(three.js)實現室內三維定位,3D定位,3D樓宇bim、實時定位三維可視化解決方案——第十四課(定位升級版)

来源:https://www.cnblogs.com/yeyunfei/archive/2022/09/06/16616696.html
-Advertisement-
Play Games

使用three.js(webgl)搭建智慧樓宇、3D定位、三維室內定位、設備檢測、數字孿生、物聯網3D、物業3D監控、物業基礎設施可視化運維、3d建築,3d消防,消防演習模擬,3d庫房,webGL,threejs,3d機房,bim管理系統 ...


序:

  還是要抽出時間看書的,迷上了豆豆的作品,最近在看《天幕紅塵》,書中主人公的人生價值觀以及修為都是讓我驚為嘆止。很想成為那樣的人,但是再看看自己每天干的事,與時間的支配情況,真是十分的汗顏。除了為了生活所必須的工作時間外,還有大部分零散的時間不是給了短視頻,就是給了短訊文章,簡訊媒介,不說是毫無意義吧,但也著實是浮躁虛誇了。

  用豆豆作品里的話術,"透視社會依次有三個層面:技術、制度和文化。小到一個人,大到一個國家一個民族,任何一種命運歸根到底都是那種文化屬性的產物"。 我終究是乾技術的,還是無法洞察其中奧義,只是熟悉了幾門糊口的技巧而已,究竟其本質便無所得之了,或者說依然沒找到那安身立命的意義。長路漫漫,且尋著吧。人生也許也像某個技術門類,需要不斷的回顧,記錄,總結。才能真正發現一些實質性的東西。究竟涅槃,如來?

  本想談技術,話題終究是扯遠了,但總歸要扯點啥吧,練練文筆也好,述述心態也罷,反正也少有人看寫在前面的廢話,這任算是,無傷技術之大雅,無關文章之緊要了。

  還是閑話少序,切入正題吧。

前言:

  前面的課程介紹過定位相關的技術解決方案,《webgl(three.js)實現室內定位,樓宇bim、實時定位三維可視化解決方案——第五課》 ,從硬體到可視化,都已經比較全面的講述了一遍,這邊文章相當於那篇文件的一個改進版本,主要是在可視化呈現方面,根據具體的實施項目,在可視化方面做一個比較全面的技術剖析。

關於硬體採集端技術,因為精度要求不高,任然採用的是:低功耗有源RFID+讀卡器基地器+智能分析。

關於室內定位市場前景,那篇文章也做了一些分析,這裡不做贅述。

 一、整體效果

還是先看整體效果,再探具體實現技術的究竟

 上圖展示整體園區以及周邊的科技感效果。

  上圖展示近距離整體園區建設風貌。

二、功能展示

2.1、展開樓層

 

樓層展開實現比較簡單,首先再建模的時候講究分離模型,不能講樓層內部,樓層外牆一股腦做成一個模型,需要講模型分解,分開建模,

實現樓層展開就比較方便了,只需要控制外牆模型隱藏,然後控制每個樓層的的高度位置就可以。

 實現代碼如下:

ModelBussiness.prototype.tempNameList = [];
ModelBussiness.prototype.tempDataList = [];
ModelBussiness.prototype.videoDataCache = {};
ModelBussiness.prototype.showFloorState = "close";
//顯示樓層內部情況
ModelBussiness.prototype.showBuildFloors = function (buildnub, callBack) {
    var _this = this
    _this.showFloorState = "open";
    var builds = WT3DObj.commonFunc.findObjectsByNames(["wjwb1_232", "wjwbuilds_55"]);
    //隱藏大樓
    WT3DObj.commonFunc.setSkinColorByname("wjwb1_232", 0x00ffff);
    WT3DObj.commonFunc.changeCameraPosition({ x: 3652.5144280174954, y: 990.805706980618, z: 5107.394022507952 }, { x: 1914.4771268074287, y: -723.8717024746979, z: 2181.6118222317314 }, 500,
        function () { });
    WT3DModel.commonFunc.changeObjsOpacity(builds, 1, 0.1, 500, function (obj) {
            var _obj = WT3DObj.commonFunc.findObject("wjwb1_232");
            if (typeof (_obj.oldPositionY) == 'undefined') {
                _obj.oldPositionY = _obj.position.y
            }
            _obj.position.y = 1000000;
            _obj.visible = false;
 
        WT3DObj.commonFunc.changeCameraPosition({ x: 3247.2796000738454, y: 2191.5405041410445, z: 5229.077446579187 }, { x: 2719.261239206996, y: 80.49406057323252, z: 3015.8739289848077 }, 500,
            function () { });

        var names = ["floor_1", "floor_2", "floor_3", "floor_4", "floor_5", "floor_6"];
        var floors = WT3DObj.commonFunc.findObjectsByNames(names);
        modelBussiness.openFloors(floors, function () {
            if (callBack) {
                callBack();
            }
        });
    });

}
//隱藏樓層內部情況
ModelBussiness.prototype.hideBuildFloors = function (buildnub, callBack) {
    var _this = this
    _this.showFloorState = "close";
    var names = ["floor_1", "floor_2", "floor_3", "floor_4", "floor_5", "floor_6"];
    var builds = WT3DObj.commonFunc.findObjectsByNames(["wjwb1_232", "wjwbuilds_55"]);
    var floors = WT3DObj.commonFunc.findObjectsByNames(names);
    this.closeFloors(floors, function () {
        $.each(builds, function (_index, _obj) {
            if (typeof (_obj.oldPositionY) == 'undefined') {
                _obj.oldPositionY = _obj.position.y
            }
            _obj.position.y = _obj.oldPositionY;
            _obj.visible = true;
        })
        WT3DModel.commonFunc.changeObjsOpacity(builds, 0, 1, 1000, function (obj) {
            WT3DObj.commonFunc.setSkinColorByname("wjwb1_232", 0x000000);
        });
        if (callBack) {
            callBack();
        }
    })

}
//顯示樓層
ModelBussiness.prototype.openFloors = function (floors, callBack) {
    //顯示樓層
    $.each(floors, function (_index, _obj) {
        if (typeof (_obj.oldPositionY) == 'undefined') {
            _obj.oldPositionY = _obj.position.y
        }
        if (_obj.position.y > 100000) {
            _obj.position.y -= 1000000;
        }
        _obj.visible = true;
    });
    setTimeout(function () {
        $.each(floors, function (_index, _obj) {
        //展開樓層
        _obj.floorPosition = _obj.position.y;
        var floor = parseInt(_obj.name.split("_")[1]);
        height = (floor - 1) * 300 +50;
        new Tn(_obj.position).to({//補充間隔動畫
            y: height
        }, 500).start();
        });
        setTimeout(function () {

        if (callBack) {
            callBack()
        }
        },600);
    }, 500)

}

 2.2、繪製定位路徑

 

 繪製定位路徑,相比樓層展開要複雜一些,這裡要用到定位設備與虛擬模型之間的關聯與綁定,然後標記跟著模型運動

主要分為以下幾步:

  第一、建模

  第二、建立虛擬模型,綁定設備id

  第三、數據id轉換為模型id

  第四、定址,找到對應的虛擬模型列表、並且獲取各自位置

  第五、根據位置畫線、移動標簽

三、具體實現

3.1、創建周遭環境模型,特效模型等

 建模代碼如下:

[{"show":true,"uuid":"","name":"cube2_6","objType":"cube2","length":200,"width":200,"height":200,"x":0,"y":200,"z":0,"style":{"skinColor":16777215,"skin":{"skin_up":{"skinColor":16777215,"imgurl":"../../img/3dImg/rack_inside.jpg","materialType":"basic","side":1,"opacity":1},"skin_down":{"skinColor":16777215},"skin_fore":{"skinColor":16777215},"skin_behind":{"skinColor":16777215},"skin_left":{"skinColor":16777215},"skin_right":{"skinColor":16777215}}},"showSortNub":6},{"show":true,"uuid":"","name":"wjwbuilds_270","objType":"GroupObj","scale":{"x":1,"y":1,"z":1},"position":{"x":0,"y":0,"z":0},"rotation":[{"direction":"x","degree":0}],"modelGroupName":"wjwbuilds","modelSrc":"../js/msj3D/sourse/customModels/models/wjwbuilds.json?v1.50.4428873971970626","srcType":"filePath","showSortNub":270}]

 3.2、創建外牆模型

 單獨創建需要裂解的大樓外牆模型,具體如下:

[{"show":true,"uuid":"","name":"cube2_6","objType":"cube2","length":200,"width":200,"height":200,"x":0,"y":200,"z":0,"style":{"skinColor":16777215,"skin":{"skin_up":{"skinColor":16777215,"imgurl":"../../img/3dImg/rack_inside.jpg","materialType":"basic","side":1,"opacity":1},"skin_down":{"skinColor":16777215},"skin_fore":{"skinColor":16777215},"skin_behind":{"skinColor":16777215},"skin_left":{"skinColor":16777215},"skin_right":{"skinColor":16777215}}},"showSortNub":6},{"show":true,"uuid":"","name":"wjwb1_7","objType":"GroupObj","scale":{"x":1,"y":1,"z":1},"position":{"x":0,"y":0,"z":0},"rotation":[{"direction":"x","degree":0}],"modelGroupName":"wjwb1","modelSrc":"../js/msj3D/sourse/customModels/models/wjwb1.json?v1.50.7245325959034448","srcType":"filePath","showSortNub":7}]

 3.3、其它細節樓宇模型

 作為輔助美觀模型,單獨創建模型如下:

[{"show":true,"uuid":"","name":"wjwb2_38","objType":"GroupObj","scale":{"x":1,"y":1,"z":1},"position":{"x":0,"y":0,"z":0},"rotation":[{"direction":"x","degree":0}],"modelGroupName":"wjwb2","modelSrc":"../js/msj3D/sourse/customModels/models/wjwb2.json?v1.50.2327047742615571","srcType":"filePath","showSortNub":38}]

 3.4、樓層模型

各樓層模型單獨創建,便於控制與展示

[{"show":true,"uuid":"","name":"wjwf1_40","objType":"GroupObj","scale":{"x":1,"y":1,"z":1},"position":{"x":0,"y":0,"z":0},"rotation":[{"direction":"x","degree":0}],"modelGroupName":"wjwf1","modelSrc":"../js/msj3D/sourse/customModels/models/wjwf1.json?v1.50.13740666293081194","srcType":"filePath","showSortNub":40}]

 多角度觀察一下樓層模型:

 單元測試樓宇模型裂解效果

四、定位詳解

 本想放到第三章一起講解,但這部分實現比較重要,所以單獨一章講解

 如上圖,粉色的點位表示房間門內的輔助點,亮綠色的點位表示設備所對應的門外輔助點

我們這裡只需要綁定門外的輔助點到對應的設備就可以

當再某處停留事件過長,我們通常判斷已經進入房間,直接講門外門內兩個點鏈接,即可。

 4.1、存儲虛擬點位

//使用二叉樹儲存法,將輔助點與設備id進行綁定。
{
"cp": { "x": 2898.062281840033, "y": 726.9857194504245, "z": 4474.268417657025 },
     "ct": { "x": 2919.5843654655655, "y": -325.13303496900545, "z": 3386.2841814639646 }, line: [2010, 2002, 2016, 2028, 2018, 2032, ["h1", 2038], 2026, 2022, 2036, 2020, [2000, 2034], 2004, 2014],//二叉樹存儲數據 Points: [{ "name": "f2d_2010", "position": { "x": 2824.843, "y": 82.926, "z": 3874.214 } }, { "name": "f2d_2016", "position": { "x": 2824.843, "y": 82.926, "z": 3977.133 } }, { "name": "f2d_2028", "position": { "x": 2824.843, "y": 82.926, "z": 4010.544 } }, { "name": "f2d_2018", "position": { "x": 2824.843, "y": 82.926, "z": 4084.157 } }, { "name": "f2d_2032", "position": { "x": 2824.843, "y": 82.926, "z": 4110.372 } }, { "name": "f2d_2038", "position": { "x": 2824.843, "y": 82.926, "z": 4191.56 } }, { "name": "f2d_h1", "position": { "x": 2824.843, "y": 82.926, "z": 4145.947 } }, { "name": "f2d_2026", "position": { "x": 2894.811, "y": 82.926, "z": 4142.355 } }, { "name": "f2d_2022", "position": { "x": 2929.456, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2036", "position": { "x": 2993.039, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2020", "position": { "x": 3127.172, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2000", "position": { "x": 3138.358, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2014", "position": { "x": 3196.413, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2004", "position": { "x": 3159.209, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2034", "position": { "x": 3140.007, "y": 82.926, "z": 4238.683 } }, { "name": "f2d_2010_room", "position": { "x": 2794.836, "y": 82.926, "z": 3874.214 } }, { "name": "f2d_2002", "position": { "x": 2820.207, "y": 82.926, "z": 3901.037 } }, { "name": "f2d_2002_room", "position": { "x": 2794.657, "y": 82.926, "z": 3901.037 } }, { "name": "f2d_2016_room", "position": { "x": 2795.467, "y": 82.926, "z": 3977.133 } }, { "name": "f2d_2028_room", "position": { "x": 2790.713, "y": 82.926, "z": 4010.544 } }, { "name": "f2d_2018_room", "position": { "x": 2797.472, "y": 82.926, "z": 4074.339 } }, { "name": "f2d_2032_room", "position": { "x": 2798.134, "y": 82.926, "z": 4110.372 } }, { "name": "f2d_2038_room", "position": { "x": 2796.368, "y": 82.926, "z": 4191.56 } }, { "name": "f2d_2026_room", "position": { "x": 2894.811, "y": 82.926, "z": 4076.308 } }, { "name": "f2d_2022_room", "position": { "x": 2929.456, "y": 82.926, "z": 4107.921 } }, { "name": "f2d_2036_room", "position": { "x": 2993.039, "y": 82.926, "z": 4103.112 } }, { "name": "f2d_2020_room", "position": { "x": 3127.172, "y": 82.926, "z": 4110.79 } }, { "name": "f2d_2000_room", "position": { "x": 3138.358, "y": 82.926, "z": 4156.895 } }, { "name": "f2d_2004_room", "position": { "x": 3159.209, "y": 82.926, "z": 4156.794 } }, { "name": "f2d_2014_room", "position": { "x": 3196.413, "y": 82.926, "z": 4157.111 } }, { "name": "f2d_2034_room", "position": { "x": 3165.756, "y": 82.926, "z": 4238.683 } }] }
//存儲輔助點模型位置到數組中,方便快速查找。
[{ "name": "f2d_2010", "position": { "x": 2824.843, "y": 82.926, "z": 3874.214 } }, { "name": "f2d_2016", "position": { "x": 2824.843, "y": 82.926, "z": 3977.133 } }, { "name": "f2d_2028", "position": { "x": 2824.843, "y": 82.926, "z": 4010.544 } }, { "name": "f2d_2018", "position": { "x": 2824.843, "y": 82.926, "z": 4084.157 } }, { "name": "f2d_2032", "position": { "x": 2824.843, "y": 82.926, "z": 4110.372 } }, { "name": "f2d_2038", "position": { "x": 2824.843, "y": 82.926, "z": 4191.56 } }, { "name": "f2d_h1", "position": { "x": 2824.843, "y": 82.926, "z": 4145.947 } }, { "name": "f2d_2026", "position": { "x": 2894.811, "y": 82.926, "z": 4142.355 } }, { "name": "f2d_2022", "position": { "x": 2929.456, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2036", "position": { "x": 2993.039, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2020", "position": { "x": 3127.172, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2000", "position": { "x": 3138.358, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2014", "position": { "x": 3196.413, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2004", "position": { "x": 3159.209, "y": 82.926, "z": 4137.219 } }, { "name": "f2d_2034", "position": { "x": 3140.007, "y": 82.926, "z": 4238.683 } }, { "name": "f2d_2010_room", "position": { "x": 2794.836, "y": 82.926, "z": 3874.214 } }, { "name": "f2d_2002", "position": { "x": 2820.207, "y": 82.926, "z": 3901.037 } }, { "name": "f2d_2002_room", "position": { "x": 2794.657, "y": 82.926, "z": 3901.037 } }, { "name": "f2d_2016_room", "position": { "x": 2795.467, "y": 82.926, "z": 3977.133 } }, { "name": "f2d_2028_room", "position": { "x": 2790.713, "y": 82.926, "z": 4010.544 } }, { "name": "f2d_2018_room", "position": { "x": 2797.472, "y": 82.926, "z": 4074.339 } }, { "name": "f2d_2032_room", "position": { "x": 2798.134, "y": 82.926, "z": 4110.372 } }, { "name": "f2d_2038_room", "position": { "x": 2796.368, "y": 82.926, "z": 4191.56 } }, { "name": "f2d_2026_room", "position": { "x": 2894.811, "y": 82.926, "z": 4076.308 } }, { "name": "f2d_2022_room", "position": { "x": 2929.456, "y": 82.926, "z": 4107.921 } }, { "name": "f2d_2036_room", "position": { "x": 2993.039, "y": 82.926, "z": 4103.112 } }, { "name": "f2d_2020_room", "position": { "x": 3127.172, "y": 82.926, "z": 4110.79 } }, { "name": "f2d_2000_room", "position": { "x": 3138.358, "y": 82.926, "z": 4156.895 } }, { "name": "f2d_2004_room", "position": { "x": 3159.209, "y": 82.926, "z": 4156.794 } }, { "name": "f2d_2014_room", "position": { "x": 3196.413, "y": 82.926, "z": 4157.111 } }, { "name": "f2d_2034_room", "position": { "x": 3165.756, "y": 82.926, "z": 4238.683 } }]

 4.2、具體實現畫線定位

 實現畫線定位是利用設備id找到對應輔助點,然後將輔助點鏈接起來的方式

定位標簽移動,使用補間動畫移動效果即可。

//顯示路徑
function drawLineFunc(floor, start, end, timeLong, startOut, endIn) {
    //drawLineDataList.push({
    //    floor: 樓層,
    //    start: 開始設備點id,
    //    end: 結束設備點id,
    //    timeLong: 移動時長,
    //    startOut: 是否是從房間里出來,
    //    endIn: 是否進入房間
    //});
  
    WT3DObj.commonFunc.changeCameraPosition(ConfigData["f" + floor].cp, ConfigData["f" + floor].ct, 300,
        function () { });
    //生成路徑節點數組
    var startindex = -1;
    var startindex2 = -1;
    var endindex = -1;
    var endindex2 =-1;
    var linedata = ConfigData["f" + floor].line;
    $.each(linedata, function (_index, _obj) {
        if (_obj instanceof Array) {
            $.each(_obj, function (_cindex, _cobj) {
                if (_cobj + "" == start + "") {
                    startindex = _index;
                    startindex2 = _cindex;
                }
                if (_cobj + "" == end + "") {
                    endindex = _index;
                    endindex2 = _cindex;
                }
            })
        } else {
            if (_obj + "" == start + "") {
                startindex = _index;
            }
            if (_obj + "" == end + "") {
                endindex = _index;
            }
        }
    });
    var pointPath = [];
    if (startindex < endindex) {
        for (var i = startindex; i <= endindex; i++) {
            var pointnub = linedata[i];
            if (pointnub instanceof Array) {
                pointPath.push(pointnub[0]);
            } else {
                pointPath.push(pointnub);
            }
        }
    }
    else if (startindex > endindex) {
        for (var i = startindex; i >= endindex; i--) {
            var pointnub = linedata[i];
            if (pointnub instanceof Array) {
                pointPath.push(pointnub[0]);
            } else {
                pointPath.push(pointnub);
            }
        }
    }
    if (endindex2 > 0) {
        var pointnub = linedata[endindex];
        for (var i = 1; i <= endindex2; i++) {
            pointPath.push(pointnub[i]);
        }
    }
    if (startindex2 != -1) {
        var startarray = [];
        var pointnub = linedata[startindex];
        for (var i = startindex2; i >0; i--) {
            startarray.push(pointnub[i]);
        }
        pointPath = startarray.concat(pointPath);
    }
    var linePositionArray = ConfigData["f" + floor].Points;
    var lineObjs = {}
    $.each(linePositionArray, function (_index, _obj) {
        lineObjs[_obj.name] = _obj.position;
    });
    var pathpoints = [];
    var positiony = WT3DObj.commonFunc.findObject("floor_" + floor).position.y ;
    $.each(pointPath, function (_index, _obj) {
    
        if (lineObjs["f" + floor + "d_" + _obj]) {
            pathpoints.push({
                x: lineObjs["f" + floor + "d_" + _obj].x,
                y: positiony ,
                z: lineObjs["f" + floor + "d_" + _obj].z,
                type: "nomal"
            });
        }
        
    });
    if (startOut) {
        $.each(linePositionArray, function (_index, _obj) {
            if (_obj.name == "f" + floor + "d_" + start + "_room") {
                pathpoints = [{
                    x: _obj.position.x,
                    y: positiony,
                    z: _obj.position.z,
                    type: "nomal"
                }].concat(pathpoints);
               }
        });
    }
    if (endIn) {
        if (end) {

            $.each(linePositionArray, function (_index, _obj) {
                if (_obj.name == "f" + floor + "d_" + end +"_room") {
                    pathpoints.push({
                        x: _obj.position.x,
                        y: positiony,
                        z: _obj.position.z,
                        type: "nomal"
                    })
                }
            });
        }
    };
  //創建節點模型
var modelsNames = modelBussiness.createRoadLine(pathpoints, new Date().getTime(), timeLong); CModelNames = CModelNames.concat(modelsNames); }

畫線與移動具體實現如下:

ModelBussiness.prototype.Drawing = false;
ModelBussiness.prototype.createRoadLine = function (points, index, timeLong) {
    if (modelBussiness.Drawing) {
        return;
    }
    modelBussiness.Drawing = true;
    var addModelNames = [];
    //points.push({
    //    x: _pobj[1],
    //    y: 0,
    //    z: _pobj[2],
    //    type: "nomal"
    //});
  //創建移動標簽模型代碼
var moveobj = { "name": "moveObj", "objType": "picIdentification", "size": { "x": 30, "y": 30 }, "position": { x: points[0].x, y: points[0].y+30, z: points[0].z }, "imgurl": "../img/3dImg/xhd.png", "showSortNub":1, "show": true, "customType1": "", "customType2": "", "animation": null, "dbclickEvents": null, "wx": null, "wy": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }; var models = []; var moveObjModel = WT3DObj.commonFunc.findObject("moveObj"); if (!moveObjModel) { models.push(moveobj); addModelNames.push("moveObj"); }
//創建線模型代碼
var model = { "show": true, "uuid": "", "name": "splinecurve_7", "objType": "SplineCurve", "segments": 24, "points": [{ "x": 0, "y": 300, "z": 0 }, { "x": 100, "y": 250, "z": 100 }, { "x": 100, "y": 400, "z": 400 }], "style": { "skinColor": 0xDFFD6 }, "LineStyle": "LinePieces", "position": { "x": 0, "y":0, "z": 0 }, "scale": { "x": 1, "y": 1, "z": 1 }, "rotation": [{ "direction": "x", "degree": 0 }, { "direction": "y", "degree": 0 }, { "direction": "z", "degree": 0 }], "showSortNub": 1, "customType1": "", "customType2": "", "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null } model.name = "Line" + index; addModelNames.push("Line" + index); model.segments = points.length - 1; var newpoints = []; var pointlength = [];//單段長度數組 var allLength = 0;//總長度 for (var i = 0; i < points.length; i++) { newpoints.push(points[0]); if (i < points.length - 1) { var length= Math.sqrt((points[i + 1].x - points[i].x) * (points[i + 1].x - points[i].x) + (points[i + 1].y - points[i].y) * (points[i + 1].y - points[i].y) + (points[i + 1].z - points[i].z) * (points[i + 1].z - points[i].z)) pointlength.push(length); allLength += length; } } model.points = newpoints; models.push(model); var modelnames = []; for (var i = 0; i < points.length - 1; i++) { if (points[i].x == points[i + 1].x && points[i].z == points[i + 1].z) { continue; } var position = { x: (points[i].x + points[i + 1].x) / 2, y: points[i].y, z: (points[i].z + points[i + 1].z) / 2 } var rotaiionz = this.getAngle(points[i].x, points[i].z, points[i + 1].x, points[i + 1].z) / 180 * Math.PI + Math.PI / 2; models.push({ "show": true, "uuid": "", "name": model.name + "_" + i, "objType": "Lathe", "position": position, "points": [{ "x": 0, "y": 0, "z": 0 }, { "x": 2, "y": 10, "z": 0 }], "style": { "skinColor": 1433087, "side": 2, "opacity": 1 }, "segments": 12, "radialSegments": 12, "closed": true, "phiStart": 0, "phiLength": 6.283185307179586, "showSortNub": 7, "customType1": "", "customType2": "", "animation": null, "dbclickEvents": null, "rotation": [{ "direction": "x", "degree": Math.PI / 2 }, { "direction": "y", "degree": 0 }, { "direction": "z", "degree": rotaiionz }], "radius": null, "scale": { "x": 1, "y": 1, "z": 1 }, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }); modelnames.push(model.name + "_" + i); addModelNames.push(model.name + "_" + i); }
  //載入模型 WT3DObj.commonFunc.loadModelsByJsons(models, { x:
0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true, function () { if (!moveObjModel) { moveObjModel = WT3DObj.commonFunc.findObject("moveObj"); } var _obj = WT3DObj.commonFunc.findObject(model.name); var _objfores = WT3DObj.commonFunc.findObjectsByNames(modelnames); $.each(_objfores, function (_findex, _fobj) { _fobj.visible = false; }); if (!timeLong) { timeLong = 0; } var runTime = 0; for (var i = 0; i < points.length - 1; i++) { (function (_index) {//創建閉包
        
//獲取小節點之間的運動時長
var stepTime = pointlength[_index] / allLength * timeLong; 
setTimeout(
function () {
  //創建路徑運動延遲等待 


new Tn(_obj.geometry.vertices[_index+1]).to({ x: points[_index + 1].x, y: points[_index + 1].y, z: points[_index + 1].z, },
 stepTime).onUpdate(function () { for (var j = _index+1; j < points.length; j++) 
{ _obj.geometry.vertices[j].x = this.x; _obj.geometry.vertices[j].y = this.y;
_obj.geometry.vertices[j].z
= this.z; }; moveObjModel.position.x = this.x;
moveObjModel.position.y
= this.y+30; moveObjModel.position.z = this.z;
_obj.geometry.verticesNeedUpdate
= true; }).start();
setTimeout(
function () { $.each(_objfores,

function (_findex, _fobj) { if (_fobj.name == model.name + "_" + _index) { _fobj.visible = true; } }); }, stepTime / 2); }, runTime); runTime += stepTime+20; })(i); }

// WT3DObj.scene.children[305].geometry.vertices[22].z = 41400 //WT3DObj.scene.children[305].geometry.verticesNeedUpdate = true;
setTimeout(
function () { modelBussiness.Drawing = false; }, timeLong) console.log("drawLine"); }); return addModelNames; }

 

由於篇幅原因,這一課先介紹到這裡 

後面我將繼續講解用webgl 建立 3D隧道、3D橋梁、webgl實現三維隧道橋梁、three.js實現三維隧道橋梁、橋梁隧道三維應用炫酷效果等等

技術交流 [email protected]

交流微信:

    

如果你有什麼要交流的心得 可郵件我或者微我

 

其它相關文章:

如何用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機房管線問題(機房升級版)-第九課(一)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 摘要:本文主要介紹基於OpenHarmony 3.0版本來對接華為雲IoT設備接入IoTDA,以小熊派BearPi-HM_Nano開發板為例,使用huaweicloud_iot_link SDK對接華為雲物聯網平臺的簡單流程。 本文分享自華為雲社區《OpenHarmony3.0如何輕鬆連接華為雲Io ...
  • 這篇文章主要是想要給大家講述一下APP打包上線到APP Store的詳細流程。作為一名開發人員,上架APP是必須要會的,否則出去都不好意思說自己是iOS程式員。而且上線過APP的小伙伴肯定都知道,iOSAPP上線相比安卓的APP上線要複雜麻煩很多,一不小心就會掉進坑裡。所以下麵我將會帶著大家一步一步 ...
  • 項目需要求在移動端H5需要展示一些數據統計的圖表,雖然第一時間想到的是echarts,常用還有Highcharts,D3等,antv家族的圖表UI好看一些,再加上F2是移動端可視化方案於是就選擇F2,打開官網果然眼前一亮F2提供的正能滿足需求,F2官網地址:https://antv.alipay.c ...
  • 每日3題 22 以下代碼執行後,控制臺中的輸出內容為? var a = [1, 2, 3]; a.join = a.shift; console.log(a == 1 && a == 2 && a == 3); 23 以下代碼執行後,控制臺中的輸出內容為? var arr = [0, 1]; arr ...
  • 公共樣式: <style> * { margin: 0; padding: 0; } .has-flex { display: flex; } </style> 垂直居中 子元素左右分佈 css .father-one { width: 100%; height: 200px; background ...
  • vue簡介 1.vue是什麼 一套用於構建用戶界面的漸進式javascript框架 構建用戶界面:拿到的數據轉換為用戶可以看到的數據 漸進式:vue可以自底向上逐層用 從一個輕量小巧的庫逐漸遞進到使用各式各樣的vue插件 2.vue開發者(老二次元了,哈哈) 2013 | 受到Angular的啟發, ...
  • JavaScript 鉤子 點擊打開視頻講解更加詳細 可以在 attribute 中聲明 JavaScript 鉤子 完整案例: <template> <div id="app"> <div id="example-3"> <button @click="show = !show"> Toggle ...
  • 自定義一個類似jquer庫==> Hq庫的具體步驟: // 1.通過$_$('div')方法就可以直接返回一個由Hq構造函數實例化出來的一個對象 // 2.在通過Hq構造函數,獲取你以選擇器為參數的所有節點 // 3.Hq在調用原型上addEles方法將所有的節點,賦值給對應的this的每一項(實例 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...