From bdcadfd1000cc0032d6215557c46ae1da6c240a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Fri, 30 Aug 2024 17:23:48 -0300 Subject: [PATCH] Refactor tool.Cad.angle_3_vectors This functions was built to work with the input calculations for the polytool. Part of its code was being duplicated in another part of the code. The refactor keeps most of the calculation in the same place. --- .../bonsai/bim/module/model/decorator.py | 17 ++--------- src/bonsai/bonsai/tool/cad.py | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index 56e8ab07d1..69fa8a7aee 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -413,7 +413,7 @@ class PolylineDecorator: distance = (snap_vector - last_point).length if distance > 0: - angle = tool.Cad.angle_3_vectors(second_to_last_point, last_point, snap_vector, degrees=True) + angle = tool.Cad.angle_3_vectors(second_to_last_point, last_point, snap_vector, new_angle=None, degrees=True) if cls.input_panel: cls.input_panel["X"] = str(round(snap_vector.x, 3)) cls.input_panel["Y"] = str(round(snap_vector.y, 3)) @@ -496,20 +496,7 @@ class PolylineDecorator: if distance < 0 or distance > 0: angle = radians(float(cls.input_panel["A"])) - # TODO This is basically the reverse process of tool.Cad.angle_3_vectors - # Combine them into a single function - v1 = second_to_last_point - last_point - v2 = snap_vector - last_point - - v1.normalize() - v2.normalize() - - # Calculate the axis of rotation - axis = v1.cross(v2).normalized() - rot_mat = Matrix.Rotation(angle, 3, axis) - parameter = round(axis.z, 2) < 0 or (round(axis.y, 2) == 0 and round(axis.x < 0)) or (round(axis.x, 2) == 0 and round(axis.y < 0)) - - rot_vector = (v1 @ rot_mat) if parameter else (rot_mat @ v1) + rot_vector = tool.Cad.angle_3_vectors(second_to_last_point, last_point, snap_vector, angle, degrees=True) coords = rot_vector * distance + last_point diff --git a/src/bonsai/bonsai/tool/cad.py b/src/bonsai/bonsai/tool/cad.py index 419edc49d6..bd735cda98 100644 --- a/src/bonsai/bonsai/tool/cad.py +++ b/src/bonsai/bonsai/tool/cad.py @@ -85,32 +85,39 @@ class Cad: return math.degrees(a) if degrees else a @classmethod - def angle_3_vectors(cls, v1, v2, v3, degrees=False): + def angle_3_vectors(cls, v1, v2, v3, new_angle=None, degrees=False): """ > takes 3 vectors. The order matters, v2 is the center point. < returns the signed angle as degrees or radians + < if a new angle is provided, return the rotation vector """ d1 = v1 - v2 d2 = v3 - v2 - axis = d1.cross(d2) - print(axis) - print(round(axis.z, 2)) - axis.normalize() + d1.normalize() + d2.normalize() + + axis = d1.cross(d2).normalized() # Calculate the unsigned angle between the "d1" and "d2" vectors a = d1.angle(d2) # Determine the sign of the angle based on the provided axis + # If new_angle, determine the direction of the rotation parameter = round(axis.z, 2) < 0 or (round(axis.y, 2) == 0 and round(axis.x < 0)) or (round(axis.x, 2) == 0 and round(axis.y < 0)) - sign = -1 if parameter else 1 - - if degrees: - a = math.degrees(a) - return a * sign + if new_angle: + rot_mat = Matrix.Rotation(new_angle, 3, axis) + rot_vector = (d1 @ rot_mat) if parameter else (rot_mat @ d1) + return rot_vector else: - return a + sign = -1 if parameter else 1 + + if degrees: + a = math.degrees(a) + return a * sign + else: + return a @classmethod def is_x(cls, value: float, x: float, tolerance: float | None = None) -> bool: