123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884 |
- 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
|