基于 WebGL(ThingJS)的社区水电燃气管线 3D 可视化管理演示

2018-12-22 15:42:38 +08:00
 xiangbulala
地下的管线错综复杂如何,图纸并不能完全满足实际需求,我们就用 ThingJS 平台来模拟一个小区水,电,天然气管线演示。

查看 DEMO

 
 
 
第一步,利用 CampusBuilder 搭建模拟场景。CampusBuilder 的模型库有各种各样的模型,使我们搭建出的场景更逼真。使用 CampusBuilde 创建层级,之后再给层级加外立面就出现了当前的效果。详情移步:CampusBuilder3D 场景制作工具 
//加载场景代码
var app = new THING.App({
    // 场景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/管线演示 2",
    //背景设置
    "skyBox": "BlueSky"
});

  

第二步, 初始化摄像机位置,添加四个按钮,并创建四个方法。
app.on('load', function () {
    //摄像机位置初始化
    app.camera.position = [0.4374202706634094, 101.92917348318593, 97.06808820543526];
    app.camera.target = [52.75056074670042, -18.885239034825123, -20.619558480451797];
    new THING.widget.Button('水管演示', water);
    new THING.widget.Button('电线演示', electric);
    new THING.widget.Button('燃气演示', gas);
});

function water() { } function electric() { } function gas() { }

 
第三步,创建管线,我们这里写水管线以后的电线,燃气管线同理。这里简单说一下 PolygonLine,它继承 THING.LineBase,同样有贴图属性,可以自己从本地上传图片至页面资源后使用。
 
var line = null;
function buildLine(points, color) {
    line = app.create({
        type: 'PolygonLine',
        points: points,
        style: {
            color: color,
        }
    });
    line.scrollUV = true;
}

function water() { var waterUnderPoints = []; buildingOpacity(0.3); app.query(/building_0/).forEach( function (parentObj) { var points = []; points.push(parentObj.selfToWorld([5, -0.8, 0])); waterUnderPoints.push(points[0]); for (var i = 3; i <= 24; i += 3) { points.push(parentObj.selfToWorld([5, i, 0])); points.push(parentObj.selfToWorld([5, i, 3])); points.push(parentObj.selfToWorld([-5, i, 3])); points.push(parentObj.selfToWorld([-5, i, -3])); points.push(parentObj.selfToWorld([5, i, -3])); points.push(parentObj.selfToWorld([5, i, 0])); } points.push(parentObj.selfToWorld([5, 24, 0])); buildLine(points, '#0000FF'); } ); waterUnderPoints.push([15.32711, -0.79, -55.655339999999999]); buildLine(waterUnderPoints, '#0000FF'); //renderOrder(); }

function buildingOpacity(num) { app.query("*").forEach(function (obj) { obj.style.opacity = num; }); }

function renderOrder(){ app.query('.PolygonLine').forEach( function (obj) { obj.renderOrder = -10000; } ); }

  

这里用到了两个方法:
1 ) buildingOpacity(num);
这个方法的主要作用就是为了将场景虚化,更好的展示我们的管线。
2 ) renderOrder();
这个我在代码中先注释掉了我们先看一下现在的效果:
 
 
注意:如果没有设置renderOrder();属性的 ,管线的渲染层级没有 building 高 ,就会导致有被 building 遮盖的 PolygonLine 无法正常显示,设置renderOrder();属性后,渲染效果正常
 
 
最后一步,创建出电线以及燃气线
function electric() {
    var electricUnderPoints = [];
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([3, -0.8, 0]));
            electricUnderPoints.push(points[0]);
            for (var i = 3; i <= 24; i += 2.5) {
                points.push(parentObj.selfToWorld([3, i, 0]));
                points.push(parentObj.selfToWorld([-3, i, 2]));
            }
            points.push(parentObj.selfToWorld([3, 24, 0]));
            buildLine(points, '#00FF00');
            console.log(points);
        }
    );
    electricUnderPoints.push([16.690666, -0.79, -55.115203999999999]);
    buildLine(electricUnderPoints, '#00FF00');
    renderOrder();
}

