using UnityEngine; namespace AstroDX.Utilities { public static class Trigonometry { public const float Tau = Mathf.PI * 2; public static Vector2 Rotate(in this Vector2 v, in float degreesRad) { var magnitude = v.magnitude; var originalDegrees = Mathf.Atan2(v.y, v.x); var newDegrees = originalDegrees + degreesRad; var newX = Mathf.Cos(newDegrees) * magnitude; var newY = Mathf.Sin(newDegrees) * magnitude; return new Vector2(newX, newY); } /// /// Calculates a point's angle relative to a center point. /// /// The absolute position of a point. /// The offset of the calculation's center point. /// The relative angle of a point from the given center point. internal static float ToPolarAngle(in Vector2 position, in Vector2? offset = null) { if (!offset.HasValue) return Mathf.Atan2(position.y, position.x); var difference = position - offset.Value; return Mathf.Atan2(difference.y, difference.x); } /// /// Calculates the angle between a line to a point on a ring /// and another line perpendicular from a tangent line of that point. /// /// /// /// /// internal static float GetTangentAngleDelta(in float adjacent, in float hypotenuse, in bool clockwise) { var angleDiff = Mathf.Acos(adjacent / hypotenuse); return clockwise ? -angleDiff : angleDiff; } /// /// /// Calculates the angle between startRotation and endRotation, /// given its traversing direction. /// /// /// The starting rotation. /// The ending rotation. /// Traversing direction. /// /// Wraps to full circle for spans smaller than this value. /// Tau / 4f is recommended for offset circles /// /// /// The span between the starting rotation and the ending rotation on a unit circle, /// in radians. /// public static float GetAngleSpan(in float startRotation, in float endRotation, bool clockwise, float wrapThreshold = Tau / 32f) { var span = clockwise ? (startRotation - endRotation + 2 * Tau) % Tau : (endRotation - startRotation + 2 * Tau) % Tau; if (span <= wrapThreshold) span += Tau; return span; } } }