Coverage for bim2sim/kernel/ifc_file.py: 100%
46 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 17:09 +0000
1import logging
3from pathlib import Path
4from ifcopenshell import file
6from bim2sim.elements.mapping.finder import TemplateFinder
7from bim2sim.elements.mapping.units import parse_ifc
8from bim2sim.elements.mapping import ifc2python
9from bim2sim.utilities.types import IFCDomain
11logger = logging.getLogger(__name__)
14class IfcFileClass:
15 """Combine IfcOpenShell file instance, finder and units together.
17 Especially if we handle multiple IFC files this dataclass helps us to keep
18 track which finder and units belong to which ifc file.
20 Args:
21 ifc_path: Pathlib object that points to ifc file
22 reset_guids: Boolean that determine if GUIDs should be reset
23 ifc_domain: Domain of the given ifc file if this is known
24 """
26 def __init__(
27 self,
28 ifc_path: Path,
29 reset_guids: bool = False,
30 ifc_domain: IFCDomain = None):
31 self.ifc_file_name = ifc_path.name
32 self.file = self.load_ifcopenshell_file(ifc_path)
33 self.finder = None
34 self.ifc_units = self.get_ifc_units()
35 self.domain = ifc_domain if ifc_domain else IFCDomain.unknown
36 self.schema = self.file.schema
37 if reset_guids:
38 self.file = ifc2python.reset_guids(self.file)
40 def initialize_finder(self, finder_path):
41 self.finder = TemplateFinder()
42 yield from self.finder.initialize(self.file)
43 if finder_path:
44 self.finder.load(finder_path)
46 @staticmethod
47 def load_ifcopenshell_file(ifc_path) -> file:
48 """Loads the IfcOpenShell file instance"""
49 ifc_file = ifc2python.load_ifc(ifc_path)
50 return ifc_file
52 def get_ifc_units(self) -> dict:
53 """Returns dict to translate IFC units to pint units
55 To use units from IFC we get all unit definitions from the ifc and their
56 corresponding measurement elements and map them to pint units.
58 Returns:
59 dict where key is the IfcMeasurement and value the pint unit
60 definition. e.g. 'IfcLengthMeasure': meter
61 """
62 logger.info(f"Initializing units for IFC file: {self.ifc_file_name}")
63 unit_assignment = self.file.by_type('IfcUnitAssignment')
65 ifc_units = {}
67 for unit_entity in unit_assignment[0].Units:
68 try:
69 if hasattr(unit_entity, 'UnitType'):
70 key = 'Ifc{}'.format(
71 unit_entity.UnitType.capitalize().replace('unit',
72 'Measure'))
73 pos_key = 'IfcPositive{}'.format(
74 unit_entity.UnitType.capitalize().replace('unit',
75 'Measure'))
76 elif hasattr(unit_entity, 'Currency'):
77 key = 'IfcMonetaryMeasure'
78 unit = parse_ifc(unit_entity)
79 ifc_units[key] = unit
80 if pos_key:
81 ifc_units[pos_key] = unit
82 except:
83 logger.warning(f"Failed to parse {unit_entity}")
84 ifc_units = {k.lower(): v for k, v in ifc_units.items()}
85 return ifc_units