function gas() { var gasUnderPoints = []; buildingOpacity(0.3); app.query(/building_0/).forEach( function (parentObj) { var points = []; points.push(parentObj.selfToWorld([-6.2, -0.3, 0])); gasUnderPoints.unshift(points[0]); for (var i = 3; i <= 24; i += 3) { points.push(parentObj.selfToWorld([-6.2, i, 0])); points.push(parentObj.selfToWorld([-6.2, i, 2])); points.push(parentObj.selfToWorld([6.2, i, 2])); points.push(parentObj.selfToWorld([6.2, i, -2])); points.push(parentObj.selfToWorld([-6.2, i, -2])); points.push(parentObj.selfToWorld([-6.2, i, 0])); } points.push(parentObj.selfToWorld([-6.2, 24, 0])); buildLine(points, '#FF0000'); console.log(points); } ); gasUnderPoints.unshift([22.963023600000003, -0.3, 57.8305784]); buildLine(gasUnderPoints, '#FF0000'); renderOrder(); }

 
 
 附上完整代码,可以直接在ThingJS平台调试
 
//加载场景代码
var app = new THING.App({
    // 场景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/管线演示 2",
    //背景设置
    "skyBox": "BlueSky"
});

app.on('load', function () { //摄像机位置初始化 app.camera.position = [0.4374202706634094, 101.92917348318593, 97.06808820543526]; app.camera.target = [52.75056074670042, -18.885239034825123, -20.619558480451797];

new THING.widget.Button('水管演示', water);
new THING.widget.Button('电线演示', electric);
new THING.widget.Button('燃气演示', gas);

});

function water() { var waterUnderPoints = []; buildingOpacity(0.3); app.query(/building_0/).forEach( function (parentObj) { var points = []; points.push(parentObj.selfToWorld([5, -0.8, 0])); waterUnderPoints.push(points[0]); for (var i = 3; i <= 24; i += 3) { points.push(parentObj.selfToWorld([5, i, 0])); points.push(parentObj.selfToWorld([5, i, 3])); points.push(parentObj.selfToWorld([-5, i, 3])); points.push(parentObj.selfToWorld([-5, i, -3])); points.push(parentObj.selfToWorld([5, i, -3])); points.push(parentObj.selfToWorld([5, i, 0])); } points.push(parentObj.selfToWorld([5, 24, 0])); buildLine(points, '#0000FF'); } ); waterUnderPoints.push([15.32711, -0.79, -55.655339999999999]); buildLine(waterUnderPoints, '#0000FF'); renderOrder(); }

function electric() { var electricUnderPoints = []; buildingOpacity(0.3); app.query(/building_0/).forEach( function (parentObj) { var points = []; points.push(parentObj.selfToWorld([3, -0.8, 0])); electricUnderPoints.push(points[0]); for (var i = 3; i <= 24; i += 2.5) { points.push(parentObj.selfToWorld([3, i, 0])); points.push(parentObj.selfToWorld([-3, i, 2])); } points.push(parentObj.selfToWorld([3, 24, 0])); buildLine(points, '#00FF00'); console.log(points); } ); electricUnderPoints.push([16.690666, -0.79, -55.115203999999999]); buildLine(electricUnderPoints, '#00FF00'); renderOrder(); }

function gas() { var gasUnderPoints = []; buildingOpacity(0.3); app.query(/building_0/).forEach( function (parentObj) { var points = []; points.push(parentObj.selfToWorld([-6.2, -0.3, 0])); gasUnderPoints.unshift(points[0]); for (var i = 3; i <= 24; i += 3) { points.push(parentObj.selfToWorld([-6.2, i, 0])); points.push(parentObj.selfToWorld([-6.2, i, 2])); points.push(parentObj.selfToWorld([6.2, i, 2])); points.push(parentObj.selfToWorld([6.2, i, -2])); points.push(parentObj.selfToWorld([-6.2, i, -2])); points.push(parentObj.selfToWorld([-6.2, i, 0])); } points.push(parentObj.selfToWorld([-6.2, 24, 0])); buildLine(points, '#FF0000'); console.log(points); } ); gasUnderPoints.unshift([22.963023600000003, -0.3, 57.8305784]); buildLine(gasUnderPoints, '#FF0000'); renderOrder(); }

