From 284df2e4846453f7a78b5636d1e23382b4e4fa83 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 22 Feb 2024 15:24:09 +0500 Subject: [PATCH] update representation item style on editing/removing shape aspect Example - https://imgur.com/a/2SxgSRH --- .../bim/module/geometry/operator.py | 48 +++++++++++++++++-- src/blenderbim/blenderbim/tool/geometry.py | 47 ++++++++++++++++++ 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 456089417c..6e14628d64 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -1644,7 +1644,7 @@ class RemoveRepresentationItem(bpy.types.Operator, Operator): tool.Geometry.remove_representation_item(representation_item) tool.Geometry.reload_representation(obj) - # reload style ui + # reload items ui bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items() @@ -1716,7 +1716,7 @@ class EditRepresentationItemStyle(bpy.types.Operator, Operator): tool.Style.assign_style_to_representation_item(representation_item, surface_style) tool.Geometry.reload_representation(obj) - # reload style ui + # reload items ui bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items() @@ -1754,7 +1754,7 @@ class UnassignRepresentationItemStyle(bpy.types.Operator, Operator): tool.Style.assign_style_to_representation_item(representation_item, None) tool.Geometry.reload_representation(obj) - # reload style ui + # reload items ui bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items() @@ -1813,7 +1813,19 @@ class EditRepresentationItemShapeAspect(bpy.types.Operator, Operator): shape_aspect.Name = shape_aspect_attrs.name shape_aspect.Description = shape_aspect_attrs.description - # reload style ui + shape_aspect_representation = tool.Geometry.get_shape_aspect_representation_for_item( + shape_aspect, representation_item + ) + styles = tool.Geometry.get_shape_aspect_styles(element, shape_aspect, representation_item) + tool.Ifc.run( + "style.assign_representation_styles", + shape_representation=shape_aspect_representation, + styles=styles, + ) + tool.Geometry.get_shape_aspect_styles(element, shape_aspect, representation_item) + tool.Geometry.reload_representation(obj) + + # reload items ui bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items() @@ -1835,6 +1847,7 @@ class RemoveRepresentationItemFromShapeAspect(bpy.types.Operator, Operator): def _execute(self, context): obj = context.active_object + element = tool.Ifc.get_entity(obj) props = obj.BIMGeometryProperties ifc_file = tool.Ifc.get() @@ -1842,7 +1855,32 @@ class RemoveRepresentationItemFromShapeAspect(bpy.types.Operator, Operator): representation_item = ifc_file.by_id(representation_item_id) shape_aspect = ifc_file.by_id(props.items[props.active_item_index].shape_aspect_id) + # unassign items before removing items as removing items + # might remove shape aspect + if representation_item.StyledByItem: + styles = tool.Geometry.get_shape_aspect_styles(element, shape_aspect, representation_item) + self.remove_styles_from_item(representation_item, styles) + tool.Geometry.reload_representation(obj) + tool.Geometry.remove_representation_items_from_shape_aspect([representation_item], shape_aspect) - # reload style ui + + # reload items ui bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items() + + def remove_styles_from_item(self, representation_item, styles): + ifc_file = tool.Ifc.get() + styled_item = representation_item.StyledByItem[0] + new_styles = [s for s in styled_item.Styles if s not in styles] + styled_item.Styles = new_styles + + for style_ in new_styles: + if style_.is_a("IfcPresentationStyleAssignment"): + new_assignment_styles = [s for s in styled_item.Styles if s not in styles] + if not new_assignment_styles: + ifc_file.remove(style_) + else: + style_.Styles = new_assignment_styles + + if not styled_item.Styles: + ifc_file.remove(styled_item) diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py index 193bd1c921..77af31d01d 100644 --- a/src/blenderbim/blenderbim/tool/geometry.py +++ b/src/blenderbim/blenderbim/tool/geometry.py @@ -31,6 +31,7 @@ import blenderbim.bim.import_ifc from math import radians, pi from mathutils import Vector, Matrix from blenderbim.bim.ifc import IfcStore +from typing import List class Geometry(blenderbim.core.tool.Geometry): @@ -872,6 +873,52 @@ class Geometry(blenderbim.core.tool.Geometry): shape_aspect.ShapeRepresentations = shape_aspect.ShapeRepresentations + (shape_aspect_representation,) return shape_aspect_representation + @classmethod + def get_shape_aspect_representation_for_item(cls, shape_aspect, representation_item): + ifc_file = tool.Ifc.get() + for inverse in ifc_file.get_inverse(representation_item): + if inverse.is_a("IfcShapeRepresentation"): + if inverse.OfShapeAspect: + if inverse.OfShapeAspect[0] == shape_aspect: + return inverse + + @classmethod + def get_shape_aspect_styles(cls, element, shape_aspect, representation_item) -> List[ifcopenshell.entity_instance]: + """update `representation_item` style based on styles connected to the `shape_aspect` + through material constituents with the same name + """ + if not shape_aspect.Name: + return [] + + # get material connected to the shape aspect with material constituent name + material = ifcopenshell.util.element.get_material(element, should_skip_usage=True) + if not material or not material.is_a("IfcMaterialConstituentSet") or not material.MaterialConstituents: + return [] + + matching_constituent = next((c for c in material.MaterialConstituents if c.Name == shape_aspect.Name), None) + if matching_constituent is None: + return [] + + constituent_material = matching_constituent.Material + if not constituent_material.HasRepresentation: + return [] + + # get shape aspect representation for item + shape_aspect_representation = cls.get_shape_aspect_representation_for_item(shape_aspect, representation_item) + + # get the styles for this context + material_representation = None + for r in constituent_material.HasRepresentation[0].Representations: + if r.ContextOfItems == shape_aspect_representation.ContextOfItems: + material_representation = r + break + + if material_representation is None: + return [] + + styles = [s for s in tool.Ifc.get().traverse(material_representation) if s.is_a("IfcPresentationStyle")] + return styles + @classmethod def delete_opening_object_placement(cls, placement): model = tool.Ifc.get()