Forge


forge Viewer 3(功能)

1.3d\2d获取列表切换

//获取3d,2d列表 
viewerDocument.getRoot().search({'type':'geometry','role':'2d'}); viewerDocument.getRoot().search({'type':'geometry','role':'3d'}); 
//加载模型节点 
var viewables = viewerDocument.getRoot().search({'type':'geometry'}); 
viewer.loadDocumentNode(viewerDocument, viewables[2]);     

2.获取选择节点的数据信息

//得到当前选择集的对象集合(DbId数组)
var sel = NOP_VIEWER.getSelection();
//考察选择集中第一个对象的属性信息 
NOP_VIEWER.getProperties(sel[0],function(objProp){     
    if(objProp){             
        console.log(objProp);
        //遍历每个属性
        for(var index in objProp.properties){                 
            var Prop = objProp.properties[index];
            //console.log('name: ' + Prop.displayName + '    value:    ' +Prop.displayValue);
        }
     }
});

3.聚焦元素、选择元素

viewer.getSelection()   
//测试获取选中的Id viewer.fitToView([19547]) 
//聚焦元素 viewer.getAggregateSelection() 
//获取多个模型 选择的数据  viewer.clearSelection()
//清空选择 viewer.select(9562,viewer.impl.modelQueue().getModels()[0]); 
//选择元素,指定模型 viewer.impl.modelQueue().getModels() 
//获取模型列表     viewer.fitToView([19547],viewer.impl.modelQueue().getModels()[0]) viewer.select([4299,2652],null)

4.获取具体元素集合:

//获取元素 viewer.search('"基本墙"', function(dbids){     console.log(dbids); }, function(error){     console.log(error); }, ['name'] ); //获取元素集合 //返回元素的所有属性 viewer.getProperties(viewer.getSelection()[0],function(pbjProp){ console.log(pbjProp) })  //方法只返回dbid列表的指定属性 viewer.model.getBulkProperties2([3810], ['Category'],function(elements){     console.log(elements);},null) 

5.同步浏览多个视图:

var options = {    viewports: [        function(id) { return id === 2||id === 3; },function(id) { return id === 1; },    ] }; viewer.loadExtension('Autodesk.SplitScreen', options); //获取加载的Model viewer.impl.modelQueue().getModels()[2].id viewer.impl.modelQueue().getModels()[2].getData().urn //添加颜色 this.viewer.setThemingColor( 3964, new THREE.Vector4( 255 / 255, 0, 0, 1 ),viewer.impl.modelQueue().getModels()[0]);

6.元素信息

 it.enumNodeChildren(viewer.getSelection()[0], function(fragId) {   console.log(fragId) });  //获取元素碎片id: viewer.model.getData().instanceTree.enumNodeFragments(viewer.getSelection()[0], function(fragId) {     console.log(fragId); });  var fragProxy = viewer.impl.getFragmentProxy(viewer.model,fragId) fragProxy.frags fragProxy.frags.geoms.geomBoxes   

7.视点保存

 var cam = viewer.getState() viewer.restoreState(cam)

8.剖面

 Vector4 {x: 0, y: 0, z: -1, w: 1} :  负方向 剖的是负方向的元素(去除) w=1 距离00点 1 的位置 (1 往下的都看不到)  Vector4 {x: 0, y: 0, z: 1, w: 1} : 正方向  剖的正方向的元素(去除)  w=1 就是 距离00点 1的位置 即-1 的位置    -1 往上的都看不到 viewer.setCutPlanes( [ new THREE.Vector4( 0, 0, 1,1.575 )] );

