From 48e5d148172cdaf35c1baf211e195f0709ddf330 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Wed, 10 Apr 2024 15:54:04 +0500 Subject: [PATCH] nest.assign_object to support ifc2x3 --- .../ifcopenshell/api/nest/assign_object.py | 14 ++++++-- .../ifcopenshell/api/nest/unassign_object.py | 10 +++++- .../test/api/nest/test_assign_object.py | 32 +++++++++++-------- .../test/api/nest/test_unassign_object.py | 3 ++ .../test/util/test_element.py | 4 +++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py b/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py index a53193afc5..b56daa8300 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py @@ -106,9 +106,14 @@ class Usecase: if not self.settings["related_objects"]: return + ifc2x3 = self.file.schema == "IFC2X3" + related_objects = set(self.settings["related_objects"]) relating_object = self.settings["relating_object"] - is_nested_by = next((i for i in relating_object.IsNestedBy), None) + if ifc2x3: + is_nested_by = next((i for i in relating_object.IsDecomposedBy if i.is_a("IfcRelNests")), None) + else: + is_nested_by = next((i for i in relating_object.IsNestedBy), None) previous_nests_rels: set[ifcopenshell.entity_instance] = set() objects_without_nests: list[ifcopenshell.entity_instance] = [] @@ -116,7 +121,10 @@ class Usecase: # check if there is anything to change for object in related_objects: - object_rel = next(iter(object.Nests), None) + if ifc2x3: + object_rel = next((i for i in object.Decomposes if i.is_a("IfcRelNests")), None) + else: + object_rel = next(iter(object.Nests), None) if object_rel is None: objects_without_nests.append(object) @@ -134,7 +142,7 @@ class Usecase: if not objects_to_change: return is_nested_by - # NOTE: An object can both be nested and assigned to a container or aggregate. + # NOTE: An object can both be nested and assigned to a container or an aggregate. # unassign elements from previous nests for nests in previous_nests_rels: diff --git a/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py b/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py index 1f7d0f0f54..1c986f2cd0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py @@ -55,7 +55,15 @@ class Usecase: def execute(self) -> None: related_objects = set(self.settings["related_objects"]) - rels = set(rel for object in related_objects if (rel := next((rel for rel in object.Nests), None))) + ifc2x3 = self.file.schema == "IFC2X3" + if ifc2x3: + rels = set( + rel + for object in related_objects + if (rel := next((rel for rel in object.Decomposes if rel.is_a("IfcRelNests")), None)) + ) + else: + rels = set(rel for object in related_objects if (rel := next((rel for rel in object.Nests), None))) for rel in rels: related_objects = set(rel.RelatedObjects) - related_objects diff --git a/src/ifcopenshell-python/test/api/nest/test_assign_object.py b/src/ifcopenshell-python/test/api/nest/test_assign_object.py index df9757c2ce..25d4259627 100644 --- a/src/ifcopenshell-python/test/api/nest/test_assign_object.py +++ b/src/ifcopenshell-python/test/api/nest/test_assign_object.py @@ -25,9 +25,9 @@ import ifcopenshell.util.placement class TestAssignObject(test.bootstrap.IFC4): def test_assigning_a_nesting(self): - element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") - subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") rel = ifcopenshell.api.run( "nest.assign_object", self.file, related_objects=[subelement1, subelement2], relating_object=element ) @@ -36,32 +36,36 @@ class TestAssignObject(test.bootstrap.IFC4): assert rel.is_a("IfcRelNests") def test_doing_nothing_if_the_nesting_is_already_assigned(self): - element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement], relating_object=element) total_elements = len([e for e in self.file]) ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement], relating_object=element) assert len([e for e in self.file]) == total_elements def test_that_old_nesting_relationships_are_updated_if_they_still_have_elements(self): - element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") - subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") ifcopenshell.api.run( "nest.assign_object", self.file, related_objects=[subelement1, subelement2], relating_object=element1 ) - rel = subelement1.Nests[0] + rel = subelement1.Decomposes[0] if self.file.schema == "IFC2X3" else subelement1.Nests[0] assert len(rel.RelatedObjects) == 2 ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement1], relating_object=element2) assert len(rel.RelatedObjects) == 1 def test_that_old_nesting_relationships_are_purged_if_no_more_elements_are_nested(self): - element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSanitaryTerminal") - subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcValve") + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") + subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcTask") ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement1], relating_object=element1) - rel_id = subelement1.Nests[0].id() + rel_id = (subelement1.Decomposes[0] if self.file.schema == "IFC2X3" else subelement1.Nests[0]).id() ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement1], relating_object=element2) with pytest.raises(RuntimeError): self.file.by_id(rel_id) + + +class TestAssignObjectIFC2X3(test.bootstrap.IFC2X3, TestAssignObject): + pass diff --git a/src/ifcopenshell-python/test/api/nest/test_unassign_object.py b/src/ifcopenshell-python/test/api/nest/test_unassign_object.py index d26074c026..479ab0bcce 100644 --- a/src/ifcopenshell-python/test/api/nest/test_unassign_object.py +++ b/src/ifcopenshell-python/test/api/nest/test_unassign_object.py @@ -49,3 +49,6 @@ class TestUnassignObject(test.bootstrap.IFC4): ifcopenshell.api.run("nest.assign_object", self.file, related_objects=[subelement], relating_object=element) ifcopenshell.api.run("nest.unassign_object", self.file, related_objects=[subelement]) assert len(self.file.by_type("IfcRelNests")) == 0 + +class TestUnassignObjectIFC2X3(test.bootstrap.IFC2X3, TestUnassignObject): + pass diff --git a/src/ifcopenshell-python/test/util/test_element.py b/src/ifcopenshell-python/test/util/test_element.py index 2e917e1258..a0d0ee3f47 100644 --- a/src/ifcopenshell-python/test/util/test_element.py +++ b/src/ifcopenshell-python/test/util/test_element.py @@ -775,6 +775,10 @@ class TestGetNestIFC4(test.bootstrap.IFC4): assert subject.get_nest(subelement) == element +class TestGetNestIFC2X3(test.bootstrap.IFC2X3, TestGetNestIFC4): + pass + + class TestReplaceAttributeIFC4(test.bootstrap.IFC4): def test_replacing_an_elements_attribute(self): element = self.file.createIfcWall("foo")