diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index 171e138af5..8febab6b9b 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -484,6 +484,54 @@ class PolylineDecorator: return cls.input_panel + @classmethod + def calculate_x_y_and_z(cls, context): + try: + polyline_data = context.scene.BIMModelProperties.polyline_point + last_point_data = polyline_data[len(polyline_data) - 1] + except: + return + + snap_prop = context.scene.BIMModelProperties.snap_mouse_point[0] + snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z)) + last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z)) + second_to_last_point = None + if len(polyline_data) > 1: + second_to_last_point_data = polyline_data[len(polyline_data) - 2] + second_to_last_point = Vector( + (second_to_last_point_data.x, second_to_last_point_data.y, second_to_last_point_data.z) + ) + else: + second_to_last_point = Vector((0, 0, 0)) + + distance = float(cls.input_panel["D"]) + + if distance < 0 or distance > 0: + angle_rad = radians(180 - float(cls.input_panel["A"])) + ref_vec = second_to_last_point - last_point + dir_vec = last_point - snap_vector + + rot_axis = ref_vec.cross(dir_vec) + rot_axis.normalize() + rot_axis = Vector((abs(rot_axis.x), abs(rot_axis.y), abs(rot_axis.z))) + + rot_mat = Matrix.Rotation(angle_rad, 3, rot_axis) + + coords = ((ref_vec @ rot_mat) * distance) + last_point + + x = coords[0] + y = coords[1] + z = coords[2] + if cls.input_panel: + cls.input_panel["X"] = str(round(x, 4)) + cls.input_panel["Y"] = str(round(y, 4)) + if "Z" in list(cls.input_panel.keys()): + cls.input_panel["Z"] = str(round(z, 4)) + + return cls.input_panel + + return cls.input_panel + def draw_batch(self, shader_type, content_pos, color, indices=None): shader = self.line_shader if shader_type == "LINES" else self.shader batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices) diff --git a/src/bonsai/bonsai/tool/cad.py b/src/bonsai/bonsai/tool/cad.py index 109003c2ce..6693509d90 100644 --- a/src/bonsai/bonsai/tool/cad.py +++ b/src/bonsai/bonsai/tool/cad.py @@ -87,18 +87,30 @@ class Cad: @classmethod def angle_3_vectors(cls, v1, v2, v3, degrees=False): """ - > takes 3 vectors. The order matters, v2 is the center point. + > takes 3 vectors. The order matters, v2 is the center point. < returns the potentially signed angle as degrees or radians """ d1 = v1 - v2 d2 = v2 - v3 - cos_a = (d1.dot(d2)) / (d1.length * d2.length) - cos_a = max(-1, min(1, cos_a)) + axis = d1.cross(d2) + axis.normalize() + axis = Vector((abs(axis.x), abs(axis.y), abs(axis.z))) - a = math.acos(cos_a) + rotation_axis = d1.cross(d2) + + # Calculate the unsigned angle between the "from" and "to" vectors + a = d1.angle(d2) + + # Determine the sign of the angle based on the provided axis if degrees: - return math.degrees(a) + a = math.degrees(a) + + parameter = rotation_axis.dot(axis) + + sign = 1 if parameter <= 0 else -1 + + return a * sign else: return a