9.通过 externalId 查询dbId

  ar extId = 'd4f17bf0-ae11-48af-9184-8555e6c79f66-0002c195' viewer.model.getExternalIdMapping( function(map){ var dbid = map[extId]; console.log(dbid);   viewer.select(dbid);

10.获取元素的父节点

 viewer.model.getData().instanceTree.getNodeParentId(2876) //隐藏父节点 子节点也会隐藏  

11.完全隐藏元素

viewer.impl.visibilityManager.setNodeOff(node, true);

12.更新视图:

viewer.impl.invalidate(true, true, true)

13.更改构件材质:

 //步骤一: 获取元素 fragId  viewer.model.getData().instanceTree.enumNodeFragments(viewer.getSelection()[0], function(fragId) {     console.log(fragId); }); //步骤二:创建材质 var material = new THREE.MeshBasicMaterial(        {color: 0xF5F5F5, transparent: true,opacity: 0.1 }); //步骤三:设置材质 NOP_VIEWER.model.getFragmentList().setMaterial(         fragId, material   );   //步骤一得到的  fragId //步骤四:刷新页面 NOP_VIEWER.impl.invalidate(true,true,true);                

14.获取标高信息

 function onDocumentLoadSuccess(viewerDocument) {    var defaultModel = viewerDocument.getRoot().getDefaultGeometry();    var aecData=Autodesk.Viewing.Document.getAecModelData(defaultModel);     viewer.aecData=aecData;    console.log(aecData)     viewer.loadDocumentNode(viewerDocument, defaultModel); }  

15.去除forgeView中自带的扩展(全部去除)

viewer = new Autodesk.Viewing.GuiViewer3D(htmlDiv,config3d); 改成==> viewer = new Autodesk.Viewing.Viewer3D(htmlDiv,config3d);

0

自定义 Forge Viewer 右键菜单(Context Menu)

autodesk-forgeviewerjavascript

发布于 2017-11-05

img

前阵子有些 Autodesk Forge 圈的朋友们都在询问同一个问题『要怎么在 Viewer 的自带右键菜单上添加自定义项目或是只显示自订义项目』~ 以下将针对『在自带右键菜单上添加自定义项目』和『只显示自订义项目的右键菜单』进行说明。

一、 在自带右键菜单上添加自定义项目:

在自带右键菜单上添加自定义项目是非常容易的,Forge Viewer 提供了一个 API 让使用者可以非常轻易的在自带菜单上添加自个的项目,而你需要做的就是像下面这段代码一样做一个简单的 API 调用。下面这个例子会在右键菜单上添加两个新项目,一个是『改变已选构件的颜色成红色(Override color of selected elements to red)』,另一个是『回复颜色变更(Clear overridden corlor)』:

viewer.registerContextMenuCallback(  'MyChangingColorMenuItems', ( menu, status ) => {
    if( status.hasSelected ) {
        menu.push({
            title: 'Override color of selected elements to red',
            target: () => {
                const selSet = this.viewer.getSelection();
                this.viewer.clearSelection();

                const color = new THREE.Vector4( 255 / 255, 0, 0, 1 );
                for( let i = 0; i < selSet.length; i++ ) {
                    this.viewer.setThemingColor( selSet[i], color );
                }
            }
        });
    } else {
        menu.push({
            title: 'Clear overridden corlor',
            target: () => {
                this.viewer.clearThemingColors();
            }
        });
    }
});

在执行完上面的代码后就在右键菜单上看到这两个项目:

  1. 『改变已选构件的颜色成红色(Override color of selected elements to red)』项目将会在有构件被选中时在菜单上显示:

改变已选构件的颜色成红色

  1. 『回复颜色变更(Clear overridden corlor)』项目会在没有选中任何构件时出现:

回复颜色变更
但一般情况下,我们会将上面的代码放到一个自定义括展里头,让我们可以灵活的使用:

class MyMenuItemExtension extends Autodesk.Viewing.Extension {
  constructor( viewer, options ) {
    super( viewer, options );

    this.onBuildingContextMenuItem = this.onBuildingContextMenuItem.bind( this );
  }

  get menuId() {
    return 'MyColorContextMenu';
  }

  onBuildingContextMenuItem( menu, status ) {
    if( status.hasSelected ) {
      menu.push({
        title: 'Override color of selected elements to red',
        target: () => {
          const selSet = this.viewer.getSelection();
          this.viewer.clearSelection();

          // Change color of selected elements to the red
          const color = new THREE.Vector4( 255 / 255, 0, 0, 1 );
          for( let i = 0; i < selSet.length; i++ ) {
            this.viewer.setThemingColor( selSet[i], color );
          }
        }
      });

    } else {
      menu.push({
        title: 'Clear overridden corlor',
        target: () => {
          this.viewer.clearThemingColors();
        }
      });
    }
  }

  load() {
    // Add my owned menu items
    this.viewer.registerContextMenuCallback(
      this.menuId,
      this.onBuildingContextMenuItem
    );

    return true;
  }

  unload() {
    // Remove all menu items added from this extension
    this.viewer.unregisterContextMenuCallback( this.menuId );

    return true;
  }
}

Autodesk.Viewing.theExtensionManager.registerExtension( 'DemoMenuExtension', MyMenuItemExtension );

二、 只显示自订义项目的右键菜单:

如果上头的代码与你的需求不符合,你可以考虑编写一自订义的右键菜单,一样的他也不会太困难。现在举个例子来说明,像现在如果我想让自带右键菜单上除了自带项目外,还会在点击到不同构件时显示不同的项目;我需要做的就是通过继承 Autodesk.Viewing.Extensions.ViewerObjectContextMenu 和加入 hitTest 相关的逻辑到自定义右键菜单的 buildMenu 函数,就像下面这样:

class MyContextMenu extends Autodesk.Viewing.Extensions.ViewerObjectContextMenu {
  constructor( viewer ) {
    super( viewer );
  }

  isWall( dbId ) {
    //Logics for determining if selected element is wall or not.
    return new Promise( ( resolve, reject ) => {
        $.get(
            '/api/walls/' + dbId,
            ( response ) => {
                if( response && response.id != 0 ) {
                    return resolve( true );
                }
                return resolve( false );
            }
        )
        .error( ( error ) => reject( error ) );
    });
  }

  async buildMenu( event, status ) {
    // Get defulat menu items from the super class
    const menu = super.buildMenu( event, status );

    // Do hitTest to get dbIds
    const viewport = this.viewer.container.getBoundingClientRect();
    const canvasX = event.clientX - viewport.left;
    const canvasY = event.clientY - viewport.top;

    const result = this.viewer.impl.hitTest( canvasX, canvasY, false );

    if( !result || !result.dbId ) return menu;

    let isWall = false;
    try {
        isWall = await this.isWall( result.dbId );
    } catch ( error ) {
        isWall = false;
    }

    if( status.hasSelected && isWall ) {
      menu.push({
          title: 'Show current surface temperature map',
          target: () => {
              $.post(
                    '/api/walls/temperature',
                    ( response ) => {
                        ViewerUtil.showWallTemperatureMap( response.values );
                    }
              );
          }
      });
    }

    return menu;
   }

   /**
    * @override
    */
   async show( event ) {
    const numSelected = this.viewer.getSelectionCount();
    const visibility = this.viewer.getSelectionVisibility();
    const status = {
      numSelected: numSelected,
      hasSelected: ( numSelected > 0 ),
      hasVisible: visibility.hasVisible,
      hasHidden: visibility.hasHidden
    };
    const menu = await this.buildMenu( event, status );

    this.viewer.runContextMenuCallbacks( menu, status );

    if( menu && menu.length > 0 ) {
      this.contextMenu.show( event, menu );
    }
   }
}

class MyContextMenuExtension extends Autodesk.Viewing.Extension {
    constructor( viewer, options ) {
        super( viewer, options );
    }

    load() {
        // Use my owned context menu.
        this.viewer.setContextMenu( new MyContextMenu( this.viewer ) );
        return true;
    }

    unload() {
        // Restore default context menu
        this.viewer.setContextMenu( new Autodesk.Viewing.Extensions.ViewerObjectContextMenu( this.viewer ) );
        return true;
    }
}

Autodesk.Viewing.theExtensionManager.registerExtension( 'DemoWallMenuExtension', MyContextMenuExtension );

这样子就会在点击到墙构件显示这个项目『Show current surface temperature map』:
图片描述

相反的,如果你不想显示菜单上自带的项目,你可以改成继承 Autodesk.Viewing.UI.ObjectContextMenu。但你点击到墙构件的时候就只会显示『Show current surface temperature map』这个项目,就像下面这个样子:

class MyContextMenu extends Autodesk.Viewing.Extensions.ObjectContextMenu {
  constructor( viewer ) {
    super( viewer );
  }

  isWall( dbId ) {
    //Logics for determining if selected element is wall or not.
    return new Promise( ( resolve, reject ) => {
        $.get(
            '/api/walls/' + dbId,
            ( response ) => {
                if( response && response.id != 0 ) {
                    return resolve( true );
                }
                return resolve( false );
            }
        )
        .error( ( error ) => reject( error ) );
    });
  }

  async buildMenu( event, status ) {
    // Get defulat menu items from the super class
    let menu = super.buildMenu( event, status );
    
    if( !menu )
        menu = [];

    // Do hitTest to get dbIds
    const viewport = this.viewer.container.getBoundingClientRect();
    const canvasX = event.clientX - viewport.left;
    const canvasY = event.clientY - viewport.top;

    const result = this.viewer.impl.hitTest( canvasX, canvasY, false );

    if( !result || !result.dbId ) return menu;

    let isWall = false;
    try {
        isWall = await this.isWall( result.dbId );
    } catch ( error ) {
        isWall = false;
    }

    if( status.hasSelected && isWall ) {
      menu.push({
          title: 'Show current surface temperature map',
          target: () => {
              $.post(
                    '/api/walls/temperature',
                    ( response ) => {
                        ViewerUtil.showWallTemperatureMap( response.values );
                    }
              );
          }
      });
    }

    return menu;
   }

   /**
    * @override
    */
   async show( event ) {
    const numSelected = this.viewer.getSelectionCount();
    const visibility = this.viewer.getSelectionVisibility();
    const status = {
      numSelected: numSelected,
      hasSelected: ( numSelected > 0 ),
      hasVisible: visibility.hasVisible,
      hasHidden: visibility.hasHidden
    };
    const menu = await this.buildMenu( event, status );

    this.viewer.runContextMenuCallbacks( menu, status );

    if( menu && menu.length > 0 ) {
      this.contextMenu.show( event, menu );
    }
   }
}

class MyContextMenuExtension extends Autodesk.Viewing.Extension {
    constructor( viewer, options ) {
        super( viewer, options );
    }

    load() {
        // Use my owned context menu.
        this.viewer.setContextMenu( new MyContextMenu( this.viewer ) );
        return true;
    }

    unload() {
        // Restore default context menu
        this.viewer.setContextMenu( new Autodesk.Viewing.Extensions.ViewerObjectContextMenu( this.viewer ) );
        return true;
    }
}

Autodesk.Viewing.theExtensionManager.registerExtension( 'DemoWallMenuExtension', MyContextMenuExtension );

图片描述


文章作者: shipengzhen
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shipengzhen !
 上一篇
Java面向对象设计之策略模式 Java面向对象设计之策略模式
一、模式动机完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。在软件开发中也常常遇到类似的情况,实现某一个功能有多个途径,此时可以使用一种设计模式来使得系统可以灵活地
2018-09-14
下一篇 
javaScript javaScript
初识javaScriptjs组成1.ecmaScript 2.dom 3.bom javascript语法js函数 isNaN 判断是否是数字 var x = 1000 / "Apple"; isNaN(x); // 返回 true v
2018-09-14
  目录