基于 WebGL(ThingJS)的社区水电燃气管线 3D 可视化管理演示 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
xiangbulala
V2EX    Javascript

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

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

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

    目前还处于项目的早期,欢迎对 WebGL 感兴趣,而且有一定技术实力的同学加入一起共建。
    xiangbulala
        21
    xiangbulala  
    OP
       2019-01-05 15:20:47 +08:00
    @eurokingbai2。。。啥配置...
    ala2008
        22
    ala2008  
       2019-01-05 15:28:16 +08:00
    @xieguanglei 已 star :smile:
    hello20019
        23
    hello20019  
       2019-01-05 15:53:06 +08:00 via iPhone
    手机上打不开…… chrome 和 safari 都会页面崩溃
    xiangbulala
        24
    xiangbulala  
    OP
       2019-01-05 16:03:13 +08:00
    @hello20019 我试了下魅族自带浏览器打开没啥问题
    hello20019
        25
    hello20019  
       2019-01-05 16:09:01 +08:00 via iPhone
    dk7952638
        26
    dk7952638  
       2019-01-05 16:42:28 +08:00
    ThingJS 有开源替代品么?
    xiangbulala
        27
    xiangbulala  
    OP
       2019-01-05 16:51:47 +08:00
    @dk7952638 (〃''〃)现在 thingjs 不开源,不过除了项目发布都是免费的,收费主要是去 logo,离线部署
    xiangbulala
        28
    xiangbulala  
    OP
       2019-01-05 16:52:31 +08:00
    @hello20019 嗯 确实 iPhone 上有些问题,会尽快修复
    pinghai
        29
    pinghai  
       2019-01-05 18:29:02 +08:00
    试用试用 ThingJS,不断提升国内 WebGL 引擎水平啊..
    lyseky
        30
    lyseky  
       2019-01-05 18:40:38 +08:00 via Android
    @xiangbulala 好,今年学一下
    but0n
        31
    but0n  
       2019-01-05 18:43:00 +08:00 via iPhone
    @xieguanglei 不依赖 DOM API 是什么意思?
    majilei
        32
    majilei  
       2019-01-05 19:05:23 +08:00 via Android
    不错
    xieguanglei
        33
    xieguanglei  
       2019-01-05 19:52:15 +08:00
    @but0n 就是框架本身不会调用 DOM API,只需要初始化的时候注入一个具有 getContext 方法的对象(可以是 Canvas
    也可以是你自己的实现),框架不负责加载图片、模型,适应窗口尺寸变化等等。这么做的原因,是因为我们需要可以跑在 [GCanvas]( https://github.com/alibaba/GCanvas) 上(进而可以跑在 ReactNative 或 Weex 上),而且这样做这个渲染引擎也会更小,更纯粹于「渲染」。
    jfhy0901
        34
    jfhy0901  
       2019-01-05 19:59:14 +08:00 via Android
    最近正好需要这个,有时间研究一下!先收藏了
    but0n
        35
    but0n  
       2019-01-05 22:10:03 +08:00 via iPhone
    @xieguanglei DOM 也有一些可以利用的功能,Aframe 的 ECS 就有依赖 DOM 树
    circleee
        36
    circleee  
       2019-01-06 15:16:48 +08:00
    你们到底是怎么收费呀?
    xiangbulala
        37
    xiangbulala  
    OP
       2019-01-08 10:33:17 +08:00
    @circleee 场景搭建的组件都是免费使用的(包括 campusbuilder 原模模搭,citybuilder 城市搭建工具、chartbuilder 大屏图表搭建工具),在线开发演示三维场景也是免费的,只有成为商业开发者(离线演示场景)、在线项目发布(去 logo )、项目离线部署才收费
    STRRL
        38
    STRRL  
       2019-01-08 12:32:17 +08:00 via Android
    emmm 好像已经有成熟的 2b 公司在做这个了 云烟好像有一套这个
    Nicoco
        39
    Nicoco  
       2019-01-08 13:16:34 +08:00
    老哥稳
    xiangbulala
        40
    xiangbulala  
    OP
       2019-01-08 13:56:08 +08:00
    @STRRL 云烟?生产香烟的云烟么
    gjx870327
        41
    gjx870327  
       2019-01-08 13:58:05 +08:00
    不开源 有什么好说的 =。=||
    ecmascript2020
        42
    ecmascript2020  
       2019-01-08 14:31:42 +08:00
    神奇 公交车站台那边那个女的还会动
    xiangbulala
        43
    xiangbulala  
    OP
       2019-01-08 15:08:33 +08:00
    @ecmascript2020 哈哈哈你不说我都没发现,那个模型带动画
    STRRL
        44
    STRRL  
       2019-01-08 15:58:32 +08:00
    @xiangbulala 对 云南烟草公司
    lovelybear
        45
    lovelybear  
       2019-01-08 16:04:08 +08:00
    其实还不如拿 Unity 做,最后导出成 webgl 的
    xiangbulala
        46
    xiangbulala  
    OP
       2019-01-08 16:43:09 +08:00
    @lovelybear 主要面对只有前端工程师,不熟悉 webgl 的用户,降低 3D 可视化应用开发门槛
    blockmin
        47
    blockmin  
       2019-01-08 17:22:37 +08:00
    我前东家就是搞 3D 可视化的,但我在运营部门,完全不懂
    xiangbulala
        48
    xiangbulala  
    OP
       2019-01-08 17:31:12 +08:00
    @blockmin 哪家啊?~
    yao978318542
        49
    yao978318542  
       2019-01-08 17:59:09 +08:00
    提一个小 BUG 那几个演示按钮 重复点击的话 是不是会重复加载啊 而且好像不能取消
    qiuyk
        50
    qiuyk  
       2019-01-08 18:19:34 +08:00
    这不就是 BIM...么
    blockmin
        51
    blockmin  
       2019-01-08 21:46:08 +08:00
    @xiangbulala 优锘科技
    xiangbulala
        52
    xiangbulala  
    OP
       2019-01-09 09:06:07 +08:00
    @yao978318542 主要是...没做
    xiangbulala
        53
    xiangbulala  
    OP
       2019-01-09 09:07:34 +08:00
    @qiuyk 可以理解是轻量的 bim,偏向应用于可视化管理而不是建造过程
    xiangbulala
        54
    xiangbulala  
    OP
       2019-01-09 09:07:52 +08:00
    @blockmin 就是优锘科技哈哈哈
    yao978318542
        55
    yao978318542  
       2019-01-09 09:11:37 +08:00
    挺不错了 厉害
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3759 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 115ms UTC 00:12 PVG 08:12 LAX 17:12 JFK 20:12
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86