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}