From 66f735fde91460179b2de2c3028797c2322ad40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Wed, 18 Oct 2023 21:36:04 -0300 Subject: [PATCH] wip: refactor of RefreshLinkedAggregate. The operator triggers all the other linked aggregates deletion. --- .../bim/module/geometry/__init__.py | 2 +- .../bim/module/geometry/operator.py | 220 +++--------------- 2 files changed, 37 insertions(+), 185 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py index 5a93370d23..611795167b 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py @@ -39,7 +39,7 @@ classes = ( operator.OverrideOutlinerDelete, operator.OverridePasteBuffer, operator.PurgeUnusedRepresentations, - operator.RefreshAggregate, + operator.RefreshLinkedAggregate, operator.RemoveConnection, operator.RemoveRepresentation, operator.SelectConnection, diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 8798875796..767deeba9a 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -949,13 +949,12 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): if self.group_name in product_groups_name: return - linked_aggregate_group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name="Linked Aggregate") + linked_aggregate_group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), Name=self.group_name) ifcopenshell.api.run( "group.assign_group", tool.Ifc.get(), products=[element], group=linked_aggregate_group ) - ### Check if only one element and it's assembly if len(context.selected_objects) != 1: return {"FINISHED"} @@ -976,7 +975,6 @@ class DuplicateMoveLinkedAggregate(bpy.types.Operator): old_to_new = OverrideDuplicateMove.execute_ifc_duplicate_operator(self, context, linked=True) - # TODO Test with a sub aggregate added later for old_element, new_element in old_to_new.items(): old_parent = ifcopenshell.util.element.get_aggregate(old_element) if old_parent: @@ -1012,208 +1010,62 @@ class RefreshLinkedAggregate(bpy.types.Operator): return {"FINISHED"} def _execute(self, context): - self.new_active_obj = None - old_to_new = {} + self.group_name = 'Linked Aggregate' - def remove_objects(entity, level=-1, parents=[]): - level += 1 - if level == 0: - parents = [entity] - parts = ifcopenshell.util.element.get_parts(entity) - for part in parts: - if part.is_a("IfcElementAssembly"): - parents.append(part) - remove_objects(part, level, parents) - continue - else: - part_obj = tool.Ifc.get_object(part) - if part_obj: - tool.Geometry.delete_ifc_object(part_obj) - - return parents - - def duplicate_children(entity): - pset = ifcopenshell.util.element.get_pset(entity, "BBIM_Aggregate_Data") - pset_data = json.loads(pset["Data"])[0] - instance_of = pset_data["instance_of"][0] - - instance_entity = tool.Ifc.get().by_guid(instance_of) - - if not instance_entity.is_a("IfcElementAssembly"): - return - else: - parts = ifcopenshell.util.element.get_parts(instance_entity) + def delete_objects(element): + parts = ifcopenshell.util.element.get_parts(element) + if parts: for part in parts: - pset = ifcopenshell.util.element.get_pset(part, "BBIM_Aggregate_Data") if part.is_a("IfcElementAssembly"): - if not pset: - data_children = { - "children": [], - "instance_of": [part.GlobalId], - } - data = [data_children] - - pset = ifcopenshell.api.run( - "pset.add_pset", tool.Ifc.get(), product=part, name="BBIM_Aggregate_Data" - ) - ifcopenshell.api.run( - "pset.edit_pset", - tool.Ifc.get(), - pset=pset, - properties={"Parent": instance_entity.GlobalId, "Data": json.dumps(data)}, - ) - - part_obj = tool.Ifc.get_object(part) - new_part = duplicate_objects(part_obj) - - blenderbim.core.aggregate.assign_object( - tool.Ifc, - tool.Aggregate, - tool.Collector, - relating_obj=tool.Ifc.get_object(entity), - related_obj=tool.Ifc.get_object(new_part), - ) - duplicate_children(new_part) - - for part in parts: - pset = ifcopenshell.util.element.get_pset(part, "BBIM_Aggregate_Data") - if part.is_a("IfcElementAssembly"): - pass - - else: - if not pset: - pset = ifcopenshell.api.run( - "pset.add_pset", tool.Ifc.get(), product=part, name="BBIM_Aggregate_Data" - ) - else: - pset = ifcopenshell.util.element.get_pset(part, "BBIM_Aggregate_Data") - pset = tool.Ifc.get().by_id(pset["id"]) - - data_children = { - "children": [], - "instance_of": [], - } - data = [data_children] + delete_objects(part) + tool.Geometry.delete_ifc_object(tool.Ifc.get_object(part)) - ifcopenshell.api.run( - "pset.edit_pset", - tool.Ifc.get(), - pset=pset, - properties={"Parent": instance_entity.GlobalId, "Data": json.dumps(data)}, - ) - - part_obj = tool.Ifc.get_object(part) - new_part = duplicate_objects(part_obj) - blenderbim.core.aggregate.assign_object( - tool.Ifc, - tool.Aggregate, - tool.Collector, - relating_obj=tool.Ifc.get_object(entity), - related_obj=tool.Ifc.get_object(new_part), - ) - - def duplicate_objects(obj, is_root=False): - new_obj = obj.copy() - if obj.data: - new_obj.data = obj.data.copy() - if obj == context.active_object: - self.new_active_obj = new_obj - for collection in obj.users_collection: - collection.objects.link(new_obj) - obj.select_set(False) - new_obj.select_set(True) + tool.Geometry.delete_ifc_object(tool.Ifc.get_object(element)) - # This is needed to make sure the new object gets unlink from - # the old object assembly collection - new_obj.BIMObjectProperties.collection = None - - # Copy the actual class - new_entity = blenderbim.core.root.copy_class( - tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=new_obj - ) - - if new_entity: - tool.Model.handle_array_on_copied_element(new_entity) - - if not new_entity.is_a("IfcElementAssembly"): - blenderbim.core.aggregate.unassign_object( - tool.Ifc, - tool.Aggregate, - tool.Collector, - relating_obj=obj, - related_obj=tool.Ifc.get_object(new_entity), - ) - - old_to_new[tool.Ifc.get_entity(obj)] = [new_entity] - - return new_entity - + if len(context.selected_objects) != 1: - self.report({"INFO"}, "Only 1 object need to be selected.") return {"FINISHED"} - selected_root_obj = context.selected_objects[0] - selected_root_entity = tool.Ifc.get_entity(selected_root_obj) + selected_obj = context.selected_objects[0] + selected_element = tool.Ifc.get_entity(selected_obj) - if selected_root_entity.is_a("IfcElementAssembly"): + if selected_element.is_a("IfcElementAssembly"): pass - elif selected_root_entity.Decomposes: - if selected_root_entity.Decomposes[0].RelatingObject.is_a("IfcElementAssembly"): - selected_root_entity = selected_root_entity.Decomposes[0].RelatingObject - selected_root_obj = tool.Ifc.get_object(selected_root_entity) + elif selected_element.Decomposes: + if selected_element.Decomposes[0].RelatingObject.is_a("IfcElementAssembly"): + selected_element = selected_element.Decomposes[0].RelatingObject + selected_obj = tool.Ifc.get_object(selected_element) else: self.report({"INFO"}, "Object is not part of a IfcElementAssembly.") return {"FINISHED"} - - pset = ifcopenshell.util.element.get_pset(selected_root_entity, "BBIM_Aggregate_Data") - if not pset: - self.report({"INFO"}, "Object is not part of an assembly aggregate.") - return {"FINISHED"} - - pset_data = json.loads(pset["Data"])[0] - instance_of = pset_data["instance_of"][0] - original_root_entity = tool.Ifc.get().by_guid(instance_of) - if original_root_entity == selected_root_entity: - self.report({"INFO"}, "Cannot refresh original assembly. Select an assembly instance.") - return {"FINISHED"} - - parents = remove_objects(selected_root_entity) - - original_root_object = tool.Ifc.get_object(original_root_entity) - - selected_matrix = selected_root_obj.matrix_world - original_matrix = original_root_object.matrix_world - - for parent in parents: - duplicate_children(parent) - + product_linked_agg_group = [ + r.RelatingGroup + for r in getattr(selected_element, "HasAssignments", []) or [] + if r.is_a("IfcRelAssignsToGroup") + if self.group_name in r.RelatingGroup.Name + ] + selection_group = product_linked_agg_group[0].id() - # Remove connections with old objects - for new in old_to_new.values(): - for connection in new[0].ConnectedTo: - entity = connection.RelatedElement - if entity in old_to_new.keys(): - core.remove_connection(tool.Geometry, connection=connection) - for connection in new[0].ConnectedFrom: - entity = connection.RelatingElement - if entity in old_to_new.keys(): - core.remove_connection(tool.Geometry, connection=connection) + elements = tool.Drawing.get_group_elements(tool.Ifc.get().by_id(selection_group)) + for element in elements: + if element.GlobalId == selected_element.GlobalId: + continue + matrix = tool.Ifc.get_object(element).matrix_world + delete_objects(element) + # tool.Spatial.select_products(elements) - old_objs = [] - for old, new in old_to_new.items(): - old_objs.append(tool.Ifc.get_object(old)) + # DONE Select all Objects - new_obj = tool.Ifc.get_object(new[0]) + # DONE Store matrix - matrix_diff = Matrix.inverted(original_matrix) @ new_obj.matrix_world - new_matrix = selected_matrix @ matrix_diff + # DONE Delete Objects - new_obj.matrix_world = new_matrix + # Call a Function from DuplicateMoveLinkedAggregate + # Refactor the code into a function to be called - relationships = tool.Root.get_decomposition_relationships(old_objs) + # Old to New change matrix - tool.Root.recreate_decompositions(relationships, old_to_new) blenderbim.bim.handler.refresh_ui_data()