基於WebGL架構的ThingJS可視化平臺—城市地下管線3D可視化

前言
城市管網是城市最重要的公共基礎設施之一,與城市的發展和居民平常生活息息相關。根據不一樣的市政建設,管網分供水、排污、供暖、通訊、電力等多種類別,其普遍分佈遍佈地下。隨着城市發展建設所衍生出空間分佈複雜,變化大,種類繁多等問題,可視化管理是將來發展最好的解決方案。html

Demo預覽json

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70

實現數組

第一步,加載場景app

//加載場景代碼
var app = new THING.App({
    // 場景地址
    "url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Demo_地下管線",
    //背景設置
    "skyBox": "BlueSky"
});

第二步,建立管線以及建立管線信息面板。這裏PolygonLine這種類型咱們在以前的Demo中使用過沒看過的同窗能夠點進去看一下,固然那篇比較糙仍是沒有這篇好看的,能夠兩篇對比一下效果,文章地址。這裏這個renderOrder屬性劃重點,這裏將line的visible屬性設置爲false,當場景加載完成後咱們的管線就已經建立好了爲了能更好的配合咱們的面板因此給他先隱藏掉了,等到開關觸發再對他進行展現。dom

function createLine(name, color, points) {
    var line = null;
    line = app.create({
        type: 'PolygonLine',
        name: name,
        points: points,
        style: {
            color: color,
        },
    });
    line.renderOrder = -10000;
    line.scrollUV = true;
    line.visible = false;
    return line;
}

function createInfo(obj, position) {
    var panel = new THING.widget.Panel({
        template: 'default2',
        width: '120px',
        cornerType: 'polyline'
    })
    var dataObj = {
        name: obj.name,
        color: obj.style.color
    }
    panel.addString(dataObj, 'name').caption('名稱');
    panel.addString(dataObj, 'color').caption('顏色');
    var uiAnchor = app.create({
        type: 'UIAnchor',
        parent: obj,
        element: panel.domElement,
        position: [position[0], -1, position[2]],
        pivot: [-0.2, 2.1]
    });
    return uiAnchor;
}

第三步,建立功能面板以及建立各類類管線。ide

//管線的模擬數據
var dataJson = [{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' },
{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' },
{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' }];
app.on('load', function () {

    // init_camera 
    app.camera.flyTo({
        'position': [-6.199233956799988, 49.47465259648085, 113.74453304853118],
        'target': [-4.002967317456267, 26.055382001258867, 37.65111202780902],
        'time': 2000,
    });


    //建立場景
    var controlPanel = new THING.widget.Panel({
        titleText: '地下管線Demo',
        hasTitle: true, // 是否有標題
        zIndex: 999, // 設置層級
    });
    var data = {
        totalOpen: false,
        viewOpen: false,
        waterOpen: false,
        blowOffOpen: false,
        heatOpen: false
    };

    //openTotal按鈕控制
    var totalOpen = controlPanel.addBoolean(data, 'totalOpen').caption('狀態切換');
    totalOpen.on('change', function (ev) {
        if (ev) {
            //將campus下全部的obj的opacity = 0.4,將name = Uncorrelated 的obj的visiable = false
            app.query('Campus')[0].style.opacity = 0.3;
            app.query('Uncorrelated')[0].visible = false;
        } else {
            //反之初始化
            app.query('Campus')[0].style.opacity = 1;
            app.query('Uncorrelated')[0].visible = true;
        }
    });

    //viewOpen視角控制
    var viewOpen = controlPanel.addBoolean(data, 'viewOpen').caption('2D/3D');
    viewOpen.on('change', function (ev) {
        if (ev) {
            app.camera.viewMode = THING.CameraView.TopView;
        } else {
            app.camera.viewMode = THING.CameraView.Normal;
            app.skyBox = 'BlueSky';
        }
    });

    //waterOpen供水管線 color #0000FF
    var waterOpen = controlPanel.addBoolean(data, 'waterOpen').caption('供水管線');
    var waterLine = [];
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.5, 10], [74.408, -1.5, 10]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.50, 8], [-16.126, -1.50, 8], [-16.126, -1.50, -20], [-10.126, -1.50, -20], [-10.126, -1.50, 8], [74.408, -1.5, 8]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.50, 12], [-45.001, -1.5, 15.755], [-20.736, -1.5, 12], [74.408, -1.5, 12]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[4, -1.5, 46], [4, -1.50, 13.809], [4, -2, 13.809], [4, -2, 6], [4, -1.50, 6], [4, -1.5, -34]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[6, -1.50, 46], [6, -1.50, 13.809], [6, -2, 13.809], [6, -2, 6], [6, -1.50, 6], [6, -1.5, -34]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[8, -1.50, 46], [8, -1.50, 13.809], [8, -2, 13.809], [8, -2, 6], [8, -1.50, 6], [8, -1.5, -34]]));
    createInfo(waterLine[0], dataJson[0],[-28.847, -1.5, 7.957]);
    waterOpen.on('change', function (ev) {
        waterLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });


    //blowOffLine排污管線 color #FFEC8B
    var blowOffOpen = controlPanel.addBoolean(data, 'blowOffOpen').caption('排污管線');
    var blowOffLine = [];
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-2, -3, 46], [-2, -3, -34]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[0, -3, 46], [0, -3, -34]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-61.736, -3, 4], [74.408, -3, 4]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-61.736, -3, 2], [74.408, -3, 2]]));
    createInfo(blowOffLine[0], dataJson[1],[15.299, -1.5, 1.87]);
    blowOffOpen.on('change', function (ev) {
        blowOffLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });

    //heatLine供熱管線 color #FF7F24
    var heatOpen = controlPanel.addBoolean(data, 'heatOpen').caption('供熱管線');
    var heatLine = [];
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-61.736, -2, 0], [65.736, -2, 0], [74.408, -2, -8]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-61.736, -2, -2], [65.736, -2, -2], [74.408, -2, -10]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-4, -2, 46], [-4, -2, -34]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-6, -2, 46], [-6, -2, -34]]));
    createInfo(heatLine[0], dataJson[2],[-6.041, -1.817, 8.865]);
    heatOpen.on('change', function (ev) {
        heatLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });

