I'm wrapping "web-ifc-viewer" in an angular application. I've some troubles to hide and show components inside the IFC.
This is my 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 *ngIf="loadingValue!==100">
<mat-spinner mode="indeterminate" diameter="35"></mat-spinner>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
Here the final result in the browser
The issue it's that nothing happens when I toggle the layer. And the subset log looks always the same.
CodePudding user response:
Subsets or createSubset()
requires customID along side ids to identify the created subset from the original model without the customID you are overwriting your subset, it can be any string, in the example its was defined by category.toString()
CodePudding user response:
When you load an IFC model, it also gets added to the scene. You need to remove the original model from the scene.
Instead of creating a subset every time the user toggles a layer, you need to create subsets for each layer in the beginning, and just add or remove the subset from the scene when the user toggles a layer. You can find a tutorial about that here, the full example here and the working app here.
The structure of your logic should be similar to the following snippet. This has been extracted from the minimal example linked above, so probably you need to adapt it a bit to you project:
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();
});
}