Coverage for bim2sim/tasks/common/create_relations.py: 18%

39 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-12 17:09 +0000

1from bim2sim.elements.base_elements import IFCBased 

2from bim2sim.elements.bps_elements import ( 

3 ThermalZone, Storey, Building, ExternalSpatialElement) 

4from bim2sim.tasks.base import ITask 

5from bim2sim.elements.mapping.ifc2python import getBuilding, getStorey, getSite 

6 

7 

8class CreateRelations(ITask): 

9 """Relations of elements, run() method holds detailed information.""" 

10 reads = ('elements',) 

11 

12 def run(self, elements: dict[str, IFCBased]): 

13 """Bind ThermalZone to ProductBased/Storey/Building and vice versa. 

14 

15 This is needed as our CreateElements task does not work hierarchic. So 

16 we need to create the relations after initial creation. 

17 Problem: Following IFC-schema rules a space that is stretched over 

18 multiple storeys should only be assigned to one of these storeys. From 

19 IFC-Schema: 

20 "NOTE: Multi storey spaces shall be spatially contained by only a 

21 single building storey, usually it is the building storey where the 

22 base of the space lies. 

23 TODO: this might me solved via PyOCCTools.obj2_in_obj1 but this needs 

24 all shapes to be existing for ThermalZone instances and Storeys 

25 " 

26 

27 Args: 

28 elements: dict[guid: element] 

29 """ 

30 self.logger.info("Creating bim2sim elements relations.") 

31 for element in elements.values(): 

32 # connect element to site and vice versa 

33 ifc_site = getSite(element.ifc) 

34 if ifc_site: 

35 element_site = elements.get( 

36 ifc_site.GlobalId, None) 

37 if isinstance(element, Building): 

38 if element not in element_site.buildings: 

39 element_site.buildings.append(element) 

40 

41 # connect element to building and vice versa 

42 ifc_building = getBuilding(element.ifc) 

43 if ifc_building: 

44 element_building = elements.get( 

45 ifc_building.GlobalId, None) 

46 if isinstance(element, Storey): 

47 if element not in element_building.storeys: 

48 element_building.storeys.append(element) 

49 if isinstance(element, ThermalZone): 

50 if not isinstance(element, ExternalSpatialElement): 

51 if element not in element_building.thermal_zones: 

52 element_building.thermal_zones.append(element) 

53 else: 

54 if element not in element_building.elements: 

55 element_building.elements.append(element) 

56 element.building = element_building 

57 

58 # connect element to storey and vice versa 

59 ifc_storey = getStorey(element.ifc) 

60 if ifc_storey: 

61 element_storey = elements.get( 

62 ifc_storey.GlobalId, None) 

63 if isinstance(element, ThermalZone): 

64 if not isinstance(element, ExternalSpatialElement): 

65 if element not in element_storey.thermal_zones: 

66 element_storey.thermal_zones.append(element) 

67 else: 

68 if element not in element_storey.elements: 

69 element_storey.elements.append(element) 

70 if element not in element.storeys: 

71 element.storeys.append(element_storey) 

72 # relations between element and space are handled in sb_creation 

73 # as more robust