簡體   English   中英

IFC.js 顯示/隱藏圖層和組件

[英]IFC.js show/hide layers and components

我將“web-ifc-viewer”包裝在 angular 應用程序中。 我在 IFC 內隱藏和顯示組件時遇到了一些麻煩。

我從這個例子開始,但我需要構建一個通用的 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() )時,我從這樣的子集中收到 object

子集對象

這是我的 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>

這是瀏覽器中的最終結果

國際金融公司查看器

問題是當我切換圖層時沒有任何反應。 子集日志看起來總是一樣的。

子集或createSubset()需要 customID 和邊 id 來識別從原始 model 中創建的子集,而不需要覆蓋子集的 customID,它可以是任何字符串,在示例中它由category.toString()定義

當您加載 IFC model 時,它也會添加到場景中。 您需要從場景中移除原來的 model。

您無需在每次用戶切換圖層時創建子集,而是需要在開始時為每個圖層創建子集,並在用戶切換圖層時從場景中添加或刪除子集。 您可以在此處找到有關該內容的教程、 此處的完整示例和此處的工作應用程序。

您的邏輯結構應類似於以下代碼段。 這已從上面鏈接的最小示例中提取,因此您可能需要對其進行一些調整以適應您的項目:

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();
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM