[英]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.