小結
這個取點座標的方法在上文中沒有告訴你們,只是由於我原來用的方法就比較傻了,我是本身寫了一個全局的singleclick事件,觸發以後打印出當前鼠標的pickedPosistion記錄下來再寫進數組中,這無疑的是很麻煩的操做。
其實ThingJS已經給咱們寫好了一個工具叫作拾取場景座標,他的使用方式下面我會給你們貼幾張圖。整個代碼100+行仍是比較簡潔了(做者能力有限,已經努力精簡了下文能夠給做者多提意見,虛心接受)。最後附上完整代碼!
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70工具

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pb29vb20=,size_16,color_FFFFFF,t_70

完整代碼ui

//加載場景代碼
var app = new THING.App({
    // 場景地址
    "url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Demo_地下管線",
    //背景設置
    "skyBox": "BlueSky"
});

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

    // init_camera 
    app.camera.flyTo({
        'position': [-6.199233956799988, 49.47465259648085, 113.74453304853118],
        'target': [-4.002967317456267, 26.055382001258867, 37.65111202780902],
        'time': 2000,
    });


    //建立場景
    var controlPanel = new THING.widget.Panel({
        titleText: '地下管線Demo',
        hasTitle: true, // 是否有標題
        zIndex: 999, // 設置層級
    });
    var data = {
        totalOpen: false,
        viewOpen: false,
        waterOpen: false,
        blowOffOpen: false,
        heatOpen: false
    };

    //openTotal按鈕控制
    var totalOpen = controlPanel.addBoolean(data, 'totalOpen').caption('狀態切換');
    totalOpen.on('change', function (ev) {
        if (ev) {
            //將campus下全部的obj的opacity = 0.4,將name = Uncorrelated 的obj的visiable = false
            app.query('Campus')[0].style.opacity = 0.3;
            app.query('Uncorrelated')[0].visible = false;
        } else {
            //反之初始化
            app.query('Campus')[0].style.opacity = 1;
            app.query('Uncorrelated')[0].visible = true;
        }
    });

    //viewOpen視角控制
    var viewOpen = controlPanel.addBoolean(data, 'viewOpen').caption('2D/3D');
    viewOpen.on('change', function (ev) {
        if (ev) {
            app.camera.viewMode = THING.CameraView.TopView;
        } else {
            app.camera.viewMode = THING.CameraView.Normal;
            app.skyBox = 'BlueSky';
        }
    });

    //waterOpen供水管線 color #0000FF
    var waterOpen = controlPanel.addBoolean(data, 'waterOpen').caption('供水管線');
    var waterLine = [];
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.5, 10], [74.408, -1.5, 10]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.50, 8], [-16.126, -1.50, 8], [-16.126, -1.50, -20], [-10.126, -1.50, -20], [-10.126, -1.50, 8], [74.408, -1.5, 8]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[-61.736, -1.50, 12], [-45.001, -1.5, 15.755], [-20.736, -1.5, 12], [74.408, -1.5, 12]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[4, -1.5, 46], [4, -1.50, 13.809], [4, -2, 13.809], [4, -2, 6], [4, -1.50, 6], [4, -1.5, -34]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[6, -1.50, 46], [6, -1.50, 13.809], [6, -2, 13.809], [6, -2, 6], [6, -1.50, 6], [6, -1.5, -34]]));
    waterLine.push(createLine('供水管線', 'https://thingjs.com/static/images/poly_line_04.png', [[8, -1.50, 46], [8, -1.50, 13.809], [8, -2, 13.809], [8, -2, 6], [8, -1.50, 6], [8, -1.5, -34]]));
    createInfo(waterLine[0], dataJson[0],[-28.847, 0, 7.957]);
    waterOpen.on('change', function (ev) {
        waterLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });


    //blowOffLine排污管線 color #FFEC8B
    var blowOffOpen = controlPanel.addBoolean(data, 'blowOffOpen').caption('排污管線');
    var blowOffLine = [];
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-2, -3, 46], [-2, -3, -34]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[0, -3, 46], [0, -3, -34]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-61.736, -3, 4], [74.408, -3, 4]]));
    blowOffLine.push(createLine('排污管線', 'https://thingjs.com/static/images/poly_line_03.png', [[-61.736, -3, 2], [74.408, -3, 2]]));
    createInfo(blowOffLine[0], dataJson[1],[15.299, 0, 1.87]);
    blowOffOpen.on('change', function (ev) {
        blowOffLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });

    //heatLine供熱管線 color #FF7F24
    var heatOpen = controlPanel.addBoolean(data, 'heatOpen').caption('供熱管線');
    var heatLine = [];
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-61.736, -2, 0], [65.736, -2, 0], [74.408, -2, -8]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-61.736, -2, -2], [65.736, -2, -2], [74.408, -2, -10]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-4, -2, 46], [-4, -2, -34]]));
    heatLine.push(createLine('供熱管線', 'https://thingjs.com/static/images/poly_line_02.png', [[-6, -2, 46], [-6, -2, -34]]));
    createInfo(heatLine[0], dataJson[2],[-6.041, 0, 8.865]);
    heatOpen.on('change', function (ev) {
        heatLine.forEach(function (obj) {
            obj.visible = ev;
        })
    });

});



