油田系统三维布局可视化解决方案

栏目: IT技术 · 发布时间: 4年前

内容简介:最近和一家公司在谈一个项目合作,他们公司主要是做油田相关设备的,比如油罐车、压力车、泵车等。我的印象中只要和石油相关的企业,就感觉和钱挨得好近,:smile: 。他们老板看了我们公司的三维产品后,大为赞叹。 惊呼,我们油田的管理最好也能上一套这样的三维系统。

最近和一家公司在谈一个项目合作,他们公司主要是做油田相关设备的,比如油罐车、压力车、泵车等。

我的印象中只要和石油相关的企业,就感觉和钱挨得好近,:smile: 。

他们老板看了我们公司的三维产品后,大为赞叹。 惊呼,我们油田的管理最好也能上一套这样的三维系统。

油田行业的三维可视化项目,我们之前没有做过相关的行业,但是在三维可视化方面,我们经验还是挺多的,比如数据中心、医院、学校等三维可视化项目,还包括智慧园区、智慧城市、智慧小镇的方向的等三维可视化。

下面先上几张三维可视化的图瞅瞅:

油田系统三维布局可视化解决方案

油田系统三维布局可视化解决方案

油田系统三维布局可视化解决方案

虽然我们没有直接做过油田的三维可视化,但是有了以上三维方案的技术积累,这事做起来就不会太难。

其实客户的需求,并不是就某个油田场景进行三维可视化的场景搭建。而是要做一个油田三维的布局工具,通过布局工具,可以自由搭建不同的油田场景。

这比直接搭建一个三维的场景要难许多。

所谓万事开头难,难在不开头。 天下事有难易乎,干就完了。

在商务人员和客户确立合同,正式立项后, 我们的设计小姐姐,开发小哥哥,都各司其职,下边就讲一下项目的大概内容。

搭建模型库

第一步要做的就是建模,设计组使用3D建模 工具 3d max或者c4d 进行油田设备模型的建模。建模后,导出后缀为obj或者gltf格式文件,这两种格式是我们三维渲染引擎支持的最好的文件格式。

建模后的所有模型文件,最终会放到后端的模型库,模型库的管理目录如下图所示:

油田系统三维布局可视化解决方案

加载模型

加载模型可使用引擎模型的加载函数进行模型加载,比如obj模型加载,示例代码如下:

new mono.OBJMTLLoader().load( 'yaliche.obj', 'yaliche.mtl', '',  (node)=> {
    node.type = 'obj';
    box.addByDescendant(node);
  },
);

上面加载了一个压力车的模型,加载模型是一个异步的过程,所以会有一个回调函数,加载完成之后,在回调函数中,把模型文件生成的三维对象加入到场景容器box之中,加入之后,场景中就会显示我们的三维对象,如下图所示:

油田系统三维布局可视化解决方案

搭建编辑器框架

在和设计组、开发组一起探讨之后,我们编辑器的框架和视图初步设计出来了,大致样子如下:

油田系统三维布局可视化解决方案

视图左上角是我们的logo,上方是工具栏。左侧分为场景区和组件区,场景区是创建三维场景的列表,组件区主要是模型列表,同时还有些echarts图表组件。

中间部分是三维场景呈现区。

对于这个页面布局,我想不用做太多技术上的阐述,基本上会一点前端开发的人员都可以实现类似的效果。

<div>
      <div id="leftTreeWrap">
        <div>
          <div id="leftTree">
            <div>
              <div>
                场景
              </div>
              
            </div>
            <div>
              组件
            </div>

            <div id="modelGroupWrap">
              <!-- <div id="groundWrap">
                <h2><span>场景模型</span></h2>
                <div id="groundTree">
                  <div></div>
                </div>
              </div> -->
            </div>
          </div>
        </div>
      </div>
      <div>
        <div>
          <div></div>
        </div>
        <div tabindex="0">
          <canvas id="monoCanvas"></canvas>
        </div>
      </div>

左侧边栏包括两个部分,一个是场景列表,一个是模型列表。场景列表是树组件,模型列表是手风琴组件,如下图所示:

油田系统三维布局可视化解决方案

模型列表的创建过程是这样的,首先从后端获取所有的模型:

getComponentTree({ params: { owner: user } }, '同步云端组件树失败').then((res) => {
      if (res) {
        const treeData = res.data.data;
        treeData.forEach(({ data }) => {
          this.appendModelBtn(data, true);
        });
        // this.renderTreeDom(res.data.data);
      }
    });

通过每个模型创建模型对于的button,函数是appendModelBtn,如下:

appendModelBtn(modelData, isNew) {
    const domWrap = this.groupDom[modelData.group];
    if (!domWrap) {
      console.log('缺少该类型对应的组', modelData.group);
      if (modelData.category === 'skyBox') {
        modelData.isNew = true;
        skyData.push({ modelData });
      }
    } else {
      domWrap.querySelector('.tree-wrap').appendChild(this.createModelBtnDom(modelData, isNew));
    }
  }

