From 93fd3f97e3fbb5bad32a6900e66b115013ef1cc2 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 8 May 2022 18:03:18 +1000 Subject: [PATCH] #2111 New feature to select by style and see style usage --- .../blenderbim/bim/module/material/data.py | 4 +- .../blenderbim/bim/module/style/__init__.py | 1 + .../blenderbim/bim/module/style/operator.py | 37 +++--- .../blenderbim/bim/module/style/ui.py | 10 +- src/blenderbim/blenderbim/core/style.py | 4 + src/blenderbim/blenderbim/core/tool.py | 2 + src/blenderbim/blenderbim/tool/material.py | 16 +-- src/blenderbim/blenderbim/tool/style.py | 12 ++ src/blenderbim/test/bim/feature/style.feature | 10 ++ src/blenderbim/test/tool/test_style.py | 26 ++++ .../ifcopenshell/util/element.py | 56 +++++++-- .../test/util/test_element.py | 115 ++++++++++++++++-- 12 files changed, 242 insertions(+), 51 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/material/data.py b/src/blenderbim/blenderbim/bim/module/material/data.py index 2eff87dfbe..3f5245fc13 100644 --- a/src/blenderbim/blenderbim/bim/module/material/data.py +++ b/src/blenderbim/blenderbim/bim/module/material/data.py @@ -92,8 +92,10 @@ class ObjectMaterialData: element_type = ifcopenshell.util.element.get_type(element) if element_type != element: material = ifcopenshell.util.element.get_material(element_type) + if not material: + return if material.is_a() in ("IfcMaterialLayerSetUsage", "IfcMaterialLayerSet"): name_attr = "LayerSetName" else: name_attr = "Name" - return getattr(material, name_attr, "Unnamed") + return getattr(material, name_attr, "Unnamed") or "Unnamed" diff --git a/src/blenderbim/blenderbim/bim/module/style/__init__.py b/src/blenderbim/blenderbim/bim/module/style/__init__.py index c7ecdab9e3..d8d6b7f344 100644 --- a/src/blenderbim/blenderbim/bim/module/style/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/style/__init__.py @@ -27,6 +27,7 @@ classes = ( operator.EnableEditingStyle, operator.LoadStyles, operator.RemoveStyle, + operator.SelectByStyle, operator.UnlinkStyle, operator.UpdateStyleColours, operator.UpdateStyleTextures, diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 0e352ed138..09e1215b1f 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -24,14 +24,7 @@ import ifcopenshell.util.representation from blenderbim.bim.ifc import IfcStore -class Operator: - def execute(self, context): - IfcStore.execute_ifc_operator(self, context) - blenderbim.bim.handler.refresh_ui_data() - return {"FINISHED"} - - -class UpdateStyleColours(bpy.types.Operator, Operator): +class UpdateStyleColours(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.update_style_colours" bl_label = "Update Style Colours" bl_options = {"REGISTER", "UNDO"} @@ -40,7 +33,7 @@ class UpdateStyleColours(bpy.types.Operator, Operator): core.update_style_colours(tool.Ifc, tool.Style, obj=context.active_object.active_material) -class UpdateStyleTextures(bpy.types.Operator, Operator): +class UpdateStyleTextures(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.update_style_textures" bl_label = "Update Style Textures" bl_options = {"REGISTER", "UNDO"} @@ -55,7 +48,7 @@ class UpdateStyleTextures(bpy.types.Operator, Operator): ) -class RemoveStyle(bpy.types.Operator, Operator): +class RemoveStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.remove_style" bl_label = "Remove Style" bl_options = {"REGISTER", "UNDO"} @@ -65,7 +58,7 @@ class RemoveStyle(bpy.types.Operator, Operator): core.remove_style(tool.Ifc, tool.Material, tool.Style, style=tool.Ifc.get().by_id(self.style)) -class AddStyle(bpy.types.Operator, Operator): +class AddStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_style" bl_label = "Add Style" bl_options = {"REGISTER", "UNDO"} @@ -74,7 +67,7 @@ class AddStyle(bpy.types.Operator, Operator): core.add_style(tool.Ifc, tool.Style, obj=context.active_object.active_material) -class UnlinkStyle(bpy.types.Operator, Operator): +class UnlinkStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.unlink_style" bl_label = "Unlink Style" bl_options = {"REGISTER", "UNDO"} @@ -83,7 +76,7 @@ class UnlinkStyle(bpy.types.Operator, Operator): core.unlink_style(tool.Ifc, tool.Style, obj=context.active_object.active_material) -class EnableEditingStyle(bpy.types.Operator, Operator): +class EnableEditingStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.enable_editing_style" bl_label = "Enable Editing Style" bl_options = {"REGISTER", "UNDO"} @@ -92,7 +85,7 @@ class EnableEditingStyle(bpy.types.Operator, Operator): core.enable_editing_style(tool.Style, obj=context.active_object.active_material) -class DisableEditingStyle(bpy.types.Operator, Operator): +class DisableEditingStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.disable_editing_style" bl_options = {"REGISTER", "UNDO"} bl_label = "Disable Editing Style" @@ -101,7 +94,7 @@ class DisableEditingStyle(bpy.types.Operator, Operator): core.disable_editing_style(tool.Style, obj=context.active_object.active_material) -class EditStyle(bpy.types.Operator, Operator): +class EditStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.edit_style" bl_label = "Edit Style" bl_options = {"REGISTER", "UNDO"} @@ -110,7 +103,7 @@ class EditStyle(bpy.types.Operator, Operator): core.edit_style(tool.Ifc, tool.Style, obj=context.active_object.active_material) -class DisableEditingStyles(bpy.types.Operator, Operator): +class DisableEditingStyles(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.disable_editing_styles" bl_options = {"REGISTER", "UNDO"} bl_label = "Disable Editing Styles" @@ -119,7 +112,7 @@ class DisableEditingStyles(bpy.types.Operator, Operator): core.disable_editing_styles(tool.Style) -class LoadStyles(bpy.types.Operator, Operator): +class LoadStyles(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.load_styles" bl_label = "Load Styles" bl_options = {"REGISTER", "UNDO"} @@ -127,3 +120,13 @@ class LoadStyles(bpy.types.Operator, Operator): def _execute(self, context): core.load_styles(tool.Style, style_type=self.style_type) + + +class SelectByStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.select_by_style" + bl_label = "Select By Material" + bl_options = {"REGISTER", "UNDO"} + style: bpy.props.IntProperty() + + def _execute(self, context): + core.select_by_style(tool.Style, style=tool.Ifc.get().by_id(self.style)) diff --git a/src/blenderbim/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py index d41a3ad46f..86f4261866 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -57,8 +57,8 @@ class BIM_PT_styles(Panel): #row.operator("bim.add_presentation_style", text="", icon="ADD") if self.props.styles and self.props.active_style_index < len(self.props.styles): style = self.props.styles[self.props.active_style_index] - # op = row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF") - # op.style = style.ifc_definition_id + op = row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF") + op.style = style.ifc_definition_id row.operator("bim.remove_style", text="", icon="X").style = style.ifc_definition_id self.layout.template_list("BIM_UL_styles", "", self.props, "styles", self.props, "active_style_index") @@ -138,6 +138,6 @@ class BIM_UL_styles(UIList): if item: row = layout.row(align=True) row.label(text=item.name) - #row2 = row.row() - #row2.alignment = "RIGHT" - #row2.label(text=str(item.total_elements)) + row2 = row.row() + row2.alignment = "RIGHT" + row2.label(text=str(item.total_elements)) diff --git a/src/blenderbim/blenderbim/core/style.py b/src/blenderbim/blenderbim/core/style.py index 4cc8e32a01..e56f7dcc32 100644 --- a/src/blenderbim/blenderbim/core/style.py +++ b/src/blenderbim/blenderbim/core/style.py @@ -110,3 +110,7 @@ def load_styles(style, style_type=None): def disable_editing_styles(style): style.disable_editing_styles() + + +def select_by_style(style_tool, style=None): + style_tool.select_elements(style_tool.get_elements_by_style(style)) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 123bc1e5f5..bfc273fc10 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -443,6 +443,7 @@ class Style: def export_surface_attributes(cls, obj): pass def get_active_style_type(cls): pass def get_context(cls, obj): pass + def get_elements_by_style(cls, style): pass def get_name(cls, obj): pass def get_style(cls, obj): pass def get_surface_rendering_attributes(cls, obj): pass @@ -454,6 +455,7 @@ class Style: def import_presentation_styles(cls, style_type): pass def import_surface_attributes(cls, style, obj): pass def is_editing_styles(cls): pass + def select_elements(cls, elements): pass @interface diff --git a/src/blenderbim/blenderbim/tool/material.py b/src/blenderbim/blenderbim/tool/material.py index 1e47c643c7..0b3832ca24 100644 --- a/src/blenderbim/blenderbim/tool/material.py +++ b/src/blenderbim/blenderbim/tool/material.py @@ -46,7 +46,7 @@ class Material(blenderbim.core.tool.Material): @classmethod def get_elements_by_material(cls, material): - return set(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material)) + return ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material) @classmethod def get_name(cls, obj): @@ -75,13 +75,13 @@ class Material(blenderbim.core.tool.Material): new = props.materials.add() new.ifc_definition_id = material.id() new.name = get_name(material) - new.total_elements = len(set(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material))) - else: - for material in materials: - new = props.materials.add() - new.ifc_definition_id = material.id() - new.name = get_name(material) - new.total_elements = len(set(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material))) + new.total_elements = len(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material)) + return + for material in materials: + new = props.materials.add() + new.ifc_definition_id = material.id() + new.name = get_name(material) + new.total_elements = len(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material)) @classmethod def is_editing_materials(cls): diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 4c42e0ab57..a5031d5c60 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -56,6 +56,10 @@ class Style(blenderbim.core.tool.Style): def get_context(cls, obj): return ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW") + @classmethod + def get_elements_by_style(cls, style): + return ifcopenshell.util.element.get_elements_by_style(tool.Ifc.get(), style) + @classmethod def get_name(cls, obj): return obj.name @@ -188,6 +192,7 @@ class Style(blenderbim.core.tool.Style): new = props.styles.add() new.ifc_definition_id = style.id() new.name = style.Name or "Unnamed" + new.total_elements = len(ifcopenshell.util.element.get_elements_by_style(tool.Ifc.get(), style)) @classmethod def import_surface_attributes(cls, style, obj): @@ -197,3 +202,10 @@ class Style(blenderbim.core.tool.Style): @classmethod def is_editing_styles(cls): return bpy.context.scene.BIMStylesProperties.is_editing + + @classmethod + def select_elements(cls, elements): + for element in elements: + obj = tool.Ifc.get_object(element) + if obj: + obj.select_set(True) diff --git a/src/blenderbim/test/bim/feature/style.feature b/src/blenderbim/test/bim/feature/style.feature index 66ad775f2e..161c39d167 100644 --- a/src/blenderbim/test/bim/feature/style.feature +++ b/src/blenderbim/test/bim/feature/style.feature @@ -75,3 +75,13 @@ Scenario: Disable editing styles And I press "bim.load_styles(style_type='IfcSurfaceStyle')" When I press "bim.disable_editing_style" Then nothing happens + +Scenario: Select by style + Given an empty IFC project + And I add a cube + And I add a material + And I press "bim.add_style" + And I press "bim.load_styles(style_type='IfcSurfaceStyle')" + And the variable "style" is "{ifc}.by_type('IfcSurfaceStyle')[0].id()" + When I press "bim.select_by_style(style={style})" + Then nothing happens diff --git a/src/blenderbim/test/tool/test_style.py b/src/blenderbim/test/tool/test_style.py index dd39292dc7..53e147f9d9 100644 --- a/src/blenderbim/test/tool/test_style.py +++ b/src/blenderbim/test/tool/test_style.py @@ -95,6 +95,20 @@ class TestGetContext(NewFile): assert subject.get_context("obj") == context +class TestGetElementsByStyle(NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcWall") + style = ifc.createIfcSurfaceStyle() + item = ifc.createIfcExtrudedAreaSolid() + ifc.createIfcStyledItem(Item=item, Styles=[style]) + element.Representation = ifc.createIfcProductDefinitionShape( + Representations=[ifc.createIfcShapeRepresentation(Items=[item])] + ) + assert subject.get_elements_by_style(style) == {element} + + class TestGetName(NewFile): def test_run(self): assert subject.get_name(bpy.data.materials.new("Material")) == "Material" @@ -426,3 +440,15 @@ class TestIsEditingStyles(NewFile): subject.is_editing_styles() is False bpy.context.scene.BIMStylesProperties.is_editing = True subject.is_editing_styles() is True + + +class TestSelectElements(NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc().set(ifc) + element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcPump") + obj = bpy.data.objects.new("Object", None) + bpy.context.scene.collection.objects.link(obj) + tool.Ifc.link(element, obj) + subject.select_elements([element]) + assert obj in bpy.context.selected_objects diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index a3813e5d85..8f141cfaa3 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -134,25 +134,65 @@ def get_material(element, should_skip_usage=False): def get_elements_by_material(ifc_file, material): - results = [] + results = set() for inverse in ifc_file.get_inverse(material): if inverse.is_a("IfcRelAssociatesMaterial"): - results.extend(inverse.RelatedObjects) + results.update(inverse.RelatedObjects) elif inverse.is_a("IfcMaterialLayer"): for material_set in inverse.ToMaterialLayerSet: - results.extend(get_elements_by_material(ifc_file, material_set)) + results.update(get_elements_by_material(ifc_file, material_set)) elif inverse.is_a("IfcMaterialProfile"): for material_set in inverse.ToMaterialProfileSet: - results.extend(get_elements_by_material(ifc_file, material_set)) + results.update(get_elements_by_material(ifc_file, material_set)) elif inverse.is_a("IfcMaterialConstituent"): for material_set in inverse.ToMaterialConstituentSet: - results.extend(get_elements_by_material(ifc_file, material_set)) + results.update(get_elements_by_material(ifc_file, material_set)) elif inverse.is_a("IfcMaterialLayerSetUsage"): - results.extend(get_elements_by_material(ifc_file, inverse)) + results.update(get_elements_by_material(ifc_file, inverse)) elif inverse.is_a("IfcMaterialProfileSetUsage"): - results.extend(get_elements_by_material(ifc_file, inverse)) + results.update(get_elements_by_material(ifc_file, inverse)) elif inverse.is_a("IfcMaterialList"): - results.extend(get_elements_by_material(ifc_file, inverse)) + results.update(get_elements_by_material(ifc_file, inverse)) + return results + + +def get_elements_by_style(ifc_file, style): + results = set() + inverses = list(ifc_file.get_inverse(style)) + while inverses: + inverse = inverses.pop() + if inverse.is_a("IfcPresentationStyleAssignment"): + inverses.extend(ifc_file.get_inverse(inverse)) + continue + if not inverse.is_a("IfcStyledItem"): + continue + if inverse.Item: + [ + results.update(get_elements_by_representation(ifc_file, i)) + for i in ifc_file.get_inverse(inverse.Item) + if i.is_a("IfcShapeRepresentation") + ] + else: + styled_reps = [i for i in ifc_file.get_inverse(inverse) if i.is_a("IfcStyledRepresentation")] + for styled_rep in styled_reps: + for material_def_rep in styled_rep.OfProductRepresentation: + results.update(get_elements_by_material(ifc_file, material_def_rep.RepresentedMaterial)) + return results + + +def get_elements_by_representation(ifc_file, representation): + results = set() + [results.update(pr.ShapeOfProduct) for pr in representation.OfProductRepresentation] + for rep_map in representation.RepresentationMap: + for inverse in ifc_file.get_inverse(rep_map): + if inverse.is_a("IfcTypeProduct"): + results.add(inverse) + elif inverse.is_a("IfcMappedItem"): + [ + results.update(get_elements_by_representation(ifc_file, rep)) + for rep in ifc_file.get_inverse(inverse) + if rep.is_a("IfcShapeRepresentation") + ] return results diff --git a/src/ifcopenshell-python/test/util/test_element.py b/src/ifcopenshell-python/test/util/test_element.py index c00931252d..5ec3a49ad6 100644 --- a/src/ifcopenshell-python/test/util/test_element.py +++ b/src/ifcopenshell-python/test/util/test_element.py @@ -278,7 +278,7 @@ class TestGetElementsByMaterial(test.bootstrap.IFC4): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") material = ifcopenshell.api.run("material.add_material", self.file) ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material) - assert subject.get_elements_by_material(self.file, material) == [element] + assert subject.get_elements_by_material(self.file, material) == {element} def test_getting_elements_of_a_material_layer_set(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") @@ -290,9 +290,9 @@ class TestGetElementsByMaterial(test.bootstrap.IFC4): ifcopenshell.api.run("material.assign_material", self.file, product=element_type, material=material_set) ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialLayerSetUsage") usage = self.file.by_type("IfcMaterialLayerSetUsage")[0] - assert set(subject.get_elements_by_material(self.file, material)) == {element, element_type} - assert set(subject.get_elements_by_material(self.file, material_set)) == {element, element_type} - assert set(subject.get_elements_by_material(self.file, usage)) == {element} + assert subject.get_elements_by_material(self.file, material) == {element, element_type} + assert subject.get_elements_by_material(self.file, material_set) == {element, element_type} + assert subject.get_elements_by_material(self.file, usage) == {element} def test_getting_elements_of_a_material_profile_set(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") @@ -304,18 +304,20 @@ class TestGetElementsByMaterial(test.bootstrap.IFC4): ifcopenshell.api.run("material.assign_material", self.file, product=element_type, material=material_set) ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialProfileSetUsage") usage = self.file.by_type("IfcMaterialProfileSetUsage")[0] - assert set(subject.get_elements_by_material(self.file, material)) == {element, element_type} - assert set(subject.get_elements_by_material(self.file, material_set)) == {element, element_type} - assert set(subject.get_elements_by_material(self.file, usage)) == {element} + assert subject.get_elements_by_material(self.file, material) == {element, element_type} + assert subject.get_elements_by_material(self.file, material_set) == {element, element_type} + assert subject.get_elements_by_material(self.file, usage) == {element} def test_getting_elements_of_a_material_constituent_set(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") material = ifcopenshell.api.run("material.add_material", self.file) - material_set = ifcopenshell.api.run("material.add_material_set", self.file, set_type="IfcMaterialConstituentSet") + material_set = ifcopenshell.api.run( + "material.add_material_set", self.file, set_type="IfcMaterialConstituentSet" + ) ifcopenshell.api.run("material.add_constituent", self.file, constituent_set=material_set, material=material) ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material_set) - assert set(subject.get_elements_by_material(self.file, material)) == {element} - assert set(subject.get_elements_by_material(self.file, material_set)) == {element} + assert subject.get_elements_by_material(self.file, material) == {element} + assert subject.get_elements_by_material(self.file, material_set) == {element} def test_getting_elements_of_a_material_list(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") @@ -323,8 +325,97 @@ class TestGetElementsByMaterial(test.bootstrap.IFC4): material_set = ifcopenshell.api.run("material.add_material_set", self.file, set_type="IfcMaterialList") ifcopenshell.api.run("material.add_list_item", self.file, material_list=material_set, material=material) ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material_set) - assert set(subject.get_elements_by_material(self.file, material)) == {element} - assert set(subject.get_elements_by_material(self.file, material_set)) == {element} + assert subject.get_elements_by_material(self.file, material) == {element} + assert subject.get_elements_by_material(self.file, material_set) == {element} + + +class TestGetElementsByStyle(test.bootstrap.IFC4): + def test_getting_elements_of_a_styled_representation_item(self): + element = self.file.createIfcWall() + style = self.file.createIfcSurfaceStyle() + item = self.file.createIfcExtrudedAreaSolid() + self.file.createIfcStyledItem(Item=item, Styles=[style]) + element.Representation = self.file.createIfcProductDefinitionShape( + Representations=[self.file.createIfcShapeRepresentation(Items=[item])] + ) + assert subject.get_elements_by_style(self.file, style) == {element} + + def test_getting_elements_of_a_styled_mapped_representation_item(self): + element = self.file.createIfcWall() + style = self.file.createIfcSurfaceStyle() + item = self.file.createIfcExtrudedAreaSolid() + self.file.createIfcStyledItem(Item=item, Styles=[style]) + element.Representation = self.file.createIfcProductDefinitionShape( + Representations=[ + self.file.createIfcShapeRepresentation( + Items=[ + self.file.createIfcMappedItem( + MappingSource=self.file.createIfcRepresentationMap( + MappedRepresentation=self.file.createIfcShapeRepresentation(Items=[item]) + ) + ) + ] + ) + ] + ) + assert subject.get_elements_by_style(self.file, style) == {element} + + def test_getting_type_elements_of_a_styled_mapped_representation_item(self): + element = self.file.createIfcWallType() + style = self.file.createIfcSurfaceStyle() + item = self.file.createIfcExtrudedAreaSolid() + self.file.createIfcStyledItem(Item=item, Styles=[style]) + element.RepresentationMaps = [ + self.file.createIfcRepresentationMap( + MappedRepresentation=self.file.createIfcShapeRepresentation(Items=[item]) + ) + ] + assert subject.get_elements_by_style(self.file, style) == {element} + + def test_getting_elements_of_a_styled_material(self): + element = self.file.createIfcWall() + material = ifcopenshell.api.run("material.add_material", self.file) + ifcopenshell.api.run("material.assign_material", self.file, product=element, material=material) + style = self.file.createIfcSurfaceStyle() + self.file.createIfcMaterialDefinitionRepresentation( + RepresentedMaterial=material, + Representations=[ + self.file.createIfcStyledRepresentation(Items=[self.file.createIfcStyledItem(Styles=[style])]) + ], + ) + assert subject.get_elements_by_style(self.file, style) == {element} + + +class TestGetElementsByRepresentation(test.bootstrap.IFC4): + def test_getting_elements_of_a_styled_representation_item(self): + element = self.file.createIfcWall() + representation = self.file.createIfcShapeRepresentation() + element.Representation = self.file.createIfcProductDefinitionShape(Representations=[representation]) + assert subject.get_elements_by_representation(self.file, representation) == {element} + + def test_getting_elements_of_a_styled_mapped_representation_item(self): + element = self.file.createIfcWall() + representation = self.file.createIfcShapeRepresentation() + element.Representation = self.file.createIfcProductDefinitionShape( + Representations=[ + self.file.createIfcShapeRepresentation( + Items=[ + self.file.createIfcMappedItem( + MappingSource=self.file.createIfcRepresentationMap( + MappedRepresentation=representation + ) + ) + ] + ) + ] + ) + assert subject.get_elements_by_representation(self.file, representation) == {element} + + def test_getting_type_elements_of_a_styled_mapped_representation_item(self): + element = self.file.createIfcWallType() + representation = self.file.createIfcShapeRepresentation() + element.RepresentationMaps = [self.file.createIfcRepresentationMap(MappedRepresentation=representation)] + assert subject.get_elements_by_representation(self.file, representation) == {element} class TestGetlayers(test.bootstrap.IFC4):