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 · 11498 次点击
    这是一个创建于 2189 天前的主题,其中的信息可能已经有所发展或是发生改变。
    地下的管线错综复杂如何,图纸并不能完全满足实际需求,我们就用 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.com/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   ·   实用小工具   ·   3405 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 49ms · UTC 11:00 · PVG 19:00 · LAX 03:00 · JFK 06:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.