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