diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py b/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py index 5f400f53b6..d953ec62df 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py @@ -8,6 +8,7 @@ import blenderbim.bim.module.geometry.add_representation as add_representation import blenderbim.bim.module.geometry.map_representation as map_representation import blenderbim.bim.module.geometry.assign_styles as assign_styles import blenderbim.bim.module.geometry.assign_representation as assign_representation +import blenderbim.bim.module.geometry.unassign_representation as unassign_representation import blenderbim.bim.module.geometry.remove_representation as remove_representation from blenderbim.bim.ifc import IfcStore from blenderbim.bim import import_ifc @@ -202,13 +203,21 @@ class SwitchRepresentation(bpy.types.Operator): class RemoveRepresentation(bpy.types.Operator): bl_idname = "bim.remove_representation" bl_label = "Remove Representation" - ifc_definition_id: bpy.props.IntProperty() + obj: bpy.props.StringProperty() # TODO + representation_id: bpy.props.IntProperty() def execute(self, context): self.file = IfcStore.get_file() - representation = self.file.by_id(self.ifc_definition_id) + representation = self.file.by_id(self.representation_id) obj = bpy.context.active_object - mesh = bpy.data.meshes.get("{}/{}".format(representation.ContextOfItems.id(), representation.id())) + product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + if representation.RepresentationType == "MappedRepresentation": + mesh_name = "{}/{}".format( + representation.ContextOfItems.id(), representation.Items[0].MappingSource.MappedRepresentation.id() + ) + else: + mesh_name = "{}/{}".format(representation.ContextOfItems.id(), representation.id()) + mesh = bpy.data.meshes.get(mesh_name) if mesh: if obj.data == mesh: # TODO we can do better than this @@ -216,9 +225,12 @@ class RemoveRepresentation(bpy.types.Operator): if not void_mesh: void_mesh = bpy.data.meshes.new("Void") obj.data = void_mesh - bpy.data.meshes.remove(mesh) + if representation.RepresentationType != "MappedRepresentation": + bpy.data.meshes.remove(mesh) + product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + unassign_representation.Usecase(self.file, {"product": product, "representation": representation}).execute() remove_representation.Usecase(self.file, {"representation": representation}).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + Data.load(product.id()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py b/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py index b5c83d1120..66ce5a0de8 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py +++ b/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py @@ -1,5 +1,6 @@ import ifcopenshell.util.element + class Usecase: def __init__(self, file, settings=None): self.file = file @@ -8,6 +9,20 @@ class Usecase: self.settings[key] = value def execute(self): + if self.settings["representation"].RepresentationType == "MappedRepresentation": + return self.remove_mapped_representation_portion_only() + return self.remove_entire_representation_tree() + + def remove_mapped_representation_portion_only(self): + dummy_context = self.file.create_entity("IfcRepresentationContext") + dummy_representation_map = self.file.createIfcRepresentationMap() + self.settings["representation"].ContextOfItems = dummy_context + for item in self.settings["representation"].Items: + item.MappingSource = dummy_representation_map + ifcopenshell.util.element.remove_deep(self.file, self.settings["representation"]) + self.file.remove(self.settings["representation"]) + + def remove_entire_representation_tree(self): dummy_context = self.file.create_entity("IfcRepresentationContext") for subelement in self.file.traverse(self.settings["representation"]): if subelement.is_a("IfcRepresentationItem") and subelement.StyledByItem: @@ -27,10 +42,3 @@ class Usecase: else: assigned_items.remove(element) inverse.AssignedItems = list(assigned_items) - elif inverse.is_a("IfcProductRepresentation"): - representations = set(inverse.Representations) - if len(representations) == 1: - self.file.remove(inverse) - else: - representations.remove(element) - inverse.Representations = list(representations) diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py b/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py index e04c33f644..34d94e10a1 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py @@ -41,7 +41,7 @@ class BIM_PT_representations(Panel): op = row.operator("bim.switch_representation", icon="OUTLINER_DATA_MESH", text="") op.ifc_definition_id = ifc_definition_id op.disable_opening_subtractions = False - row.operator("bim.remove_representation", icon="X", text="").ifc_definition_id = ifc_definition_id + row.operator("bim.remove_representation", icon="X", text="").representation_id = ifc_definition_id class BIM_PT_mesh(Panel): diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py b/src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py new file mode 100644 index 0000000000..a7a3a1ecaf --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py @@ -0,0 +1,57 @@ +import blenderbim.bim.module.geometry.remove_representation as remove_representation +import ifcopenshell.util.element + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = {"product": None, "representation": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.settings["product"].is_a("IfcProduct"): + self.unassign_product_representation(self.settings["product"], self.settings["representation"]) + elif self.settings["product"].is_a("IfcTypeProduct"): + self.unassign_type_representation() + + def unassign_product_representation(self, product, representation): + representations = list(product.Representation.Representations or []) + representations.remove(representation) + if not representations: + self.file.remove(product.Representation) + else: + product.Representation.Representations = representations + + def unassign_type_representation(self): + for representation_map in self.settings["product"].RepresentationMaps or []: + if representation_map.MappedRepresentation == self.settings["representation"]: + self.unassign_products_using_mapped_representation(representation_map) + self.remove_representation_map_only(representation_map) + break + self.settings["product"].RepresentationMaps = self.settings["product"].RepresentationMaps or None + + def remove_representation_map_only(self, representation_map): + dummy_representation = self.file.createIfcShapeRepresentation() + representation_map.MappedRepresentation = dummy_representation + ifcopenshell.util.element.remove_deep(self.file, representation_map) + self.file.remove(representation_map) + + def unassign_products_using_mapped_representation(self, representation_map): + mapped_representations = [] + just_representations = [] + for map_usage in representation_map.MapUsage or []: + for inverse in self.file.get_inverse(map_usage): + if not inverse.is_a("IfcShapeRepresentation"): + continue + for definition in inverse.OfProductRepresentation or []: + for product in definition.ShapeOfProduct or []: + mapped_representations.append({ + "product": product, + "representation": inverse + }) + just_representations.append(inverse) + for item in mapped_representations: + self.unassign_product_representation(item["product"], item["representation"]) + for representation in just_representations: + remove_representation.Usecase(self.file, {"representation": representation}).execute()