// Converts an angle to an equivalent angle within the range with the given center. // The range will always be 360 degrees in size. public Angle Remainder(Angle centerOfTheInterval) { IntervalFloat interval = IntervalFloat.FromCenterRadius( centerOfTheInterval.GetDegrees(), 180.0f); degrees = interval.Remainder(degrees); return(this); }
// Converts an angle to an equivalent angle within the range with the given center. // The range will always be 360 degrees in size. public Angle ToCoterminal(Angle centerOfTheInterval) { IntervalFloat interval = IntervalFloat.FromRadius( 180.0f, centerOfTheInterval.GetDegrees()); degrees = interval.Remainder(degrees); return(this); }
// Converts an angle to an equivalent angle within the range with the given center. // The range will always be 360 degrees in size. public Angle MoveIntoInterval(Angle centerOfTheInterval) { IntervalFloat interval = IntervalFloat.FromCenterRadius( centerOfTheInterval.GetDegrees(), 180.0f); degrees = UtilPeriodic.MoveIntoInterval(degrees, interval); return(this); }
// Like the approach float function, but rotates current along the shortest path // to the target, like an angle moving along a circle towards a different angle. public static float Approach(float current, float target, float stepSize, IntervalFloat interval) { current = MoveIntoInterval(current, interval); target = MoveIntoInterval(target, interval); if (GetSmallerDistance(current, target, interval) < stepSize) { return(target); } current += stepSize * SignShortestRotation(current, target, interval); return(current); }
// Returns the larger distance between the two values. public static float GetLargerDistance(float value1, float value2, IntervalFloat interval) { float distance = GetSomeDistance(value1, value2, interval); if (distance <= interval.GetCenter()) { return(interval.GetDiameter() - distance); } else { return(distance); } }
// Returns one of the two distances between the two values on the interval. // This accounts for the distance traveled via wrapping across the ends of the interval. // There's no guarantee whether this will be the smaller distance or the larger distance. private static float GetSomeDistance(float value1, float value2, IntervalFloat interval) { return(MoveIntoInterval(Mathf.Abs(value1 - value2), interval)); /* * float degrees = Mathf.Abs(angle1.GetDegrees() - angle2.GetDegrees()); * return Angle.FromDegrees(degrees).ToUnsignedRange(); */ /* * return AngleDegreesToUnsignedRange( * Mathf.Abs(angle1.GetDegrees() - angle2.GetDegrees())); */ }
// Moves the given value into the range, preserving the value's position in the period. public static float MoveIntoInterval(float value, IntervalFloat interval) { float start = interval.GetStart(); float end = interval.GetEnd(); float diameter = interval.GetDiameter(); while (value >= end) { value -= diameter; } while (value < start) { value += diameter; } return(value); }
// Returns true if the shortest path between the two given values can be // traversed by a positive increase from the start value. public static bool IsShortestRotationPositive(float start, float end, IntervalFloat interval) { // Normalize the start and end values to be within the interval. start = MoveIntoInterval(start, interval); end = MoveIntoInterval(end, interval); // Whether the shortest rotation involves stepping (wrapping) // across the ends of the interval. // True means it doesn't need to wrap. False means it does. bool wrapless = Mathf.Abs(start - end) < interval.GetCenter(); if (start < end) { return(wrapless); } else { return(!wrapless); } }
// Mirrors a value across the x-axis of a circle. public static float MirrorVertical(float value, IntervalFloat interval) { return(MoveIntoInterval(-value, interval)); }
// Mirrors a value across the y-axis of a circle. public static float MirrorHorizontal(float value, IntervalFloat interval) { return(MoveIntoInterval(interval.GetCenter() - value, interval)); }
// Moves a value to the opposite end of a circle. // This is effectively the same as rotating by 180 degrees. public static float Reverse(float value, IntervalFloat interval) { return(MoveIntoInterval(value + interval.GetRadius(), interval)); }
// Returns the sign of the shortest rotation between the two values. public static int SignShortestRotation(float start, float end, IntervalFloat interval) { return(UtilMath.Sign(IsShortestRotationPositive(start, end, interval))); }
// Returns a random angle measure within the given interval. public static Angle FromRandomDegrees(IntervalFloat interval) { return(Angle.FromDegrees(interval.GetRandom())); }
// Change the interval that the float exists on. public void SetInterval(IntervalFloat newInterval) { interval = newInterval; ConstrainValue(); }
// Constructor. public ModularFloat(IntervalFloat interval, float initialValue) { value = initialValue; this.interval = interval; }