From 86c5cc0f51d7a2e9551efafa8051e7efe16db137 Mon Sep 17 00:00:00 2001 From: Juan Hoyos Date: Mon, 12 Aug 2024 12:26:07 -0500 Subject: [PATCH] feat(core): adds a way to find related entites based on inverse attributes to IfcRelationsIndexer --- .../src/ifc/IfcRelationsIndexer/example.ts | 41 +++++++++++++++++++ .../core/src/ifc/IfcRelationsIndexer/index.ts | 32 +++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/packages/core/src/ifc/IfcRelationsIndexer/example.ts b/packages/core/src/ifc/IfcRelationsIndexer/example.ts index cc0a886dc..7611b91e4 100644 --- a/packages/core/src/ifc/IfcRelationsIndexer/example.ts +++ b/packages/core/src/ifc/IfcRelationsIndexer/example.ts @@ -201,6 +201,47 @@ if (buildingStorey && buildingStorey[0]) { ::: + ### 🤏 Getting entities related with another + There are situations in which you need to know elements related to another based on a specific inverse attribute. For example, to know all the elements that has a specific IfcPropertySet, all elements inside a known IfcBuildingStorey, all elements sharing a common IfcClassificationReference, etc. Let's take the following as examples of this feature! + */ + +// This is the equivalent to say: All entities in the model that are contained in structure 138 +const storeyElements = indexer.getEntitiesWithRelation( + model, + "ContainedInStructure", + 138, +); + +console.log( + `IfcBuildingStorey 138 has the following IfcElement: ${[...storeyElements]}`, +); + +// This is the equivalent to say: All entities in the model that contains entity 138 +const elementStorey = indexer.getEntitiesWithRelation( + model, + "ContainsElements", + 186, +); + +console.log( + `IfcElement 186 is located inside IfcBuildingStorey ${[...elementStorey][0]}`, +); + +// This is the equivalent to say: All entities in the model that are defined by entity 303 +const psetDefinitions = indexer.getEntitiesWithRelation( + model, + "IsDefinedBy", + 303, +); + +console.log(`${[...psetDefinitions]} are defined by IfcPropertySet 303`); + +/* MD + :::tip + + Needless to say, you must know the expressID of the entity you want to find its relations with (138 is the expressID of the IfcBuildingStorey named "Nivel 1" in the example model). + + ::: ### ⏱️ Measuring the performance (optional) --- diff --git a/packages/core/src/ifc/IfcRelationsIndexer/index.ts b/packages/core/src/ifc/IfcRelationsIndexer/index.ts index 1659c425f..b2f43e402 100644 --- a/packages/core/src/ifc/IfcRelationsIndexer/index.ts +++ b/packages/core/src/ifc/IfcRelationsIndexer/index.ts @@ -394,6 +394,38 @@ export class IfcRelationsIndexer extends Component implements Disposable { this.onDisposed.reset(); } + /** + * Retrieves the entities within a given model that have a specific relation with a given entity. + * + * @param model - The BIM model to search for related entities. + * @param inv - The IFC schema inverse attribute of the relation to search for (e.g., "IsDefinedBy", "ContainsElements"). + * @param expressID - The expressID of the entity within the model. + * + * @returns A `Set` with the expressIDs of the entities that have the specified relation with the given entity. + * + * @throws An error if the model relations are not indexed or if the inverse attribute name is invalid. + */ + getEntitiesWithRelation( + model: FragmentsGroup, + inv: InverseAttribute, + expressID: number, + ) { + const relations = this.relationMaps[model.uuid]; + if (!relations) + throw new Error( + "IfcRelationsIndexer: the model relations are not indexed!", + ); + const set: Set = new Set(); + for (const [id, map] of relations) { + const index = this.getAttributeIndex(inv); + if (index === null) + throw new Error("IfcRelationsIndexer: invalid inverse attribute name"); + const rels = map.get(index); + if (rels && rels.includes(expressID)) set.add(id); + } + return set; + } + /** * Adds relations between an entity and other entities in a BIM model. *