From f0b19358616c8bd862765a0718cd9834f2730217 Mon Sep 17 00:00:00 2001 From: CyrilWaechter Date: Fri, 25 Nov 2022 18:52:58 +0100 Subject: [PATCH] Add system assignment check @aothms Is there a way to check against IFC formal propositions ? Example for [IfcZone](http://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcZone.htm#5.4.3.82.4-Formal-propositions) @Moult Should I move is_assignable to an util ? --- .../ifcopenshell/api/system/assign_system.py | 34 ++++++++++++++++++- .../test/util/test_system.py | 15 ++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/system/assign_system.py b/src/ifcopenshell-python/ifcopenshell/api/system/assign_system.py index 5fff2595de..113e9e3b0a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/system/assign_system.py +++ b/src/ifcopenshell-python/ifcopenshell/api/system/assign_system.py @@ -20,6 +20,33 @@ import ifcopenshell import ifcopenshell.api +ASSIGNABLE_DICT = { + "IfcZone": ("IfcZone", "IfcSpace", "IfcSpatialZone"), + "IfcBuiltSystem": ( + "IfcBuiltElement", + "IfcFurnishingElement", + "IfcElementAssembly", + "IfcTransportElement", + ), + "IfcBuildingSystem": ( + "IfcBuildingElement", + "IfcFurnishingElement", + "IfcElementAssembly", + "IfcTransportElement", + ), + "IfcDistributionSystem": ("IfcDistributionElement",), + "IfcStructuralAnalysisModel": ("IfcStructuralMember", "IfcStructuralConnection"), + "IfcGroup": ("IfcObjectDefinition",), +} + + +def is_assignable(product, system) -> bool: + for assignable in ASSIGNABLE_DICT.get(system.is_a(), ()): + if product.is_a(assignable): + return True + return False + + class Usecase: def __init__(self, file, **settings): self.file = file @@ -31,6 +58,11 @@ class Usecase: self.settings[key] = value def execute(self): + system = self.settings["system"] + product = self.settings["product"] + if not is_assignable(product, system): + raise TypeError(f"You cannot assign an {product.is_a()} to an {system.is_a()}") + if not self.settings["system"].IsGroupedBy: return self.file.create_entity( "IfcRelAssignsToGroup", @@ -39,7 +71,7 @@ class Usecase: "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedObjects": [self.settings["product"]], "RelatingGroup": self.settings["system"], - } + }, ) rel = self.settings["system"].IsGroupedBy[0] related_objects = set(rel.RelatedObjects) or set() diff --git a/src/ifcopenshell-python/test/util/test_system.py b/src/ifcopenshell-python/test/util/test_system.py index 8c603b216f..172c34bb2e 100644 --- a/src/ifcopenshell-python/test/util/test_system.py +++ b/src/ifcopenshell-python/test/util/test_system.py @@ -39,11 +39,20 @@ class TestGetElementSystems(test.bootstrap.IFC4): def test_do_not_get_non_services_groups(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") - ifcopenshell.api.run("system.assign_system", self.file, product=element, system=self.file.createIfcGroup()) - ifcopenshell.api.run("system.assign_system", self.file, product=element, system=self.file.createIfcZone()) ifcopenshell.api.run( - "system.assign_system", self.file, product=element, system=self.file.createIfcStructuralAnalysisModel() + "system.assign_system", + self.file, + product=element, + system=self.file.createIfcGroup(), ) + for not_assignable_system_class in ("IfcZone", "IfcStructuralAnalysisModel"): + with pytest.raises(TypeError): + ifcopenshell.api.run( + "system.assign_system", + self.file, + product=element, + system=self.file.create_entity(not_assignable_system_class), + ) assert not subject.get_element_systems(element)