【问题标题】:IFC.js show/hide layers and componentsIFC.js 显示/隐藏图层和组件
【发布时间】:2022-08-22 17:50:41
【问题描述】:

我在一个角度应用程序中包装了“web-ifc-viewer”。 我在 IFC 内隐藏和显示组件时遇到了一些麻烦。

我已经从这个example 开始,但我需要构建一个通用的 BIM 查看器,所以我不能定义任何类别。

import {AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from \'@angular/core\';
import {IfcViewerAPI} from \"web-ifc-viewer\";
import {Subject, takeUntil} from \"rxjs\";
import {AppThemes, BimViewerService} from \"./bim-viewer.service\";

@Component({
  selector: \'almaviva-bim-viewer\',
  templateUrl: \'./bim-viewer.template.html\',
  styleUrls: [\'./bim-viewer.component.scss\']
})
export class BimViewerComponent implements AfterViewInit {
  @ViewChild(\'viewerContainer\')
  container!: ElementRef;
  viewer?: IfcViewerAPI;
  model: any;
  ifcElement: any;
  loadingValue: number = 0;


  constructor() {
  }

  ngAfterViewInit(): void {
    if (this.container) {
      this.viewer = new IfcViewerAPI({container: this.container.nativeElement});
      this.loadIfc(\'/assets/sample.ifc\');
    }

  }

  private async loadIfc(url: string) {
    try {
      if (this.viewer) {
        await this.viewer.IFC.loader.ifcManager.useWebWorkers(true, \'/assets/IFCWorker.js\');
        await this.viewer.IFC.setWasmPath(\"wasm/\");
        this.viewer.axes.setAxes(1000);
        this.viewer.grid.setGrid(1000);
        await this.viewer.IFC.loader.ifcManager.applyWebIfcConfig({
          USE_FAST_BOOLS: true,
          COORDINATE_TO_ORIGIN: true
        });
        this.viewer.IFC.loader.ifcManager.setOnProgress(
          (event) => {
            this.loadingValue = Math.floor((event.loaded * 100) / event.total);
          }
        )
        this.model = await this.viewer.IFC.loadIfcUrl(url);
        const project = await this.viewer.IFC.getSpatialStructure(this.model.modelID, true);
        this.ifcElement = project.children[0];
        await this.viewer.shadowDropper.renderShadow(this.model.modelID);
      }
    } catch (e) {
      console.log(e);
    }
  }

  async toggleLayer(event: Event, layer: any) {
      const subset = this.viewer?.IFC.loader.ifcManager.createSubset({
      modelID: this.model.modelID,
      ids: [layer.expressID],
      removePrevious: true,
      customID: `${layer.expressID}-custom-id`
    });
    if (subset) {
      this.viewer?.context.getScene().remove(subset);
    }
  }
}

当我切换图层(toggleLayer())时,我从子集中收到一个对象,如下所示

这是我的html

<div>
  <mat-sidenav-container>
    <mat-sidenav mode=\"side\" opened>
      <mat-toolbar>
      <span>
        BIM
      </span>
      </mat-toolbar>
      <mat-progress-bar mode=\"determinate\" [value]=\"loadingValue\"></mat-progress-bar>
      <mat-list role=\"list\" *ngIf=\"!ifcElement\">
          <mat-list-item role=\"listitem\">
            Caricamento IFC in corso...
          </mat-list-item>
      </mat-list>
      <mat-accordion *ngIf=\"ifcElement\">
        <mat-expansion-panel *ngFor=\"let arch of ifcElement?.children || []\">
          <mat-expansion-panel-header>
            <mat-panel-title>
              {{arch.Name?.value || arch.LongName?.value || \'Architettura\'}}
            </mat-panel-title>
          </mat-expansion-panel-header>
          <mat-list role=\"list\">
            <mat-list-item role=\"listitem\" *ngFor=\"let layer of arch.children\">
              <mat-checkbox (click)=\"toggleLayer($event, layer)\">
                {{layer.Name?.value || layer.LongName?.value || \'N/A\'}}
              </mat-checkbox>
            </mat-list-item>
          </mat-list>
        </mat-expansion-panel>
      </mat-accordion>
    </mat-sidenav>
    <mat-sidenav-content>
      <div id=\"viewer-container\" #viewerContainer></div>
      <div class=\"loading-spinner-wrapper\" *ngIf=\"loadingValue!==100\">
        <mat-spinner mode=\"indeterminate\" diameter=\"35\"></mat-spinner>
      </div>
    </mat-sidenav-content>
  </mat-sidenav-container>
</div>

这是浏览器中的最终结果

问题是当我切换图层时没有任何反应。子集日志看起来总是一样的。

    标签: javascript angularjs ifc


    【解决方案1】:

    子集或 createSubset() 需要 customID 以及边 ID 来识别原始模型中创建的子集,而无需您覆盖子集的 customID,它可以是任何字符串,在 example 中它由 category.toString() 定义

    【讨论】:

    • 我添加了一个自定义 id (customID: '${layer.expressID}-custom-id') 作为字符串,但仍然不起作用。什么都没发生。无论我在方法中传递哪个 expressID,子集日志总是相同的。
    【解决方案2】:

    加载 IFC 模型时,它也会添加到场景中。您需要从场景中移除原始模型。

    您无需在每次用户切换图层时创建子集,而是需要在开始时为每个图层创建子集,并在用户切换图层时从场景中添加或删除子集。您可以找到关于 here 的教程、完整示例 here 和工作应用程序 here

    你的逻辑结构应该类似于下面的sn-p。这已从上面链接的最小示例中提取,因此您可能需要对其进行一些调整以适应您的项目:

    import {
        IFCWALLSTANDARDCASE,
        IFCSLAB,
        IFCDOOR,
        IFCWINDOW,
        IFCFURNISHINGELEMENT,
        IFCMEMBER,
        IFCPLATE,
    } from 'web-ifc';
    
    //Sets up the IFC loading
    const ifcModels = [];
    const ifcLoader = new IFCLoader();
    ifcLoader.ifcManager.setWasmPath('../../../');
    ifcLoader.load('../../../IFC/01.ifc', async (ifcModel) => {
        ifcModels.push(ifcModel);
        await setupAllCategories();
    });
    
    
    // Sets up optimized picking
    ifcLoader.ifcManager.setupThreeMeshBVH(
        computeBoundsTree,
        disposeBoundsTree,
        acceleratedRaycast);
    
    // List of categories names
    const categories = {
        IFCWALLSTANDARDCASE,
        IFCSLAB,
        IFCFURNISHINGELEMENT,
        IFCDOOR,
        IFCWINDOW,
        IFCPLATE,
        IFCMEMBER,
    };
    
    // Gets the name of a category
    function getName(category) {
        const names = Object.keys(categories);
        return names.find(name => categories[name] === category);
    }
    
    // Gets all the items of a category
    async function getAll(category) {
        return ifcLoader.ifcManager.getAllItemsOfType(0, category, false);
    }
    
    // Creates a new subset containing all elements of a category
    async function newSubsetOfType(category) {
        const ids = await getAll(category);
        return ifcLoader.ifcManager.createSubset({
            modelID: 0,
            scene,
            ids,
            removePrevious: true,
            customID: category.toString(),
        });
    }
    
    // Stores the created subsets
    const subsets = {};
    
    async function setupAllCategories() {
        const allCategories = Object.values(categories);
        for (let i = 0; i < allCategories.length; i++) {
            const category = allCategories[i];
            await setupCategory(category);
        }
    }
    
    // Creates a new subset and configures the checkbox
    async function setupCategory(category) {
        subsets[category] = await newSubsetOfType(category);
        setupCheckBox(category);
    }
    
    // Sets up the checkbox event to hide / show elements
    function setupCheckBox(category) {
        const name = getName(category);
        const checkBox = document.getElementById(name);
        checkBox.addEventListener('change', (event) => {
            const checked = event.target.checked;
            const subset = subsets[category];
            if (checked) scene.add(subset);
            else subset.removeFromParent();
        });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-10
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多