diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py index 921be2e1a3..6101bc4c9d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/assign_material_style.py @@ -16,6 +16,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell + class Usecase: def __init__(self, file, material=None, style=None, context=None, should_use_presentation_style_assignment=False): @@ -112,6 +114,27 @@ class Usecase: else: self.create_new_definition_representation() + material_constituents_names = [] + for inverse in self.file.get_inverse(self.settings["material"]): + if inverse.is_a("IfcMaterialConstituent") and inverse.Name: + material_constituents_names.append(inverse.Name) + if not material_constituents_names: + return + + elements = ifcopenshell.util.element.get_elements_by_material(self.file, self.settings["material"]) + shape_aspects = [] + for element in elements: + shape_aspects += ifcopenshell.util.element.get_shape_aspects(element) + + for shape_aspect in shape_aspects: + if shape_aspect.Name not in material_constituents_names: + continue + + for rep in shape_aspect.ShapeRepresentations: + ifcopenshell.api.run( + "style.assign_representation_styles", self.file, shape_representation=rep, styles=[self.style] + ) + def modify_existing_definition_representation(self): definition_representation = self.settings["material"].HasRepresentation[0] representation = self.get_styled_representation(definition_representation) diff --git a/src/ifcopenshell-python/test/api/style/test_assign_material_style.py b/src/ifcopenshell-python/test/api/style/test_assign_material_style.py new file mode 100644 index 0000000000..eab6dd73b4 --- /dev/null +++ b/src/ifcopenshell-python/test/api/style/test_assign_material_style.py @@ -0,0 +1,56 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2022 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import pytest +import test.bootstrap +import ifcopenshell +import ifcopenshell.api + + +# TODO: test assigning styles without material constituents +class TestAssignMaterialStyle(test.bootstrap.IFC4): + def test_update_shape_aspect_representaitons_items_styles_if_material_is_part_of_matching_material_constituents( + self, + ): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + name = "Concrete" + product_shape = self.file.createIfcProductDefinitionShape() + element.Representation = product_shape + context = self.file.createIfcGeometricRepresentationContext() + + representation = self.file.createIfcShapeRepresentation() + item = self.file.createIfcExtrudedAreaSolid() + representation.Items = [item] + + shape_aspect = self.file.createIfcShapeAspect(ShapeRepresentations=(representation,), Name=name) + shape_aspect.PartOfProductDefinitionShape = product_shape + + style = self.file.createIfcSurfaceStyle() + material = ifcopenshell.api.run("material.add_material", self.file) + material_set = ifcopenshell.api.run( + "material.add_material_set", self.file, set_type="IfcMaterialConstituentSet" + ) + constituent = ifcopenshell.api.run( + "material.add_constituent", self.file, constituent_set=material_set, material=material + ) + constituent.Name = name + ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material_set) + + ifcopenshell.api.run("style.assign_material_style", self.file, material=material, style=style, context=context) + + assert item.StyledByItem[0].Styles == (style,)