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;
}
}
}