From fbd4177d08a476b04cccb6d9717c6f14850a5e74 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 19 Sep 2022 09:11:57 +1000 Subject: [PATCH] New feature to merge aligned walls and retain parametric connections --- .../blenderbim/bim/module/model/__init__.py | 5 +- .../blenderbim/bim/module/model/handler.py | 3 - .../blenderbim/bim/module/model/wall.py | 73 +++++++++++++++++++ .../blenderbim/bim/module/model/workspace.py | 4 + 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 7886169ca6..751778a97a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -26,11 +26,12 @@ classes = ( product.AlignProduct, product.DynamicallyVoidProduct, workspace.Hotkey, - wall.JoinWall, wall.AlignWall, wall.FlipWall, - wall.SplitWall, + wall.JoinWall, + wall.MergeWall, wall.RecalculateWall, + wall.SplitWall, opening.AddElementOpening, profile.ExtendProfile, prop.BIMModelProperties, diff --git a/src/blenderbim/blenderbim/bim/module/model/handler.py b/src/blenderbim/blenderbim/bim/module/model/handler.py index 407d896e16..b3c8be53ab 100644 --- a/src/blenderbim/blenderbim/bim/module/model/handler.py +++ b/src/blenderbim/blenderbim/bim/module/model/handler.py @@ -61,9 +61,6 @@ def load_post(*args): IfcStore.add_element_listener(slab.element_listener) IfcStore.add_element_listener(profile.element_listener) - ifcopenshell.api.add_post_listener( - "geometry.add_representation", "BlenderBIM.DumbWall.GenerateAxis", wall.generate_axis - ) ifcopenshell.api.add_post_listener( "geometry.add_representation", "BlenderBIM.DumbWall.CalculateQuantities", wall.calculate_quantities ) diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index 2eea7fc044..7522d65f68 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -185,6 +185,22 @@ class SplitWall(bpy.types.Operator): return {"FINISHED"} +class MergeWall(bpy.types.Operator): + bl_idname = "bim.merge_wall" + bl_label = "Merge Wall" + bl_options = {"REGISTER", "UNDO"} + + @classmethod + def poll(cls, context): + return context.selected_objects + + def execute(self, context): + selected_objs = [o for o in context.selected_objects if o.data and hasattr(o.data, "transform")] + if len(selected_objs) == 2: + DumbWallJoiner().merge([o for o in selected_objs if o != context.active_object][0], context.active_object) + return {"FINISHED"} + + class RecalculateWall(bpy.types.Operator): bl_idname = "bim.recalculate_wall" bl_label = "Recalculate Wall" @@ -754,6 +770,63 @@ class DumbWallJoiner: self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"]) self.recreate_wall(element2, wall2, axis2["reference"], axis2["reference"]) + def merge(self, wall1, wall2): + element1 = tool.Ifc.get_entity(wall1) + element2 = tool.Ifc.get_entity(wall2) + axis1 = self.get_wall_axis(wall1) + axis2 = self.get_wall_axis(wall2) + + angle = tool.Cad.angle_edges(axis1["reference"], axis2["reference"], signed=False, degrees=True) + if not tool.Cad.is_x(angle, 0): + return + + intersect1, connection1 = mathutils.geometry.intersect_point_line(axis2["reference"][0], *axis1["reference"]) + if not tool.Cad.is_x((intersect1 - axis2["reference"][0]).length, 0): + return + + intersect2, connection2 = mathutils.geometry.intersect_point_line(axis2["reference"][1], *axis1["reference"]) + if not tool.Cad.is_x((intersect2 - axis2["reference"][1]).length, 0): + return + + changed_connections = set() + + if connection1 < 0: + changed_connections.add("ATSTART") + axis1["reference"][0] = intersect2 if connection2 < connection1 else intersect1 + elif connection1 > 1: + changed_connections.add("ATEND") + axis1["reference"][1] = intersect2 if connection2 > connection1 else intersect1 + + for connection in changed_connections: + ifcopenshell.api.run("geometry.disconnect_path", tool.Ifc.get(), element=element1, connection_type=connection) + + for rel in element2.ConnectedTo: + if rel.RelatingConnectionType in changed_connections: + other = tool.Ifc.get_object(rel.RelatedElement) + ifcopenshell.api.run( + "geometry.connect_path", + tool.Ifc.get(), + relating_element=element1, + related_element=rel.RelatedElement, + relating_connection=rel.RelatingConnectionType, + related_connection=rel.RelatedConnectionType, + ) + + for rel in element2.ConnectedFrom: + if rel.RelatedConnectionType in changed_connections: + ifcopenshell.api.run( + "geometry.connect_path", + tool.Ifc.get(), + relating_element=rel.RelatingElement, + related_element=element1, + relating_connection=rel.RelatingConnectionType, + related_connection=rel.RelatedConnectionType, + ) + + self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"]) + bpy.data.objects.remove(wall2) + + def duplicate_wall(self, wall1): wall2 = wall1.copy() wall2.data = wall2.data.copy() diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py index d9c43f6298..9f3a21109c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -43,6 +43,7 @@ class BimTool(WorkSpaceTool): ("bim.hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}), ("bim.join_wall", {"type": "T", "value": "PRESS", "shift": True}, {"properties": [("join_type", "L")]}), ("bim.recalculate_wall", {"type": "Y", "value": "PRESS", "shift": True}, {"properties": []}), + ("bim.merge_wall", {"type": "M", "value": "PRESS", "shift": True}, {"properties": []}), ("bim.flip_wall", {"type": "F", "value": "PRESS", "shift": True}, {"properties": []}), ("bim.split_wall", {"type": "S", "value": "PRESS", "shift": True}, {"properties": []}), ("bim.hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_X")]}), @@ -141,6 +142,9 @@ class BimTool(WorkSpaceTool): row = layout.row(align=True) row.label(text="", icon="EVENT_SHIFT") row.label(text="Regen Connections", icon="EVENT_Y") + row = layout.row(align=True) + row.label(text="", icon="EVENT_SHIFT") + row.label(text="Merge", icon="EVENT_M") row = layout.row() row.label(text="Wall Tools")