mathio/period.rs
1/// # Periodical
2/// Returns value that is normalized into a given period.
3/// Allows you to easily clamp values with overflow.
4///
5/// The most common example would be normalizing degrees between 0 and 360.
6///
7/// # Examples
8///
9/// ```
10/// let period = 360.0;
11/// assert_eq!(315.0, periodical(period, -45.0));
12/// assert_eq!(45.0, periodical(period, 45.0));
13/// assert_eq!(0.0, periodical(period, 360.0));
14/// assert_eq!(90.0, periodical(period, 450.0));
15/// ```
16pub fn periodical(period: f32, x: f32) -> f32 {
17 let value = x % period;
18 if value < 0.0 {
19 value + period
20 } else {
21 value
22 }
23}
24
25/// # Periodical Difference Short
26/// Returns a difference between 2 periodical values.
27/// Uses the shortest path.
28///
29/// The most common example would be getting a difference between 2 angles in degrees.
30/// Because of the nature of trigonometry, you can sometimes get inner or outer angle depending on use case.
31/// This function will always return the INNER angle.
32///
33/// # Examples
34///
35/// ```
36/// let period = 360.0;
37/// assert_eq!(120.0, periodical_difference_short(period, 0.0, 120.0));
38/// assert_eq!(-90.0, periodical_difference_short(period, 0.0, 270.0)); //Always returns the inner angle
39/// assert_eq!(45.0, periodical_difference_short(period, 45.0, 90.0));
40/// assert_eq!(-45.0, periodical_difference_short(period, 90.0, 45.0));
41/// ```
42pub fn periodical_difference_short(period: f32, x1: f32, x2: f32) -> f32 {
43 let difference = (periodical(period, x2) - periodical(period, x1)) % period;
44 if difference > period / 2.0 {
45 difference - period
46 } else if difference < -period / 2.0 {
47 difference + period
48 } else {
49 difference
50 }
51}
52
53/// # Periodical Difference Long
54/// Returns a difference between 2 periodical values.
55/// Uses the longest path.
56///
57/// The most common example would be getting a difference between 2 angles in degrees.
58/// Because of the nature of trigonometry, you can sometimes get inner or outer angle depending on use case. This function will always return the OUTER angle.
59///
60/// # Examples
61///
62/// ```
63/// let period = 360.0;
64/// assert_eq!(-240.0, periodical_difference_long(period, 0.0, 120.0)); //Always returns the outer angle
65/// assert_eq!(270.0, periodical_difference_long(period, 0.0, 270.0));
66/// assert_eq!(-315.0, periodical_difference_long(period, 45.0, 90.0));
67/// assert_eq!(315.0, periodical_difference_long(period, 90.0, 45.0));
68/// ```
69pub fn periodical_difference_long(period: f32, x1: f32, x2: f32) -> f32 {
70 let difference = (periodical(period, x2) - periodical(period, x1)) % period;
71 if difference < 0.0 {
72 difference + period
73 } else if difference <= period / 2.0 {
74 difference - period
75 } else {
76 difference
77 }
78}
79
80/// # Periodical Tween Short
81/// A function to tween between two periodical values
82/// Uses the shortest path.
83///
84/// The most common example would be tweening between 2 angles in degrees.
85pub fn periodical_tween_short(period: f32, x1: f32, x2: f32, slider: f32) -> f32 {
86 let start = periodical(period, x1);
87 periodical(
88 period,
89 start + periodical_difference_short(period, x1, x2) * slider,
90 )
91}
92
93/// # Periodical Tween Long
94/// A function to tween between two periodical values
95/// Uses the longest path.
96///
97/// The most common example would be tweening between 2 angles in degrees.
98pub fn periodical_tween_long(period: f32, x1: f32, x2: f32, slider: f32) -> f32 {
99 let start = periodical(period, x1);
100 let difference = periodical_difference_long(period, x1, x2);
101 periodical(period, start + difference * slider)
102}