from mathutils import * from math import * import bpy def angle_to_length(angle: float, target: float = 1.0) -> float: """ Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 180deg(!). The distance is clamped to the target value. :param angle: Input angle (in radians) :type angle: float :param target: Desired distance between end points, defaults to 1.0 :type target: float, optional :return: The distance between two points :rtype: float """ if angle > 0: return (target * 0.5 * sin(pi - angle)) / sin(angle * 0.5) # School trigonometry else: return target def half_angle_to_length(angle: float, target: float = 1.0) -> float: """ Converts input angle to distance between two points in imaginary isosceles triangle with default angle of 90deg. The distance is clamped to the target value. :param angle: Input angle (in radians) :type angle: float :param target: Desired distance between end points, defaults to 1.0 :type target: float, optional :return: The distance between two points :rtype: float """ side = sqrt(pow(target, 2) * 0.5) # Length of imaginary triangle's side angle = abs(pi * 0.5 - angle) # Default angle is 90deg return (side * sin(angle)) / sin((pi - angle) * 0.5) def angle_compensation(angle: float) -> float: side_len = sqrt(pow(pi * 0.5, 2) * 0.5) # Length of imaginary triangle's side distance = 0.5 # Distance to which move bone to angle = abs(pi - angle) # Compensate non-linear input angle if angle > 0: comp_angle = (side_len * 0.5 * sin(angle)) / sin(angle * 0.5) else: comp_angle = side_len return (sqrt(pow(tan(comp_angle), 2) + 1) - 1) * distance def half_angle_compensation(angle: float) -> float: side = sqrt(pow(pi * 0.25, 2) * 0.5) # Length of imaginary triangle's side angle = abs(angle) final_angle = (side * sin(angle)) / sin((pi - angle) * 0.5) # Width of imaginary triangle's base return sqrt(pow(tan(final_angle), 2) + 1) - 1 # What the fuck?? def test_compensation(angle: float) -> float: side = sqrt(pow(pi * 0.5, 2) * 0.5) # Triangle's side is now a desired output angle in radians angle = abs(pi - angle) # Rotate default angle to 180deg return angle_to_length(angle, side) def test_half_compensation(angle: float) -> float: side = pi * 0.25 angle = abs(pi * 0.5 + angle) # Rotate default angle to 90deg return half_angle_to_length(angle, side) bpy.app.driver_namespace["angle_to_length"] = angle_to_length bpy.app.driver_namespace["half_angle_to_length"] = half_angle_to_length bpy.app.driver_namespace["angle_compensation"] = angle_compensation bpy.app.driver_namespace["half_angle_compensation"] = half_angle_compensation bpy.app.driver_namespace["test_compensation"] = test_compensation bpy.app.driver_namespace["test_half_compensation"] = test_half_compensation