/************************************************************************

  • common */

function buildingOpacity(num) { app.query("*").forEach(function (obj) { obj.style.opacity = num; }); }

function renderOrder(){ app.query('.PolygonLine').forEach( function (obj) { obj.renderOrder = -10000; } ); }

var line = null; function buildLine(points, color) { line = app.create({ type: 'PolygonLine', points: points, style: { color: color, } }); line.scrollUV = true; }

  

 现实中社区管线远比 DEMO 中复杂,开发者可以根据自身业务实际,使用 ThingJS 开发出更多三维可视化应用。
 
11507 次点击
所在节点    JavaScript
55 条回复
randyo
2018-12-22 16:08:01 +08:00
大神啊! Mark
xiangbulala
2018-12-22 16:36:54 +08:00
@randyo 试试 thingjs...简单~~
randyo
2018-12-22 16:52:02 +08:00
@xiangbulala 可视化有什么好的教程吗
xiangbulala
2018-12-22 17:36:36 +08:00
@randyo 3D 的话 three.js 啊,three.js 学起来门槛比较高,也可以试试 thingjs
腾讯课堂教程: https://ke.qq.com/course/list/webgl?tuin=1022909f
优酷搜一下 thingjs 有不少项目案例的视频
momocraft
2018-12-22 17:42:50 +08:00
原来 thingjs 是做这个的, 最近在知乎常看到广告
7gugu
2018-12-22 18:04:32 +08:00
dalao,那个管线的位置要怎么确定?是有软件可以导入还是计算出来?
randyo
2018-12-22 21:36:22 +08:00
@xiangbulala 谢谢了
Geeker
2018-12-22 23:36:11 +08:00
模型建的好
izoabr
2018-12-23 01:47:09 +08:00
demo 是不是挂了?
yesiamloki
2018-12-23 11:58:37 +08:00
请问能做缓冲区分析吗
xiangbulala
2018-12-24 09:55:10 +08:00
@momocraft 还有 V2EX 啊~~
xiangbulala
2018-12-24 09:55:55 +08:00
@Geeker 公开了一批模型可以直接用~
xiangbulala
2018-12-24 09:56:32 +08:00
@yesiamloki 现在还没有专门的这个功能,不过可以通过 API 实现
xiangbulala
2018-12-24 09:59:26 +08:00
@yesiamloki 可以关注一下 thingjs 的[citybuilder]( http://www.thingjs.com/guide/?m=city),3D 城市的可视化工具,目前还比较简单,迭代演进中,欢迎提提意见
xiangbulala
2018-12-24 10:25:44 +08:00
@7gugu 目前管线还没有产品化的工具,项目中有几种实现方式
1、直接 max 中模型建好
2、在搭建工具中摆好点位,程序生成管线
3、按照项目方提供的数据和逻辑程序生成管线
lyseky
2019-01-05 10:32:54 +08:00
想学,国内教程太少了
xiangbulala
2019-01-05 10:42:47 +08:00
@lyseky thingjs 把 three.js 封装了,基本上懂 js 就能搞定,bilibili 有视频教程: https://www.bilibili.com/video/av37691017
eurokingbai2
2019-01-05 11:29:33 +08:00
safari 不显示,chrome 卡到带不动。。
dd0754
2019-01-05 14:05:07 +08:00
卧槽
xieguanglei
2019-01-05 14:42:33 +08:00
难得看到 V2 上有 WebGL 相关的帖子,借楼插个广告吧: https://alibaba.github.io/G3D/cn/

一个小巧精致的材质渲染引擎,和 three.js 的定位有些类似,但是更小,更专注于「渲染」这件事本身,把渲染引擎对 DOM API 的依赖完全地解耦出来了。

目前还处于项目的早期,欢迎对 WebGL 感兴趣,而且有一定技术实力的同学加入一起共建。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/520009

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX