utils/
geometry.rs

1//! 2D & 3D vector implementations.
2
3use crate::number::{Integer, Number, Signed, UnsignedInteger};
4use std::fmt::Debug;
5use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
6
7macro_rules! vec_impl {
8    ($n:literal, $tuple:tt =>
9        $(#[$m:meta])* $v:vis struct $s:ident{$($i:tt => $f:ident),+}
10    ) => {
11        #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
12        $(#[$m])* $v struct $s<T: Number> {
13            $(pub $f: T,)+
14        }
15
16        impl<T: Number> $s<T> {
17            pub const ORIGIN: Self = Self{$($f: T::ZERO),+};
18
19            #[inline]
20            #[must_use]
21            pub const fn new($($f: T),+) -> Self {
22                Self{$($f),+}
23            }
24
25            /// Returns the manhattan distance from the origin.
26            #[inline]
27            #[must_use]
28            pub fn manhattan_distance(self) -> T::Unsigned
29            where
30                T: Integer
31            {
32                T::Unsigned::ZERO $(+ self.$f.unsigned_abs())+
33            }
34
35            /// Returns the manhattan distance from the specified point.
36            #[inline]
37            #[must_use]
38            pub fn manhattan_distance_from(self, rhs: Self) -> T::Unsigned
39            where
40                T: Integer
41            {
42                T::Unsigned::ZERO $(+ self.$f.abs_diff(rhs.$f))+
43            }
44
45            /// Add the provided signed vector, wrapping on overflow.
46            ///
47            /// Useful for adding a signed direction onto an unsigned position.
48            #[inline]
49            #[must_use]
50            pub fn wrapping_add_signed(self, rhs: $s<T::Signed>) -> Self
51            where
52                T: UnsignedInteger,
53            {
54                Self{
55                    $($f: self.$f.wrapping_add_signed(rhs.$f),)+
56                }
57            }
58        }
59
60        impl<T: Number> Add for $s<T> {
61            type Output = Self;
62
63            #[inline]
64            fn add(self, rhs: Self) -> Self {
65                Self{
66                    $($f: self.$f + rhs.$f,)+
67                }
68            }
69        }
70
71        impl<T: Number> AddAssign for $s<T> {
72            #[inline]
73            fn add_assign(&mut self, rhs: Self) {
74                $(self.$f += rhs.$f;)+
75            }
76        }
77
78        impl<T: Number> Mul<T> for $s<T> {
79            type Output = Self;
80
81            #[inline]
82            fn mul(self, rhs: T) -> Self {
83                Self{
84                    $($f: self.$f * rhs,)+
85                }
86            }
87        }
88
89        impl<T: Number> MulAssign<T> for $s<T> {
90            #[inline]
91            fn mul_assign(&mut self, rhs: T) {
92                $(self.$f *= rhs;)+
93            }
94        }
95
96        impl<T: Number> Sub for $s<T> {
97            type Output = Self;
98
99            #[inline]
100            fn sub(self, rhs: Self) -> Self {
101                Self{
102                    $($f: self.$f - rhs.$f,)+
103                }
104            }
105        }
106
107        impl<T: Number> SubAssign for $s<T> {
108            #[inline]
109            fn sub_assign(&mut self, rhs: Self) {
110                $(self.$f -= rhs.$f;)+
111            }
112        }
113
114        impl<T: Number> From<[T; $n]> for $s<T> {
115            #[inline]
116            fn from(arr: [T; $n]) -> Self {
117                Self{$(
118                    $f: arr[$i],
119                )+}
120            }
121        }
122
123        impl<T: Number> From<$tuple> for $s<T> {
124            #[inline]
125            fn from(arr: $tuple) -> Self {
126                Self{$(
127                    $f: arr.$i,
128                )+}
129            }
130        }
131
132        impl<T: Number> From<$s<T>> for [T; $n] {
133            #[inline]
134            fn from(value: $s<T>) -> Self {
135                [$(value.$f),+]
136            }
137        }
138
139        impl<T: Number> From<$s<T>> for $tuple {
140            #[inline]
141            fn from(value: $s<T>) -> Self {
142                ($(value.$f),+)
143            }
144        }
145    };
146}
147
148vec_impl! {2, (T, T) =>
149    /// Struct representing a 2D vector or point.
150    #[doc(alias("Vector", "Vector2", "Point", "Point2", "Point2D"))]
151    pub struct Vec2{0 => x, 1 => y}
152}
153
154impl<T: Signed> Vec2<T> {
155    pub const UP: Self = Self {
156        x: T::ZERO,
157        y: T::ONE,
158    };
159    pub const RIGHT: Self = Self {
160        x: T::ONE,
161        y: T::ZERO,
162    };
163    pub const DOWN: Self = Self {
164        x: T::ZERO,
165        y: T::MINUS_ONE,
166    };
167    pub const LEFT: Self = Self {
168        x: T::MINUS_ONE,
169        y: T::ZERO,
170    };
171
172    /// Rotate this vector 90 degrees clockwise.
173    #[inline]
174    #[must_use]
175    pub fn turn_right(self) -> Self {
176        Self {
177            x: self.y,
178            y: -self.x,
179        }
180    }
181
182    /// Rotate this vector 90 degrees counterclockwise.
183    #[inline]
184    #[must_use]
185    pub fn turn_left(self) -> Self {
186        Self {
187            x: -self.y,
188            y: self.x,
189        }
190    }
191}
192
193vec_impl! {3, (T, T, T) =>
194    /// Struct representing a 3D vector or point.
195    #[doc(alias("Vector3", "Point3", "Point3D"))]
196    pub struct Vec3{0 => x, 1 => y, 2 => z}
197}