From d6fb50851777d19e331ce39f08a940e08f54b395 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 11 Apr 2024 14:00:49 +0500 Subject: [PATCH] assign_type not to remap if it's type was assigned previously --- .../ifcopenshell/api/type/assign_type.py | 9 ++- .../test/api/type/test_assign_type.py | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py index 260b068e7e..6e3db8d595 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py @@ -19,7 +19,7 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.element -from typing import Union +from typing import Union, Iterable class Usecase: @@ -98,6 +98,7 @@ class Usecase: IFC requires all occurrences to map those representations. Some IFC vendors might disobey this, or you might want to handle it yourself. In this scenario, you may set this to False. + This also enabled adding material usages mapping. :type should_map_representations: bool :return: The IfcRelDefinesByType relationship or `None` if `related_objects` was empty list. @@ -250,17 +251,17 @@ class Usecase: if self.settings["should_map_representations"]: if getattr(relating_type, "RepresentationMaps", None): - for related_object in related_objects: + for related_object in objects_to_change: ifcopenshell.api.run( "type.map_type_representations", self.file, related_object=related_object, relating_type=relating_type, ) - self.map_material_usages(related_objects) + self.map_material_usages(objects_to_change) return types - def map_material_usages(self, related_objects: set[ifcopenshell.entity_instance]) -> None: + def map_material_usages(self, related_objects: Iterable[ifcopenshell.entity_instance]) -> None: type_material = ifcopenshell.util.element.get_material(self.settings["relating_type"]) if not type_material: return diff --git a/src/ifcopenshell-python/test/api/type/test_assign_type.py b/src/ifcopenshell-python/test/api/type/test_assign_type.py index 484cceb260..e1728747ee 100644 --- a/src/ifcopenshell-python/test/api/type/test_assign_type.py +++ b/src/ifcopenshell-python/test/api/type/test_assign_type.py @@ -19,6 +19,7 @@ import test.bootstrap import ifcopenshell.api import ifcopenshell.util.element +import ifcopenshell.util.representation import pytest @@ -65,6 +66,83 @@ class TestAssignType(test.bootstrap.IFC4): with pytest.raises(RuntimeError): self.file.by_id(rel_id) + def test_map_representation_disabled(self): + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + context = self.file.createIfcGeometricRepresentationContext() + rep = self.file.createIfcShapeRepresentation(ContextOfItems=context) + ifcopenshell.api.run("geometry.assign_representation", self.file, product=element_type, representation=rep) + ifcopenshell.api.run("material.assign_material", self.file, product=element_type, type="IfcMaterialLayerSet") + + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run( + "type.assign_type", + self.file, + related_objects=[element], + relating_type=element_type, + should_map_representations=False, + ) + + # no representation mapping and no material usage + assert ifcopenshell.util.representation.get_representation(element, context=context) == None + assert ifcopenshell.util.element.get_material(element, should_inherit=False) == None + + def test_map_representation(self): + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + context = self.file.createIfcGeometricRepresentationContext() + rep = self.file.createIfcShapeRepresentation(ContextOfItems=context) + ifcopenshell.api.run("geometry.assign_representation", self.file, product=element_type, representation=rep) + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type) + mapped_rep = ifcopenshell.util.representation.get_representation(element, context=context) + assert mapped_rep.RepresentationType == "MappedRepresentation" + assert mapped_rep.Items[0].MappingSource.MappedRepresentation == rep + + def test_map_representation(self): + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + context = self.file.createIfcGeometricRepresentationContext() + rep = self.file.createIfcShapeRepresentation(ContextOfItems=context) + ifcopenshell.api.run("geometry.assign_representation", self.file, product=element_type, representation=rep) + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element1], relating_type=element_type) + assert (mapped_rep := ifcopenshell.util.representation.get_representation(element1, context=context)) + mapped_rep_id = mapped_rep.id() + + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run( + "type.assign_type", self.file, related_objects=[element1, element2], relating_type=element_type + ) + assert (mapped_rep := ifcopenshell.util.representation.get_representation(element1, context=context)) + assert mapped_rep.id() == mapped_rep_id + + def test_map_material_usages(self): + material_types = ("IfcMaterialLayerSet",) + if self.file.schema != "IFC2X3": + material_types += ("IfcMaterialProfileSet",) + for material_type in material_types: + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("material.assign_material", self.file, product=element_type, type=material_type) + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type) + material = ifcopenshell.util.element.get_material(element) + assert material + assert material.is_a(f"{material_type}Usage") + + def test_do_not_reassign_material_if_it_was_assigned_previously(self): + element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("material.assign_material", self.file, product=element_type, type="IfcMaterialLayerSet") + ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element1], relating_type=element_type) + assert (material := ifcopenshell.util.element.get_material(element1)) + material_id = material.id() + + # use 2 elements to trigger material assignment code block + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run( + "type.assign_type", self.file, related_objects=[element1, element2], relating_type=element_type + ) + assert (material := ifcopenshell.util.element.get_material(element1)) + assert material.id() == material_id + class TestAssignTypeIFC2X3(test.bootstrap.IFC2X3, TestAssignType): pass