@@ -3,7 +3,6 @@ import { FragmentsGroup } from "@thatopen/fragments";
33import { Disposable , Event , Component , Components } from "../../core" ;
44import { FragmentManager } from "../../fragments/FragmentManager" ;
55import { IfcPropertiesUtils } from "../Utils" ;
6- import { getRelationMap } from "./src/getRelationMap" ;
76import {
87 RelationsMap ,
98 ModelsRelationMap ,
@@ -32,11 +31,7 @@ export class IfcRelationsIndexer extends Component implements Disposable {
3231
3332 private _relToAttributesMap = relToAttributesMap ;
3433
35- /**
36- * Array of inverse attribute names.
37- * This array is used to define the inverse attributes that the indexer will process and index.
38- */
39- readonly inverseAttributes : InverseAttributes = [
34+ private _inverseAttributes : InverseAttributes = [
4035 "IsDecomposedBy" ,
4136 "Decomposes" ,
4237 "AssociatedTo" ,
@@ -53,6 +48,17 @@ export class IfcRelationsIndexer extends Component implements Disposable {
5348 "ContainsElements" ,
5449 ] ;
5550
51+ private _ifcRels = [
52+ WEBIFC . IFCRELAGGREGATES ,
53+ WEBIFC . IFCRELASSOCIATESMATERIAL ,
54+ WEBIFC . IFCRELASSOCIATESCLASSIFICATION ,
55+ WEBIFC . IFCRELASSIGNSTOGROUP ,
56+ WEBIFC . IFCRELDEFINESBYPROPERTIES ,
57+ WEBIFC . IFCRELDEFINESBYTYPE ,
58+ WEBIFC . IFCRELDEFINESBYTEMPLATE ,
59+ WEBIFC . IFCRELCONTAINEDINSPATIALSTRUCTURE ,
60+ ] as const ;
61+
5662 /**
5763 * Holds the relationship mappings for each model processed by the indexer.
5864 * The structure is a map where each key is a model's UUID, and the value is another map.
@@ -78,15 +84,6 @@ export class IfcRelationsIndexer extends Component implements Disposable {
7884 delete this . relationMaps [ data . groupID ] ;
7985 } ;
8086
81- private getAttributeRels ( value : string ) {
82- const keys : number [ ] = [ ] ;
83- for ( const [ rel , attribute ] of this . _relToAttributesMap . entries ( ) ) {
84- const { forRelating, forRelated } = attribute ;
85- if ( forRelating === value || forRelated === value ) keys . push ( rel ) ;
86- }
87- return keys ;
88- }
89-
9087 /**
9188 * Adds a relation map to the model's relations map.
9289 *
@@ -125,46 +122,43 @@ export class IfcRelationsIndexer extends Component implements Disposable {
125122
126123 const relationsMap : RelationsMap = new Map ( ) ;
127124
128- for ( const attribute of this . inverseAttributes ) {
129- const rels = this . getAttributeRels ( attribute ) ;
130- for ( const rel of rels ) {
131- await IfcPropertiesUtils . getRelationMap (
132- model ,
133- rel ,
134- async ( relatingID , relatedID ) => {
135- const inverseAttributes = this . _relToAttributesMap . get ( rel ) ;
136- if ( ! inverseAttributes ) return ;
137- const { forRelated : related , forRelating : relating } =
138- inverseAttributes ;
139- if ( relating ) {
140- const currentMap =
141- relationsMap . get ( relatingID ) ?? new Map < number , number [ ] > ( ) ;
142- // TODO: indexOf might be slow. Better a Map<string, number>?
143- const index = this . inverseAttributes . indexOf ( relating ) ;
144- currentMap . set ( index , relatedID ) ;
145- relationsMap . set ( relatingID , currentMap ) ;
146- }
147- if ( related ) {
148- for ( const id of relatedID ) {
149- const currentMap =
150- relationsMap . get ( id ) ?? new Map < number , number [ ] > ( ) ;
151- const index = this . inverseAttributes . indexOf ( related ) ;
152- const relations = currentMap . get ( index ) ?? [ ] ;
153- relations . push ( relatingID ) ;
154- currentMap . set ( index , relations ) ;
155- relationsMap . set ( id , currentMap ) ;
156- }
157- }
158- } ,
159- ) ;
160- }
125+ for ( const rel of this . _ifcRels ) {
126+ await IfcPropertiesUtils . getRelationMap (
127+ model ,
128+ rel ,
129+ async ( relatingID , relatedIDs ) => {
130+ const inverseAttributes = this . _relToAttributesMap . get ( rel ) ;
131+ if ( ! inverseAttributes ) return ;
132+ const { forRelated : related , forRelating : relating } =
133+ inverseAttributes ;
134+
135+ // forRelating
136+ const currentMap =
137+ relationsMap . get ( relatingID ) ?? new Map < number , number [ ] > ( ) ;
138+ const index = this . _inverseAttributes . indexOf ( relating ) ;
139+ currentMap . set ( index , relatedIDs ) ;
140+ relationsMap . set ( relatingID , currentMap ) ;
141+
142+ // forRelated
143+ for ( const id of relatedIDs ) {
144+ const currentMap =
145+ relationsMap . get ( id ) ?? new Map < number , number [ ] > ( ) ;
146+ const index = this . _inverseAttributes . indexOf ( related ) ;
147+ const relations = currentMap . get ( index ) ?? [ ] ;
148+ relations . push ( relatingID ) ;
149+ currentMap . set ( index , relations ) ;
150+ relationsMap . set ( id , currentMap ) ;
151+ }
152+ } ,
153+ ) ;
161154 }
155+
162156 this . setRelationMap ( model , relationsMap ) ;
163157 return relationsMap ;
164158 }
165159
166160 /**
167- * Processes a given model from a WebIfc API to index its IFC entities relations based on predefined inverse attributes .
161+ * Processes a given model from a WebIfc API to index its IFC entities relations.
168162 *
169163 * @param ifcApi - The WebIfc API instance from which to retrieve the model's properties.
170164 * @param modelID - The unique identifier of the model within the WebIfc API.
@@ -174,42 +168,44 @@ export class IfcRelationsIndexer extends Component implements Disposable {
174168 async processFromWebIfc ( ifcApi : WEBIFC . IfcAPI , modelID : number ) {
175169 const relationsMap : RelationsMap = new Map ( ) ;
176170
177- const properties : Record < string , Record < string , any > > = { } ;
178- const lines = ifcApi . GetAllLines ( modelID ) ;
171+ for ( const relType of this . _ifcRels ) {
172+ const relInverseAttributes = this . _relToAttributesMap . get ( relType ) ;
173+ if ( ! relInverseAttributes ) continue ;
174+ const { forRelated : related , forRelating : relating } =
175+ relInverseAttributes ;
176+ const relExpressIDs = ifcApi . GetLineIDsWithType ( modelID , relType ) ;
177+ for ( let i = 0 ; i < relExpressIDs . size ( ) ; i ++ ) {
178+ const relAttrs = await ifcApi . properties . getItemProperties (
179+ modelID ,
180+ relExpressIDs . get ( i ) ,
181+ ) ;
182+ const relatingKey = Object . keys ( relAttrs ) . find ( ( key ) =>
183+ key . startsWith ( "Relating" ) ,
184+ ) ;
185+ const relatedKey = Object . keys ( relAttrs ) . find ( ( key ) =>
186+ key . startsWith ( "Related" ) ,
187+ ) ;
188+ if ( ! ( relatingKey && relatedKey ) ) continue ;
189+ const relatingID = relAttrs [ relatingKey ] . value ;
190+ const relatedIDs = relAttrs [ relatedKey ] . map ( ( el : any ) => el . value ) ;
179191
180- for ( let i = 0 ; i < lines . size ( ) ; i ++ ) {
181- const line = lines . get ( i ) ;
182- const attrs = await ifcApi . properties . getItemProperties ( modelID , line ) ;
183- properties [ line ] = attrs ;
184- }
192+ // forRelating
193+ const currentMap =
194+ relationsMap . get ( relatingID ) ?? new Map < number , number [ ] > ( ) ;
195+ const index = this . _inverseAttributes . indexOf ( relating ) ;
196+ currentMap . set ( index , relatedIDs ) ;
197+ relationsMap . set ( relatingID , currentMap ) ;
185198
186- for ( const attribute of this . inverseAttributes ) {
187- const rels = this . getAttributeRels ( attribute ) ;
188- for ( const rel of rels ) {
189- getRelationMap ( properties , rel , ( relatingID , relatedID ) => {
190- const inverseAttributes = this . _relToAttributesMap . get ( rel ) ;
191- if ( ! inverseAttributes ) return ;
192- const { forRelated : related , forRelating : relating } =
193- inverseAttributes ;
194- if ( relating ) {
195- const currentMap =
196- relationsMap . get ( relatingID ) ?? new Map < number , number [ ] > ( ) ;
197- const index = this . inverseAttributes . indexOf ( relating ) ;
198- currentMap . set ( index , relatedID ) ;
199- relationsMap . set ( relatingID , currentMap ) ;
200- }
201- if ( related ) {
202- for ( const id of relatedID ) {
203- const currentMap =
204- relationsMap . get ( id ) ?? new Map < number , number [ ] > ( ) ;
205- const index = this . inverseAttributes . indexOf ( related ) ;
206- const relations = currentMap . get ( index ) ?? [ ] ;
207- relations . push ( relatingID ) ;
208- currentMap . set ( index , relations ) ;
209- relationsMap . set ( id , currentMap ) ;
210- }
211- }
212- } ) ;
199+ // forRelated
200+ for ( const id of relatedIDs ) {
201+ const currentMap =
202+ relationsMap . get ( id ) ?? new Map < number , number [ ] > ( ) ;
203+ const index = this . _inverseAttributes . indexOf ( related ) ;
204+ const relations = currentMap . get ( index ) ?? [ ] ;
205+ relations . push ( relatingID ) ;
206+ currentMap . set ( index , relations ) ;
207+ relationsMap . set ( id , currentMap ) ;
208+ }
213209 }
214210 }
215211
@@ -240,7 +236,7 @@ export class IfcRelationsIndexer extends Component implements Disposable {
240236 const indexMap = this . relationMaps [ model . uuid ] ;
241237 if ( ! indexMap ) return null ;
242238 const entityRelations = indexMap . get ( expressID ) ;
243- const attributeIndex = this . inverseAttributes . indexOf ( relationName ) ;
239+ const attributeIndex = this . _inverseAttributes . indexOf ( relationName ) ;
244240 if ( ! entityRelations || attributeIndex === - 1 ) return null ;
245241 const relations = entityRelations . get ( attributeIndex ) ;
246242 if ( ! relations ) return null ;
0 commit comments