axgeom/
vec2.rs

1use crate::Axis;
2use core::convert::TryInto;
3use core::ops::*;
4use num_traits::float::FloatCore;
5use num_traits::Zero;
6#[cfg(feature="serde")]
7use serde::{Deserialize, Serialize};
8
9///Convenience function to create a vector.
10#[inline(always)]
11pub const fn vec2<N>(x: N, y: N) -> Vec2<N> {
12    Vec2 { x, y }
13}
14
15///Convenience function to create a vector where both component are the same.
16#[inline(always)]
17pub fn vec2same<N: Copy>(a: N) -> Vec2<N> {
18    Vec2 { x: a, y: a }
19}
20
21///A 2D vector.
22#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24#[must_use]
25pub struct Vec2<N> {
26    pub x: N,
27    pub y: N,
28}
29
30impl<N> AsRef<[N; 2]> for Vec2<N> {
31    #[inline(always)]
32    fn as_ref(&self) -> &[N; 2] {
33        unsafe { &*(self as *const _ as *const _) }
34    }
35}
36
37impl<N> AsMut<[N; 2]> for Vec2<N> {
38    #[inline(always)]
39    fn as_mut(&mut self) -> &mut [N; 2] {
40        unsafe { &mut *(self as *mut _ as *mut _) }
41    }
42}
43
44#[inline(always)]
45pub fn absdiff<T>(x: T, y: T) -> T
46where
47    T: Sub<Output = T> + PartialOrd,
48{
49    if x < y {
50        y - x
51    } else {
52        x - y
53    }
54}
55
56fn gen_abs<S: Neg<Output = S> + PartialOrd + Zero>(num: S) -> S {
57    if num < S::zero() {
58        -num
59    } else {
60        num
61    }
62}
63impl<S: Copy + Neg<Output = S> + PartialOrd + Zero> Vec2<S> {
64    #[inline(always)]
65    pub fn abs(&self) -> Vec2<S> {
66        vec2(gen_abs(self.x), gen_abs(self.y))
67    }
68    #[inline(always)]
69    pub fn rotate_90deg_right(&self) -> Vec2<S> {
70        vec2(-self.y, self.x)
71    }
72    #[inline(always)]
73    pub fn rotate_90deg_left(&self) -> Vec2<S> {
74        vec2(self.y, self.x)
75    }
76
77    #[inline(always)]
78    pub fn split_into_components(&self) -> [Vec2<S>; 2] {
79        [vec2(self.x, S::zero()), vec2(S::zero(), self.y)]
80    }
81}
82
83impl<S: Add<Output = S> + Sub<Output = S> + PartialOrd + Copy> Vec2<S> {
84    #[inline(always)]
85    pub fn manhattan_dis(&self, other: Vec2<S>) -> S {
86        absdiff(self.x, other.x) + absdiff(self.y, other.y)
87    }
88}
89
90impl<
91        T: Copy
92            + PartialOrd
93            + core::ops::Sub<Output = T>
94            + core::ops::Mul<Output = T>
95            + core::ops::Add<Output = T>,
96    > Vec2<T>
97{
98    ///If the point is outside the rectangle, returns the squared distance from a point to a rectangle.
99    ///If the point is inside the rectangle, it will return None.
100    #[inline(always)]
101    #[must_use]
102    pub fn distance_squared_to_point(&self, point: Vec2<T>) -> T {
103        (point.x - self.x) * (point.x - self.x) + (point.y - self.y) * (point.y - self.y)
104    }
105}
106
107#[test]
108fn test_rotate() {
109    let b = vec2(1, 1).rotate_90deg_right();
110    assert_eq!(b, vec2(-1, 1));
111
112    let b = vec2(1, 0).rotate_90deg_right();
113    assert_eq!(b, vec2(0, 1));
114}
115
116impl<S: Mul<Output = S> + Div<Output = S> + Add<Output = S> + Copy> Vec2<S> {
117    #[inline(always)]
118    pub fn scale(&self, other: Vec2<S>) -> Vec2<S> {
119        vec2(self.x * other.x, self.y * other.y)
120    }
121
122    #[inline(always)]
123    pub fn inv_scale(&self, other: Vec2<S>) -> Vec2<S> {
124        vec2(self.x / other.x, self.y / other.y)
125    }
126
127    #[inline(always)]
128    #[must_use]
129    pub fn magnitude2(&self) -> S {
130        self.x * self.x + self.y * self.y
131    }
132    #[inline(always)]
133    #[must_use]
134    pub fn dot(&self, other: Vec2<S>) -> S {
135        self.x * other.x + self.y * other.y
136    }
137}
138impl<S: FloatCore> Vec2<S> {
139    #[inline(always)]
140    pub fn is_nan(&self) -> bool {
141        self.x.is_nan() || self.y.is_nan()
142    }
143}
144
145#[cfg(feature = "std")]
146impl<S: num_traits::Float> Vec2<S> {
147    #[inline(always)]
148    pub fn truncate_at(&self, mag: S) -> Vec2<S> {
149        if self.magnitude() > mag {
150            self.normalize_to(mag)
151        } else {
152            *self
153        }
154    }
155
156    #[inline(always)]
157    pub fn normalize_to(&self, mag: S) -> Vec2<S> {
158        let l = self.magnitude2().sqrt();
159        (*self) * (mag / l)
160    }
161
162    #[inline(always)]
163    pub fn magnitude(&self) -> S {
164        self.magnitude2().sqrt()
165    }
166}
167
168///Cast an array of 2 elements of primitive type to another primitive type using "as" on each element.
169#[must_use]
170pub fn arr2_as<B: 'static + Copy, A: num_traits::AsPrimitive<B>>(a: [A; 2]) -> [B; 2] {
171    let [a, b] = a;
172    [a.as_(), b.as_()]
173}
174
175impl<T> Vec2<T> {
176    #[inline(always)]
177    pub fn inner_as<B: 'static + Copy>(self) -> Vec2<B>
178    where
179        T: num_traits::AsPrimitive<B>,
180    {
181        vec2(self.x.as_(), self.y.as_())
182    }
183}
184
185impl<'a, B: Copy> From<&'a [B; 2]> for Vec2<B> {
186    fn from(a: &'a [B; 2]) -> Self {
187        let [a, b] = *a;
188        vec2(a, b)
189    }
190}
191
192impl<B> From<[B; 2]> for Vec2<B> {
193    fn from(a: [B; 2]) -> Self {
194        let [a, b] = a;
195        vec2(a, b)
196    }
197}
198
199impl<B> From<Vec2<B>> for [B; 2] {
200    fn from(a: Vec2<B>) -> Self {
201        [a.x, a.y]
202    }
203}
204
205impl<'a, B> From<&'a Vec2<B>> for &'a [B; 2] {
206    fn from(a: &'a Vec2<B>) -> Self {
207        a.as_ref()
208    }
209}
210
211impl<B> Vec2<B> {
212    ///Get the range of one axis.
213    #[inline(always)]
214    #[must_use]
215    pub fn get_axis(&self, axis: impl Axis) -> &B {
216        if axis.is_xaxis() {
217            &self.x
218        } else {
219            &self.y
220        }
221    }
222
223    ///Get the mutable range of one axis.
224    #[inline(always)]
225    #[must_use]
226    pub fn get_axis_mut(&mut self, axis: impl Axis) -> &mut B {
227        if axis.is_xaxis() {
228            &mut self.x
229        } else {
230            &mut self.y
231        }
232    }
233
234    #[inline(always)]
235    pub fn inner_into<A>(self) -> Vec2<A>
236    where
237        B: Into<A>,
238    {
239        let x = self.x.into();
240        let y = self.y.into();
241        vec2(x, y)
242    }
243
244    #[inline(always)]
245    pub fn inner_try_into<A>(self) -> Result<Vec2<A>, B::Error>
246    where
247        B: TryInto<A>,
248    {
249        let x = self.x.try_into();
250        let y = self.y.try_into();
251        match (x, y) {
252            (Ok(x), Ok(y)) => Ok(vec2(x, y)),
253            (Ok(_), Err(e)) => Err(e),
254            (Err(e), Ok(_)) => Err(e),
255            (Err(e), Err(_)) => Err(e),
256        }
257    }
258}
259
260impl<S: Add<Output = S> + Copy> Add<Self> for Vec2<S> {
261    type Output = Self;
262    #[inline(always)]
263    fn add(self, rhs: Self) -> Self {
264        vec2(self.x + rhs.x, self.y + rhs.y)
265    }
266}
267
268impl<S: Sub<Output = S> + Copy> Sub<Self> for Vec2<S> {
269    type Output = Self;
270    #[inline(always)]
271    fn sub(self, rhs: Self) -> Self {
272        vec2(self.x - rhs.x, self.y - rhs.y)
273    }
274}
275
276impl<S: Mul<Output = S> + Copy> Mul<S> for Vec2<S> {
277    type Output = Self;
278    #[inline(always)]
279    fn mul(self, rhs: S) -> Self {
280        vec2(self.x * rhs, self.y * rhs)
281    }
282}
283
284impl<S: Div<Output = S> + Copy> Div<S> for Vec2<S> {
285    type Output = Self;
286    #[inline(always)]
287    fn div(self, rhs: S) -> Self {
288        vec2(self.x / rhs, self.y / rhs)
289    }
290}
291
292impl<S: DivAssign<S> + Copy> DivAssign<S> for Vec2<S> {
293    #[inline(always)]
294    fn div_assign(&mut self, scalar: S) {
295        self.x /= scalar;
296        self.y /= scalar;
297    }
298}
299impl<S: MulAssign<S> + Copy> MulAssign<S> for Vec2<S> {
300    #[inline(always)]
301    fn mul_assign(&mut self, scalar: S) {
302        self.x *= scalar;
303        self.y *= scalar;
304    }
305}
306
307impl<S: AddAssign<S> + Copy> AddAssign<Self> for Vec2<S> {
308    #[inline(always)]
309    fn add_assign(&mut self, rhs: Self) {
310        self.x += rhs.x;
311        self.y += rhs.y;
312    }
313}
314impl<S: SubAssign<S> + Copy> SubAssign<Self> for Vec2<S> {
315    #[inline(always)]
316    fn sub_assign(&mut self, rhs: Self) {
317        self.x -= rhs.x;
318        self.y -= rhs.y;
319    }
320}
321
322impl<S: Neg<Output = S>> Neg for Vec2<S> {
323    type Output = Vec2<S>;
324
325    #[inline]
326    fn neg(self) -> Vec2<S> {
327        vec2(-self.x, -self.y)
328    }
329}
330
331impl<S: Zero + Eq + Copy> Zero for Vec2<S> {
332    #[inline(always)]
333    fn zero() -> Vec2<S> {
334        vec2(S::zero(), S::zero())
335    }
336
337    #[inline(always)]
338    #[must_use]
339    fn is_zero(&self) -> bool {
340        *self == Vec2::zero()
341    }
342}