需要注意的,每个模型按钮都需要有drag and drop的功能。在模型按钮上需要监听drag 或者dragstart事件,这个被封装到一个独立的类Dragger.js里面,在该类中专门处理了dragstart事件:

addDragger(parent, subClass, option) {
    parent.addEventListener('dragstart', (e) => {
      let target = null;
      //  拿到冒泡的所有元素
      const path = eventPath(e);
      for (let i = 0; i < path.length; i += 1) {
        if (path[i].classList && path[i].classList.contains(subClass)) {
          target = path[i];
          break;
        }
      }
...
}

中间区域是三维呈现区域。 首先创建一个Network3D对象,Network3D对象是封装的三维呈现页面,其底层是由canvas组成的,并使用webgl技术进行三维渲染。下面是创建Network3D的代码:

const network = new mono.Network3D(box, null, 'monoCanvas');
    network.mode = 'editor';
    window.network = network; // todo
    this.network = network;
    network.bindApp(this);
    network.setRenderSelectFunction(() => false);
    make.Default.path = './static/myModellib/';

    network.setClearColor(0, 0, 0);
    network.setClearAlpha(0);

创建对象之后,让network可以和中间区域的大小自适应:

mono.Utils.autoAdjustNetworkBounds(
      network,
      document.querySelector('.app'),
      'clientWidth',
      'clientHeight',
    );

其中network上的box对象用于管理要加载的三维对象模型。前面说过在模型列表上增加了drag事件,模型列表上的模型,通过拖拽可以添加到network对象上去,因此在network上面也需要添加对应的事件来添加对象:

onup: (e) => {
        if (!this.sceneTree.senceId && !window.debug) {
          layui.layer.msg('请先创建或选择场景', {
            time: 2000,
          });
          return;
        }
        //  鼠标不在画布内的时候不创建
        if (isPosInCanvas(network, e)) {
          network.createElement({
            e,
            configString,
            senceId: this.sceneTree.senceId,
          });
        }
      },

当模型从左侧模型列表拖拽到network对象后,鼠标mouseup事件后,创建模型实例:

network.createElement({
            e,
            configString,
            senceId: this.sceneTree.senceId,
          });

到目前为止,已经完成了整个模型列表加载,模型拖拽创建模型实例的过程。 比如最终通过拖拽的油田场景如下所示:

油田系统三维布局可视化解决方案

在3d场景中,需要调整三维模型的位置、旋转角度和缩放比例,可以通过属性面板来调整:

油田系统三维布局可视化解决方案

也可以通过三维编辑功能直接在三维场景中对模型进行调整标记,要使用调整编辑功能,只需要加入如下这行代码即可:

const editInteraction = new mono.EditInteraction(network);
    editInteraction.setScaleable(false);
    editInteraction.setRotateable(false);
    editInteraction.setTranslateable(true);
    editInteraction.setDefaultMode('');

    network.setInteractions([...network.getInteractions(), editInteraction]);

EditInteraction类 用于调整模型的位置、旋转角度和缩放比例。 通过键盘可以调整EditInteraction当前要调整的是那个属性:

case 82: // r 在有选中element时,切换操作为旋转
          if (this.network.getIsMonoElement(this.network.currComponent)) {
            const editInteraction = this.network.getInteractions()[2];
            editInteraction.setScaleable(false);
            editInteraction.setRotateable(true);
            editInteraction.setTranslateable(false);
          }
          break;
        case 84: // t 在有选中element时,切换操作为移动
          if (this.network.getIsMonoElement(this.network.currComponent)) {
            const editInteraction = this.network.getInteractions()[2];
            editInteraction.setScaleable(false);
            editInteraction.setRotateable(false);
            editInteraction.setTranslateable(true);
          }
          break;
        case 89: // y 在有选中element时,切换操作为缩放
          if (this.network.getIsMonoElement(this.network.currComponent)) {
            const editInteraction = this.network.getInteractions()[2];
            editInteraction.setScaleable(true);
            editInteraction.setRotateable(false);
            editInteraction.setTranslateable(false);
          }
          break;

r键切换为旋转角度的调整:

油田系统三维布局可视化解决方案

t键切换为位置的调整:

油田系统三维布局可视化解决方案

y键切换为缩放的调整:

油田系统三维布局可视化解决方案

拖拽创造场景之后,每个对象还可以进行实时数据的对接,对接后呈现的效果如下:

油田系统三维布局可视化解决方案

在完成场景的创建和数据的对接之后,便可以发布场景,点击工具栏的预览按钮,即可以完成场景的发布和预览。上一张最终发布的效果图如下:

油田系统三维布局可视化解决方案

有兴趣获取编辑器的,请发邮件到:

terry.tan@servasoft.com

欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、 程序员 职业规划有浓厚兴趣。

油田系统三维布局可视化解决方案


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pattern Recognition and Machine Learning

Pattern Recognition and Machine Learning

Christopher Bishop / Springer / 2007-10-1 / USD 94.95

The dramatic growth in practical applications for machine learning over the last ten years has been accompanied by many important developments in the underlying algorithms and techniques. For example,......一起来看看 《Pattern Recognition and Machine Learning》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具