From 67b0ab6685f771ab9111219f0000fb3e5c5ed2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Sat, 15 Mar 2025 20:52:49 -0300 Subject: [PATCH] Fix #6366. Improve extrusion x_angle and direction handling. This solution brings new questions to #5938. Currently, we lack a reliable way to calculate the existing x_angle only based solely on the extrusion direction. For example, a 30 degree angled extrusion with positive direction has the same extrusion direction as a -150 degree angled extrusion with negative direction. The difference lies in the object's rotation. This means that things can get messy if the user changes the object x angle somehow. We may need to explore alternative approaches. --- src/bonsai/bonsai/bim/module/model/slab.py | 14 +++++++++----- src/bonsai/bonsai/bim/module/model/wall.py | 13 +++++++++---- src/bonsai/bonsai/tool/collector.py | 3 +++ src/bonsai/bonsai/tool/geometry.py | 4 ++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/slab.py b/src/bonsai/bonsai/bim/module/model/slab.py index 8d12a15049..ad553bbfc7 100644 --- a/src/bonsai/bonsai/bim/module/model/slab.py +++ b/src/bonsai/bonsai/bim/module/model/slab.py @@ -297,14 +297,16 @@ class DumbSlabPlaner: if representation: extrusion = tool.Model.get_extrusion(representation) if extrusion: - existing_x_angle = tool.Model.get_existing_x_angle(extrusion) + # TODO Right now we don't have a reliable way to calculate the existing x_angle only based solely on the extrusion direction. + # For instances, a 30 degrees angled extrusion with positive direction has the same extrusion direction as a + # -150 degrees angled extrusion with negative direction. The difference lies in the object's rotation. + # This means that things can get messy if the user changes the object x angle somehow. We have to figure out an alternative approach. + existing_x_angle = obj.rotation_euler.x existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 0, tolerance=0.001) else existing_x_angle existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, pi, tolerance=0.001) else existing_x_angle existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 2 * pi, tolerance=0.001) else existing_x_angle direction_ratios = Vector(extrusion.ExtrudedDirection.DirectionRatios) - offset_direction = Vector( - (abs(direction_ratios.x), abs(direction_ratios.y), abs(direction_ratios.z)) - ) # The offset direction doesn't change with direction sense + offset_direction = direction_ratios.copy() perpendicular_depth = thickness * abs(1 / cos(existing_x_angle)) perpendicular_offset = layer_params["offset"] * abs(1 / cos(existing_x_angle)) / self.unit_scale @@ -320,7 +322,9 @@ class DumbSlabPlaner: abs(existing_x_angle) < (pi / 2) and direction_ratios.z < 0 ): # The extrusion direction is negative. If the layer_parameter is set to positive, - # then the we change the extrusion direction. + # then the we change the extrusion direction. And the offset direction should remain positive + # for either direction sense, so we change it. + offset_direction *= -1 if layer_params["direction_sense"] == "POSITIVE": direction_ratios *= -1 diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 6c74184083..ed3e32702e 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -307,6 +307,9 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator): extrusion.Depth = perpendicular_depth else: if tool.Model.get_usage_type(element) == "LAYER3": + existing_x_angle = obj.rotation_euler.x + existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 0, tolerance=0.001) else existing_x_angle + existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, pi, tolerance=0.001) else existing_x_angle # Reset the transformation and returns to the original points with 0 degrees extrusion.SweptArea.OuterCurve.Points.CoordList = [ (p[0], p[1] * abs(cos(existing_x_angle))) @@ -325,9 +328,7 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator): layer_params = tool.Model.get_material_layer_parameters(element) perpendicular_depth = layer_params["thickness"] * abs(1 / cos(x_angle)) / unit_scale perpendicular_offset = layer_params["offset"] * abs(1 / cos(x_angle)) / unit_scale - offset_direction = Vector( - (abs(direction_ratios.x), abs(direction_ratios.y), abs(direction_ratios.z)) - ) # The offset direction doesn't change with direction sense + offset_direction = direction_ratios.copy() # Check angle and z direction to determine whether the extrusion direction is positive or negative if (abs(x_angle) < (pi / 2) and direction_ratios.z > 0) or ( @@ -342,6 +343,9 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator): ): # The extrusion direction is negative. If the layer_parameter is set to positive, # then the we change the extrusion direction. + # then the we change the extrusion direction. And the offset direction should remain positive + # for either direction sense, so we change it. + offset_direction *= -1 if layer_params["direction_sense"] == "POSITIVE": direction_ratios *= -1 @@ -363,9 +367,10 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator): ) # Object rotation + current_z_rot = obj.rotation_euler.z rot_mat = mathutils.Matrix.Rotation(x_angle, 4, "X") - rot_mat = obj.matrix_world @ rot_mat obj.rotation_euler = rot_mat.to_euler() + obj.rotation_euler.z = current_z_rot if layer2_objs: DumbWallRecalculator().recalculate(layer2_objs) diff --git a/src/bonsai/bonsai/tool/collector.py b/src/bonsai/bonsai/tool/collector.py index a93b5e405f..55bcd75f05 100644 --- a/src/bonsai/bonsai/tool/collector.py +++ b/src/bonsai/bonsai/tool/collector.py @@ -44,6 +44,9 @@ class Collector(bonsai.core.tool.Collector): # Note that tool.Geometry.is_locked is only checked within the if # statements for efficiency as it is a slow check. tool.Geometry.lock_scale(obj) + if element.is_a("IfcSlab"): + tool.Geometry.lock_rotation(obj, x=True) + if element.is_a("IfcGridAxis"): if tool.Geometry.is_locked(element): diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 81cffcece3..cca73f3fb4 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -177,6 +177,10 @@ class Geometry(bonsai.core.tool.Geometry): def unlock_scale(cls, obj: bpy.types.Object) -> None: obj.lock_scale = (False, False, False) + @classmethod + def lock_rotation(cls, obj: bpy.types.Object, x: bool=False, y: bool=False, z: bool=False,) -> None: + obj.lock_rotation = (x, y, z) + @classmethod def unlock_scale_object_with_openings(cls, obj: bpy.types.Object) -> None: element = tool.Ifc.get_entity(obj)