macaw/
vec2_ext.rs

1use super::Vec2;
2use super::prelude::*;
3use super::vec2;
4
5#[cfg(target_arch = "spirv")]
6use num_traits::Float;
7
8/// Extensions to [`Vec2`]
9///
10/// Adds additional functionality to [`Vec2`] that [`glam`] doesn't have.
11pub trait Vec2Ext {
12    /// `x: cos(angle), y: sin(angle)` (in radians)
13    #[must_use]
14    fn from_angle(angle: f32) -> Self;
15
16    /// Angle of the vector: `y.atan2(x)`
17    #[must_use]
18    fn angle(&self) -> f32;
19
20    /// For element `i` of `self`, return `v[i].trunc()`
21    #[must_use]
22    fn trunc(self) -> Self;
23
24    /// For element `i` of the return value, returns 0.0 if `value[i] < self[i]` and 1.0 otherwise.
25    ///
26    /// Similar to glsl's step(edge, x), which translates into edge.step(x)
27    #[must_use]
28    fn step(self, value: Self) -> Self;
29
30    /// Selects between `true` and `false` based on the result of `value[i] < self[i]`
31    #[must_use]
32    fn step_select(self, value: Self, tru: Self, fals: Self) -> Self;
33
34    /// Return only the fractional parts of each component.
35    #[must_use]
36    fn fract(self) -> Self;
37
38    /// Clamp all components of `self` to the range `[0.0, 1.0]`
39    #[must_use]
40    fn saturate(self) -> Self;
41
42    /// Get the mean value of the two components
43    #[must_use]
44    fn mean(self) -> f32;
45
46    /// Returns true if both components of the vector is the same within an absolute difference of `max_abs_diff`
47    #[must_use]
48    fn has_equal_components(self, max_abs_diff: f32) -> bool;
49}
50
51impl Vec2Ext for Vec2 {
52    #[inline]
53    fn trunc(self) -> Self {
54        vec2(self.x.trunc(), self.y.trunc())
55    }
56
57    fn from_angle(angle: f32) -> Self {
58        Self::new(angle.cos(), angle.sin())
59    }
60
61    fn angle(&self) -> f32 {
62        self.y.atan2(self.x)
63    }
64
65    fn step(self, value: Self) -> Self {
66        vec2(self.x.step(value.x), self.y.step(value.y))
67    }
68
69    fn step_select(self, value: Self, less: Self, greater_or_equal: Self) -> Self {
70        vec2(
71            self.x.step_select(value.x, less.x, greater_or_equal.x),
72            self.y.step_select(value.y, less.y, greater_or_equal.y),
73        )
74    }
75
76    fn fract(self) -> Self {
77        vec2(self.x.fract(), self.y.fract())
78    }
79
80    fn saturate(self) -> Self {
81        vec2(self.x.saturate(), self.y.saturate())
82    }
83
84    fn mean(self) -> f32 {
85        (self.x + self.y) / 2.0
86    }
87
88    fn has_equal_components(self, max_abs_diff: f32) -> bool {
89        (self.x - self.y).abs() < max_abs_diff
90    }
91}
92
93#[cfg(test)]
94mod test {
95    use super::*;
96
97    #[test]
98    fn test_mean() {
99        assert!((Vec2::ONE.mean() - 1.0).abs() < 0.0001);
100    }
101
102    #[test]
103    fn test_mean_2() {
104        assert!((vec2(1.0, 3.0).mean() - 2.0).abs() < 0.0001);
105    }
106
107    #[test]
108    fn test_has_equal_components() {
109        assert!(Vec2::ONE.has_equal_components(0.001));
110    }
111
112    #[test]
113    fn test_has_equal_components_2() {
114        assert!(vec2(0.0, 0.00001).has_equal_components(0.001));
115    }
116
117    #[test]
118    fn test_has_equal_components_3() {
119        assert!(!vec2(1.0, 0.0).has_equal_components(0.0001));
120    }
121}