get_applicable_types in ifc2x3 to prioritize IfcBuildingElementProxyType

for occurrence classes without special type.

E.g. previously:
you select IfcSlab and change it to IfcRoof - since there is not IfcRoofType in IFC2X3 it would figure the matching product type is IfcBeamType and change this slab's type element to IfcBeamType. IfcBuildingElementProxyType seems more generic and fitting.
This commit is contained in:
Andrej730
2025-03-11 18:20:12 +05:00
parent 977d814d39
commit a9f7d4ab3b
2 changed files with 15 additions and 0 deletions
@@ -183,6 +183,10 @@ class Usecase:
if self.occurrence_class:
ifc_class_ = self.occurrence_class
else:
# NOTE: in theory we can skip reassignment in IFC2X3 in some cases
# e.g. if occurrence is IfcRoof and we're reassigning to IfcBuildingElementProxyType
# but currently type_to_entity_map doesn't completely match entity_to_type_map,
# see type.py for more details.
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)))
self.reassign_class(occurrence, ifc_class_, predefined_type)
else:
@@ -43,7 +43,18 @@ for schema in mapped_schemas:
type_to_entity_map[schema].setdefault(element_type, []).append(element)
if schema == "IFC2X3":
# Prioritize IfcBuildingElementProxyType if it's available as it seems to be the most generic type.
# Otherwise classes that don't have a special type in IFC2X3 (e.g. IfcBuildingElementPart, IfcRoof)
# have IfcBeamType as their first matching type, which can be confusing.
for occurrence_type, element_types in entity_to_type_map[schema].items():
if "IfcBuildingElementProxyType" in element_types:
element_types.sort(key=lambda x: x == "IfcBuildingElementProxyType", reverse=True)
# There is no official mapping for IFC2X3 but this method gets us something that looks correct
#
# NOTE: currently `type_to_entity_map` in IFC2X3 doesn't completely match `entity_to_type_map`,
# e.g. `get_applicabl_types(IfcRoof)` returns `[IfcBuildingElementProxyType, IfcBeamType, ...]`
# but `get_applicable_entities(IfcBuildingElementProxyType)` returns `[IfcBuildingElementProxy`].
for element_type, elements in type_to_entity_map[schema].items():
# need to take both Type (4 symbols) and Style (5 symbols) into account
guessed_element = element_type[:-5] if element_type.endswith("Style") else element_type[:-4]