diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py index 06b9f7fd25..86eb30c193 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py @@ -41,6 +41,14 @@ class Usecase: product_type and product_type.RepresentationMaps and representation.RepresentationType != "MappedRepresentation" + # Revit is adding a non-mapped representation to the exported profile-based types, + # so assigning representation to occurrence by accident was assigning it to the type. + # We guard from this by skipping profile and layer-based types. + # See 6934 for example. + and not ( + (material := ifcopenshell.util.element.get_material(product_type)) + and material.is_a() in ("IfcMaterialProfileSet", "IfcMaterialLayerSet") + ) ): product = product_type @@ -60,7 +68,7 @@ class Usecase: **{ "MappingOrigin": self.file.createIfcAxis2Placement3D(self.zero, self.z_axis, self.x_axis), "MappedRepresentation": representation, - } + }, ) ) product.RepresentationMaps = maps diff --git a/src/ifcopenshell-python/test/api/geometry/test_assign_representation.py b/src/ifcopenshell-python/test/api/geometry/test_assign_representation.py index ae6ccac212..c971219157 100644 --- a/src/ifcopenshell-python/test/api/geometry/test_assign_representation.py +++ b/src/ifcopenshell-python/test/api/geometry/test_assign_representation.py @@ -18,6 +18,7 @@ import test.bootstrap import ifcopenshell.api +import ifcopenshell.api.material import ifcopenshell.api.type import ifcopenshell.api.root import ifcopenshell.api.geometry @@ -93,6 +94,33 @@ class TestAssignRepresentation(test.bootstrap.IFC4): assert wall.Representation.Representations[0] == rep assert not walltype.RepresentationMaps + def test_assigning_to_an_instance_with_a_geometric_profile_layer_based_type_only_adds_it_to_the_instance(self): + material_set_types = ( + "IfcMaterialLayerSet", + *(("IfcMaterialProfileSet",) * (self.file.schema != "IFC2X3")), + ) + for material_set_type in material_set_types: + context = self.file.createIfcGeometricRepresentationContext() + rep = self.file.createIfcShapeRepresentation(ContextOfItems=context) + rep2 = self.file.createIfcShapeRepresentation(ContextOfItems=context) + + walltype = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWallType") + ifcopenshell.api.geometry.assign_representation(self.file, product=walltype, representation=rep) + material = ifcopenshell.api.material.add_material_set(self.file, set_type=material_set_type) + ifcopenshell.api.material.assign_material(self.file, products=[walltype], material=material) + + wall = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall") + ifcopenshell.api.type.assign_type( + self.file, related_objects=[wall], relating_type=walltype, should_map_representations=False + ) + + ifcopenshell.api.geometry.assign_representation(self.file, product=wall, representation=rep2) + assert len(wall.Representation.Representations) == 1 + assert wall.Representation.Representations[0].RepresentationType != "MappedRepresentation" + assert wall.Representation.Representations[0] == rep2 + assert len(walltype.RepresentationMaps) == 1 + assert walltype.RepresentationMaps[0].MappedRepresentation == rep + class TestAssignRepresentationIFC2X3(test.bootstrap.IFC2X3, TestAssignRepresentation): pass