import { IFCRELAGGREGATES, IFCRELCONTAINEDINSPATIALSTRUCTURE, IFCRELDEFINESBYPROPERTIES, IFCRELDEFINESBYTYPE, IFCPROJECT, IfcAPI, } from "./ifc/web-ifc-api.js"; import { BufferAttribute, BufferGeometry, Mesh, Matrix4, Color, MeshLambertMaterial, DoubleSide, Group, Loader, FileLoader, } from "../../../build/three.module.js"; import { BufferGeometryUtils } from "../utils/BufferGeometryUtils.js"; const IdAttrName = "expressID"; const merge = (geoms, createGroups = false) => { return BufferGeometryUtils.mergeBufferGeometries(geoms, createGroups); }; const newFloatAttr = (data, size) => { return new BufferAttribute(new Float32Array(data), size); }; const newIntAttr = (data, size) => { return new BufferAttribute(new Uint32Array(data), size); }; const DEFAULT = "default"; const PropsNames = { aggregates: { name: IFCRELAGGREGATES, relating: "RelatingObject", related: "RelatedObjects", key: "children", }, spatial: { name: IFCRELCONTAINEDINSPATIALSTRUCTURE, relating: "RelatingStructure", related: "RelatedElements", key: "children", }, psets: { name: IFCRELDEFINESBYPROPERTIES, relating: "RelatingPropertyDefinition", related: "RelatedObjects", key: "hasPsets", }, type: { name: IFCRELDEFINESBYTYPE, relating: "RelatingType", related: "RelatedObjects", key: "hasType", }, }; class IFCParser { constructor(state) { this.currentID = -1; this.state = state; } async parse(buffer) { if (this.state.api.wasmModule === undefined) await this.state.api.Init(); this.currentID = this.newIfcModel(buffer); return this.loadAllGeometry(); } initializeMeshBVH(computeBoundsTree, disposeBoundsTree, acceleratedRaycast) { this.computeBoundsTree = computeBoundsTree; this.disposeBoundsTree = disposeBoundsTree; this.acceleratedRaycast = acceleratedRaycast; this.setupThreeMeshBVH(); } setupThreeMeshBVH() { if ( !this.computeBoundsTree || !this.disposeBoundsTree || !this.acceleratedRaycast ) return; BufferGeometry.prototype.computeBoundsTree = this.computeBoundsTree; BufferGeometry.prototype.disposeBoundsTree = this.disposeBoundsTree; Mesh.prototype.raycast = this.acceleratedRaycast; } applyThreeMeshBVH(geometry) { if (this.computeBoundsTree) geometry.computeBoundsTree(); } newIfcModel(buffer) { const data = new Uint8Array(buffer); const modelID = this.state.api.OpenModel(data); this.state.models[modelID] = { modelID, mesh: {}, items: {}, types: {}, }; return modelID; } loadAllGeometry() { this.saveAllPlacedGeometriesByMaterial(); return this.generateAllGeometriesByMaterial(); } generateAllGeometriesByMaterial() { const { geometry, materials } = this.getGeometryAndMaterials(); this.applyThreeMeshBVH(geometry); const mesh = new Mesh(geometry, materials); mesh.modelID = this.currentID; this.state.models[this.currentID].mesh = mesh; return mesh; } getGeometryAndMaterials() { const items = this.state.models[this.currentID].items; const mergedByMaterial = []; const materials = []; for (let materialID in items) { materials.push(items[materialID].material); const geometries = Object.values(items[materialID].geometries); mergedByMaterial.push(merge(geometries)); } const geometry = merge(mergedByMaterial, true); return { geometry, materials, }; } saveAllPlacedGeometriesByMaterial() { const flatMeshes = this.state.api.LoadAllGeometry(this.currentID); for (let i = 0; i < flatMeshes.size(); i++) { const flatMesh = flatMeshes.get(i); const placedGeom = flatMesh.geometries; for (let j = 0; j < placedGeom.size(); j++) { this.savePlacedGeometry(placedGeom.get(j), flatMesh.expressID); } } } savePlacedGeometry(placedGeometry, id) { const geometry = this.getBufferGeometry(placedGeometry); geometry.computeVertexNormals(); const matrix = this.getMeshMatrix(placedGeometry.flatTransformation); geometry.applyMatrix4(matrix); this.saveGeometryByMaterial(geometry, placedGeometry, id); } getBufferGeometry(placed) { const geometry = this.state.api.GetGeometry( this.currentID, placed.geometryExpressID ); const vertexData = this.getVertices(geometry); const indices = this.getIndices(geometry); const { vertices, normals } = this.extractVertexData(vertexData); return this.ifcGeomToBufferGeom(vertices, normals, indices); } getVertices(geometry) { const vData = geometry.GetVertexData(); const vDataSize = geometry.GetVertexDataSize(); return this.state.api.GetVertexArray(vData, vDataSize); } getIndices(geometry) { const iData = geometry.GetIndexData(); const iDataSize = geometry.GetIndexDataSize(); return this.state.api.GetIndexArray(iData, iDataSize); } getMeshMatrix(matrix) { const mat = new Matrix4(); mat.fromArray(matrix); return mat; } ifcGeomToBufferGeom(vertices, normals, indexData) { const geometry = new BufferGeometry(); geometry.setAttribute("position", newFloatAttr(vertices, 3)); geometry.setAttribute("normal", newFloatAttr(normals, 3)); geometry.setIndex(new BufferAttribute(indexData, 1)); return geometry; } extractVertexData(vertexData) { const vertices = []; const normals = []; let isNormalData = false; for (let i = 0; i < vertexData.length; i++) { isNormalData ? normals.push(vertexData[i]) : vertices.push(vertexData[i]); if ((i + 1) % 3 == 0) isNormalData = !isNormalData; } return { vertices, normals, }; } saveGeometryByMaterial(geom, placedGeom, id) { const color = placedGeom.color; const colorID = `${color.x}${color.y}${color.z}${color.w}`; this.storeGeometryAttribute(id, geom); this.createMaterial(colorID, color); const item = this.state.models[this.currentID].items[colorID]; const currentGeom = item.geometries[id]; if (!currentGeom) return (item.geometries[id] = geom); const merged = merge([currentGeom, geom]); item.geometries[id] = merged; } storeGeometryAttribute(id, geometry) { const size = geometry.attributes.position.count; const idAttribute = new Array(size).fill(id); geometry.setAttribute(IdAttrName, newIntAttr(idAttribute, 1)); } createMaterial(colorID, color) { const items = this.state.models[this.currentID].items; if (items[colorID]) return; const col = new Color(color.x, color.y, color.z); const newMaterial = new MeshLambertMaterial({ color: col, side: DoubleSide, }); newMaterial.transparent = color.w !== 1; if (newMaterial.transparent) newMaterial.opacity = color.w; items[colorID] = { material: newMaterial, geometries: {}, }; } } class SubsetManager { constructor(state) { this.state = state; this.selected = {}; } getSubset(modelID, material) { const currentMat = this.matIDNoConfig(modelID, material); if (!this.selected[currentMat]) return null; return this.selected[currentMat].mesh; } removeSubset(modelID, scene, material) { const currentMat = this.matIDNoConfig(modelID, material); if (!this.selected[currentMat]) return; if (scene) scene.remove(this.selected[currentMat].mesh); delete this.selected[currentMat]; } createSubset(config) { if (!this.isConfigValid(config)) return; if (this.isPreviousSelection(config)) return; if (this.isEasySelection(config)) return this.addToPreviousSelection(config); this.updatePreviousSelection(config.scene, config); return this.createSelectionInScene(config); } createSelectionInScene(config) { const filtered = this.filter(config); const { geomsByMaterial, materials } = this.getGeomAndMat(filtered); const hasDefaultMaterial = this.matID(config) == DEFAULT; const geometry = merge(geomsByMaterial, hasDefaultMaterial); const mats = hasDefaultMaterial ? materials : config.material; const mesh = new Mesh(geometry, mats); this.selected[this.matID(config)].mesh = mesh; mesh.modelID = config.modelID; config.scene.add(mesh); return mesh; } isConfigValid(config) { return ( this.isValid(config.scene) && this.isValid(config.modelID) && this.isValid(config.ids) && this.isValid(config.removePrevious) ); } isValid(item) { return item != undefined && item != null; } getGeomAndMat(filtered) { const geomsByMaterial = []; const materials = []; for (let matID in filtered) { const geoms = Object.values(filtered[matID].geometries); if (!geoms.length) continue; materials.push(filtered[matID].material); if (geoms.length > 1) geomsByMaterial.push(merge(geoms)); else geomsByMaterial.push(...geoms); } return { geomsByMaterial, materials, }; } updatePreviousSelection(scene, config) { const previous = this.selected[this.matID(config)]; if (!previous) return this.newSelectionGroup(config); scene.remove(previous.mesh); config.removePrevious ? (previous.ids = new Set(config.ids)) : config.ids.forEach((id) => previous.ids.add(id)); } newSelectionGroup(config) { this.selected[this.matID(config)] = { ids: new Set(config.ids), mesh: {}, }; } isPreviousSelection(config) { if (!this.selected[this.matID(config)]) return false; if (this.containsIds(config)) return true; const previousIds = this.selected[this.matID(config)].ids; return JSON.stringify(config.ids) === JSON.stringify(previousIds); } containsIds(config) { const newIds = config.ids; const previous = Array.from(this.selected[this.matID(config)].ids); return newIds.every( ( (i) => (v) => (i = previous.indexOf(v, i) + 1) )(0) ); } addToPreviousSelection(config) { const previous = this.selected[this.matID(config)]; const filtered = this.filter(config); const geometries = Object.values(filtered) .map((i) => Object.values(i.geometries)) .flat(); const previousGeom = previous.mesh.geometry; previous.mesh.geometry = merge([previousGeom, ...geometries]); config.ids.forEach((id) => previous.ids.add(id)); } filter(config) { const items = this.state.models[config.modelID].items; const filtered = {}; for (let matID in items) { filtered[matID] = { material: items[matID].material, geometries: this.filterGeometries( new Set(config.ids), items[matID].geometries ), }; } return filtered; } filterGeometries(selectedIDs, geometries) { const ids = Array.from(selectedIDs); return Object.keys(geometries) .filter((key) => ids.includes(parseInt(key, 10))) .reduce((obj, key) => { return { ...obj, [key]: geometries[key], }; }, {}); } isEasySelection(config) { const matID = this.matID(config); const def = this.matIDNoConfig(config.modelID); if (!config.removePrevious && matID != def && this.selected[matID]) return true; } matID(config) { if (!config.material) return DEFAULT; const name = config.material.uuid || DEFAULT; return name.concat(" - ").concat(config.modelID.toString()); } matIDNoConfig(modelID, material) { let name = DEFAULT; if (material) name = material.uuid; return name.concat(" - ").concat(modelID.toString()); } } const IfcElements = { 103090709: "IFCPROJECT", 4097777520: "IFCSITE", 4031249490: "IFCBUILDING", 3124254112: "IFCBUILDINGSTOREY", 3856911033: "IFCSPACE", 25142252: "IFCCONTROLLER", 32344328: "IFCBOILER", 76236018: "IFCLAMP", 90941305: "IFCPUMP", 177149247: "IFCAIRTERMINALBOX", 182646315: "IFCFLOWINSTRUMENT", 263784265: "IFCFURNISHINGELEMENT", 264262732: "IFCELECTRICGENERATOR", 277319702: "IFCAUDIOVISUALAPPLIANCE", 310824031: "IFCPIPEFITTING", 331165859: "IFCSTAIR", 342316401: "IFCDUCTFITTING", 377706215: "IFCMECHANICALFASTENER", 395920057: "IFCDOOR", 402227799: "IFCELECTRICMOTOR", 413509423: "IFCSYSTEMFURNITUREELEMENT", 484807127: "IFCEVAPORATOR", 486154966: "IFCWINDOWSTANDARDCASE", 629592764: "IFCLIGHTFIXTURE", 630975310: "IFCUNITARYCONTROLELEMENT", 635142910: "IFCCABLECARRIERFITTING", 639361253: "IFCCOIL", 647756555: "IFCFASTENER", 707683696: "IFCFLOWSTORAGEDEVICE", 738039164: "IFCPROTECTIVEDEVICE", 753842376: "IFCBEAM", 812556717: "IFCTANK", 819412036: "IFCFILTER", 843113511: "IFCCOLUMN", 862014818: "IFCELECTRICDISTRIBUTIONBOARD", 900683007: "IFCFOOTING", 905975707: "IFCCOLUMNSTANDARDCASE", 926996030: "IFCVOIDINGFEATURE", 979691226: "IFCREINFORCINGBAR", 987401354: "IFCFLOWSEGMENT", 1003880860: "IFCELECTRICTIMECONTROL", 1051757585: "IFCCABLEFITTING", 1052013943: "IFCDISTRIBUTIONCHAMBERELEMENT", 1062813311: "IFCDISTRIBUTIONCONTROLELEMENT", 1073191201: "IFCMEMBER", 1095909175: "IFCBUILDINGELEMENTPROXY", 1156407060: "IFCPLATESTANDARDCASE", 1162798199: "IFCSWITCHINGDEVICE", 1329646415: "IFCSHADINGDEVICE", 1335981549: "IFCDISCRETEACCESSORY", 1360408905: "IFCDUCTSILENCER", 1404847402: "IFCSTACKTERMINAL", 1426591983: "IFCFIRESUPPRESSIONTERMINAL", 1437502449: "IFCMEDICALDEVICE", 1509553395: "IFCFURNITURE", 1529196076: "IFCSLAB", 1620046519: "IFCTRANSPORTELEMENT", 1634111441: "IFCAIRTERMINAL", 1658829314: "IFCENERGYCONVERSIONDEVICE", 1677625105: "IFCCIVILELEMENT", 1687234759: "IFCPILE", 1904799276: "IFCELECTRICAPPLIANCE", 1911478936: "IFCMEMBERSTANDARDCASE", 1945004755: "IFCDISTRIBUTIONELEMENT", 1973544240: "IFCCOVERING", 1999602285: "IFCSPACEHEATER", 2016517767: "IFCROOF", 2056796094: "IFCAIRTOAIRHEATRECOVERY", 2058353004: "IFCFLOWCONTROLLER", 2068733104: "IFCHUMIDIFIER", 2176052936: "IFCJUNCTIONBOX", 2188021234: "IFCFLOWMETER", 2223149337: "IFCFLOWTERMINAL", 2262370178: "IFCRAILING", 2272882330: "IFCCONDENSER", 2295281155: "IFCPROTECTIVEDEVICETRIPPINGUNIT", 2320036040: "IFCREINFORCINGMESH", 2347447852: "IFCTENDONANCHOR", 2391383451: "IFCVIBRATIONISOLATOR", 2391406946: "IFCWALL", 2474470126: "IFCMOTORCONNECTION", 2769231204: "IFCVIRTUALELEMENT", 2814081492: "IFCENGINE", 2906023776: "IFCBEAMSTANDARDCASE", 2938176219: "IFCBURNER", 2979338954: "IFCBUILDINGELEMENTPART", 3024970846: "IFCRAMP", 3026737570: "IFCTUBEBUNDLE", 3027962421: "IFCSLABSTANDARDCASE", 3040386961: "IFCDISTRIBUTIONFLOWELEMENT", 3053780830: "IFCSANITARYTERMINAL", 3079942009: "IFCOPENINGSTANDARDCASE", 3087945054: "IFCALARM", 3101698114: "IFCSURFACEFEATURE", 3127900445: "IFCSLABELEMENTEDCASE", 3132237377: "IFCFLOWMOVINGDEVICE", 3171933400: "IFCPLATE", 3221913625: "IFCCOMMUNICATIONSAPPLIANCE", 3242481149: "IFCDOORSTANDARDCASE", 3283111854: "IFCRAMPFLIGHT", 3296154744: "IFCCHIMNEY", 3304561284: "IFCWINDOW", 3310460725: "IFCELECTRICFLOWSTORAGEDEVICE", 3319311131: "IFCHEATEXCHANGER", 3415622556: "IFCFAN", 3420628829: "IFCSOLARDEVICE", 3493046030: "IFCGEOGRAPHICELEMENT", 3495092785: "IFCCURTAINWALL", 3508470533: "IFCFLOWTREATMENTDEVICE", 3512223829: "IFCWALLSTANDARDCASE", 3518393246: "IFCDUCTSEGMENT", 3571504051: "IFCCOMPRESSOR", 3588315303: "IFCOPENINGELEMENT", 3612865200: "IFCPIPESEGMENT", 3640358203: "IFCCOOLINGTOWER", 3651124850: "IFCPROJECTIONELEMENT", 3694346114: "IFCOUTLET", 3747195512: "IFCEVAPORATIVECOOLER", 3758799889: "IFCCABLECARRIERSEGMENT", 3824725483: "IFCTENDON", 3825984169: "IFCTRANSFORMER", 3902619387: "IFCCHILLER", 4074379575: "IFCDAMPER", 4086658281: "IFCSENSOR", 4123344466: "IFCELEMENTASSEMBLY", 4136498852: "IFCCOOLEDBEAM", 4156078855: "IFCWALLELEMENTEDCASE", 4175244083: "IFCINTERCEPTOR", 4207607924: "IFCVALVE", 4217484030: "IFCCABLESEGMENT", 4237592921: "IFCWASTETERMINAL", 4252922144: "IFCSTAIRFLIGHT", 4278956645: "IFCFLOWFITTING", 4288193352: "IFCACTUATOR", 4292641817: "IFCUNITARYEQUIPMENT", }; class PropertyManager { constructor(state) { this.state = state; } getExpressId(geometry, faceIndex) { if (!geometry.index) return; const geoIndex = geometry.index.array; return geometry.attributes[IdAttrName].getX(geoIndex[3 * faceIndex]); } getItemProperties(modelID, id, recursive = false) { return this.state.api.GetLine(modelID, id, recursive); } getAllItemsOfType(modelID, type, verbose) { const items = []; const lines = this.state.api.GetLineIDsWithType(modelID, type); for (let i = 0; i < lines.size(); i++) items.push(lines.get(i)); if (verbose) return items.map((id) => this.state.api.GetLine(modelID, id)); return items; } getPropertySets(modelID, elementID, recursive = false) { const propSetIds = this.getAllRelatedItemsOfType( modelID, elementID, PropsNames.psets ); return propSetIds.map((id) => this.state.api.GetLine(modelID, id, recursive) ); } getTypeProperties(modelID, elementID, recursive = false) { const typeId = this.getAllRelatedItemsOfType( modelID, elementID, PropsNames.type ); return typeId.map((id) => this.state.api.GetLine(modelID, id, recursive)); } getSpatialStructure(modelID) { const chunks = this.getSpatialTreeChunks(modelID); const projectID = this.state.api .GetLineIDsWithType(modelID, IFCPROJECT) .get(0); const project = this.newIfcProject(projectID); this.getSpatialNode(modelID, project, chunks); return project; } newIfcProject(id) { return { expressID: id, type: "IFCPROJECT", children: [], }; } getSpatialTreeChunks(modelID) { const treeChunks = {}; this.getChunks(modelID, treeChunks, PropsNames.aggregates); this.getChunks(modelID, treeChunks, PropsNames.spatial); return treeChunks; } getChunks(modelID, chunks, propNames) { const relation = this.state.api.GetLineIDsWithType(modelID, propNames.name); for (let i = 0; i < relation.size(); i++) { const rel = this.state.api.GetLine(modelID, relation.get(i), false); const relating = rel[propNames.relating].value; const related = rel[propNames.related].map((r) => r.value); if (chunks[relating] == undefined) { chunks[relating] = related; } else { chunks[relating] = chunks[relating].concat(related); } } } getSpatialNode(modelID, node, treeChunks) { this.getChildren(modelID, node, treeChunks, PropsNames.aggregates); this.getChildren(modelID, node, treeChunks, PropsNames.spatial); } getChildren(modelID, node, treeChunks, propNames) { const children = treeChunks[node.expressID]; if (children == undefined || children == null) return; const prop = propNames.key; node[prop] = children.map((child) => { const node = this.newNode(modelID, child); this.getSpatialNode(modelID, node, treeChunks); return node; }); } newNode(modelID, id) { const typeID = this.state.models[modelID].types[id].toString(); const typeName = IfcElements[typeID]; return { expressID: id, type: typeName, children: [], }; } getAllRelatedItemsOfType(modelID, id, propNames) { const lines = this.state.api.GetLineIDsWithType(modelID, propNames.name); const IDs = []; for (let i = 0; i < lines.size(); i++) { const rel = this.state.api.GetLine(modelID, lines.get(i)); const isRelated = this.isRelated(id, rel, propNames); if (isRelated) this.getRelated(rel, propNames, IDs); } return IDs; } getRelated(rel, propNames, IDs) { const element = rel[propNames.relating]; if (!Array.isArray(element)) IDs.push(element.value); else element.forEach((ele) => IDs.push(ele.value)); } isRelated(id, rel, propNames) { const relatedItems = rel[propNames.related]; if (Array.isArray(relatedItems)) { const values = relatedItems.map((item) => item.value); return values.includes(id); } return relatedItems.value === id; } } class TypeManager { constructor(state) { this.state = state; } getAllTypes() { for (let modelID in this.state.models) { const types = this.state.models[modelID].types; if (Object.keys(types).length == 0) this.getAllTypesOfModel(parseInt(modelID)); } } getAllTypesOfModel(modelID) { this.state.models[modelID].types; const elements = Object.keys(IfcElements).map((e) => parseInt(e)); const types = this.state.models[modelID].types; elements.forEach((type) => { const lines = this.state.api.GetLineIDsWithType(modelID, type); for (let i = 0; i < lines.size(); i++) types[lines.get(i)] = type; }); } } let modelIdCounter = 0; class IFCModel extends Group { constructor(mesh, ifc) { super(); this.mesh = mesh; this.ifc = ifc; this.modelID = modelIdCounter++; } setWasmPath(path) { this.ifc.setWasmPath(path); } close(scene) { this.ifc.close(this.modelID, scene); } getExpressId(geometry, faceIndex) { return this.ifc.getExpressId(geometry, faceIndex); } getAllItemsOfType(type, verbose) { return this.ifc.getAllItemsOfType(this.modelID, type, verbose); } getItemProperties(id, recursive = false) { return this.ifc.getItemProperties(this.modelID, id, recursive); } getPropertySets(id, recursive = false) { return this.ifc.getPropertySets(this.modelID, id, recursive); } getTypeProperties(id, recursive = false) { return this.ifc.getTypeProperties(this.modelID, id, recursive); } getIfcType(id) { return this.ifc.getIfcType(this.modelID, id); } getSpatialStructure() { return this.ifc.getSpatialStructure(this.modelID); } getSubset(material) { return this.ifc.getSubset(this.modelID, material); } removeSubset(scene, material) { this.ifc.removeSubset(this.modelID, scene, material); } createSubset(config) { const modelConfig = { ...config, modelID: this.modelID, }; return this.ifc.createSubset(modelConfig); } } class IFCManager { constructor() { this.state = { models: [], api: new IfcAPI(), }; this.parser = new IFCParser(this.state); this.subsets = new SubsetManager(this.state); this.properties = new PropertyManager(this.state); this.types = new TypeManager(this.state); } async parse(buffer) { const mesh = await this.parser.parse(buffer); this.types.getAllTypes(); return new IFCModel(mesh, this); } setWasmPath(path) { this.state.api.SetWasmPath(path); } setupThreeMeshBVH(computeBoundsTree, disposeBoundsTree, acceleratedRaycast) { this.parser.initializeMeshBVH( computeBoundsTree, disposeBoundsTree, acceleratedRaycast ); } close(modelID, scene) { this.state.api.CloseModel(modelID); if (scene) scene.remove(this.state.models[modelID].mesh); delete this.state.models[modelID]; } getExpressId(geometry, faceIndex) { return this.properties.getExpressId(geometry, faceIndex); } getAllItemsOfType(modelID, type, verbose) { return this.properties.getAllItemsOfType(modelID, type, verbose); } getItemProperties(modelID, id, recursive = false) { return this.properties.getItemProperties(modelID, id, recursive); } getPropertySets(modelID, id, recursive = false) { return this.properties.getPropertySets(modelID, id, recursive); } getTypeProperties(modelID, id, recursive = false) { return this.properties.getTypeProperties(modelID, id, recursive); } getIfcType(modelID, id) { const typeID = this.state.models[modelID].types[id]; return IfcElements[typeID.toString()]; } getSpatialStructure(modelID) { return this.properties.getSpatialStructure(modelID); } getSubset(modelID, material) { return this.subsets.getSubset(modelID, material); } removeSubset(modelID, scene, material) { this.subsets.removeSubset(modelID, scene, material); } createSubset(config) { return this.subsets.createSubset(config); } } class IFCLoader extends Loader { constructor(manager) { super(manager); this.ifcManager = new IFCManager(); } load(url, onLoad, onProgress, onError) { const scope = this; const loader = new FileLoader(scope.manager); loader.setPath(scope.path); loader.setResponseType("arraybuffer"); loader.setRequestHeader(scope.requestHeader); loader.setWithCredentials(scope.withCredentials); loader.load( url, async function (buffer) { try { if (typeof buffer == "string") { throw new Error("IFC files must be given as a buffer!"); } onLoad(await scope.parse(buffer)); } catch (e) { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); } }, onProgress, onError ); } parse(buffer) { return this.ifcManager.parse(buffer); } } export { IFCLoader }; //# sourceMappingURL=IFCLoader.js.map