import * as THREE from 'three'; import * as OBC from '@thatopen/components'; import * as OBF from '@thatopen/components-front'; import * as WEBIFC from 'web-ifc'; /** * @namespace BIM */ const BIM = {}; BIM.clipper = undefined; /** * * @param {HTMLElement} container The scene container element * @returns {object} {components, world} */ BIM.init = function (container) { const components = new OBC.Components(); const worlds = components.get(OBC.Worlds); const world = worlds.create(); world.scene = new OBC.SimpleScene(components); world.renderer = new OBC.SimpleRenderer(components, container); world.camera = new OBC.SimpleCamera(components); // Starts the app and updates components at 60 fps components.init(); this.world = world; this.components = components; } /** * @param {HTMLElement} container The scene container element */ BIM.createScene = function (container) { this.init(container); // Add a grid to the scene const grids = this.components.get(OBC.Grids); const grid = grids.create(this.world); // (zoom_level, position) this.world.camera.controls.setLookAt(15, 15, 15, 0, 0, 0); this.world.scene.setup(); } /** * Enable the clipping plane */ BIM.activateClipper = function () { const casters = this.components.get(OBC.Raycasters); casters.get(this.world); // Enable plane clipper const clipper = this.components.get(OBC.Clipper); clipper.enabled = true; clipper.create(this.world); clipper.visible = true; clipper.config.color = new THREE.Color('#eaeaea'); clipper.config.size = 10; BIM.clipper = clipper; } /** * Delete a selected clipping plane */ BIM.deleteClipper = function () { if (this.clipper.enabled) { this.clipper.delete(this.world); } } /** * @todo Serve web-ifc.wasm locally via AJAX * @param {ArrayBuffer} buffer The uploaded IFC file * @param {string} name The filename to be used as the model's name * @returns {OBC.FragmentsGroup} model */ BIM.loadIfc = async function (buffer, name) { if (this.fragments) { this.fragments.dispose(); } const fragments = this.components.get(OBC.FragmentsManager); const fragmentIfcLoader = this.components.get(OBC.IfcLoader); const classifier = this.components.get(OBC.Classifier); // NOTE: loads web-ifc WASM from https://unpkg.com/web-ifc@0.0.53/ await fragmentIfcLoader.setup(); /* fragmentIfcLoader.settings.wasm = { path: "./vendor/web-ifc/", absolute: false }; */ // Excludes IFC categories from the fragment const excludedCats = [ WEBIFC.IFCTENDONANCHOR, WEBIFC.IFCREINFORCINGBAR, WEBIFC.IFCREINFORCINGELEMENT, ]; for (const cat of excludedCats) { fragmentIfcLoader.settings.excludedCategories.add(cat); } fragmentIfcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true; fragmentIfcLoader.settings.webIfc.OPTIMIZE_PROFILES = true; const model = await fragmentIfcLoader.load(buffer); model.name = name; this.world.scene.three.add(model); // To actually add the model to the scene... for (const fragment of model.items) { this.world.meshes.add(fragment.mesh); } classifier.byEntity(model); const entities = classifier.list.entities; // Useful? this.fragments = fragments; this.model = model; console.log(entities); return model; } /** * @param {OBC.FragmentsGroup} model The loaded IFC model */ BIM.setupHighligther = async function (model) { const world = this.world; const indexer = this.components.get(OBC.IfcRelationsIndexer); await indexer.process(model); let highlighter = null; if (!this.highlighter) { highlighter = this.components.get(OBF.Highlighter); highlighter.setup({ world }); } else { highlighter = this.highlighter; } const li = document.querySelector('#selected-prop'); highlighter.events.select.onHighlight.add(async (property) => { const set = property[Object.keys(property)[0]] const expressID = Array.from(set.entries())[0][0]; let testProp = await model.getProperties(Number.parseInt(expressID)); // BAD just for testing if (testProp !== null) { li.innerHTML = `