function createLine(name, image, points) {
    var line = null;
    line = app.create({
        type: 'PolygonLine',
        name: name,
        points: points,
        image: image
    });
    line.renderOrder = -10000;
    line.scrollUV = true;
    line.visible = false;
    return line;
}

function createInfo(obj,json, position) {
    var panel = new THING.widget.Panel({
        template: 'default2',
        width: '200px',
        cornerType: 'polyline'
    })
    // panel.zIndex = -10000;
    panel.renderOrder = -1000;
    var dataObj = {
        name: ' ',
        id: json.id,
        starId: json.starId,
        stopId: json.stopId,
        starDeep: json.starDeep,
        stopDeep: json.stopDeep,
        material: json.material,
        pressure: json.pressure,
    }
    panel.addString(dataObj, 'name').caption(obj.name);
    panel.addString(dataObj, 'id').caption('管線編號');
    panel.addString(dataObj, 'starId').caption('起點編號');
    panel.addString(dataObj, 'stopId').caption('終點編號');
    panel.addString(dataObj, 'starDeep').caption('起點深度');
    panel.addString(dataObj, 'stopDeep').caption('終點深度');
    panel.addString(dataObj, 'material').caption('材料');
    panel.addString(dataObj, 'pressure').caption('壓力');
    var uiAnchor = app.create({
        type: 'UIAnchor',
        parent: obj,
        element: panel.domElement,
        position: [position[0], 0, position[2]],
        pivot: [-0.2, 2.1]
    });
    return uiAnchor;
}

var dataJson = [{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' },
{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' },
{ 'id': 'BJ002', 'starId': '2TAG001', 'stopId': '2TAG002', 'starDeep': '-1.5', 'stopDeep': '-1.5', 'material': 'ASTNX01', 'pressure': '120' }];
相關文章
相關標籤/搜索