Skip to main content

blockworx_geom/
vec2.rs

1use std::fmt;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4use crate::Pos2;
5
6/// A direction-and-length, and the type a size is spelled in.
7#[derive(Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize)]
8pub struct Vec2 {
9    /// Rightwards. Width.
10    pub x: f32,
11
12    /// Downwards. Height.
13    pub y: f32,
14}
15
16/// `vec2(x, y) == Vec2::new(x, y)`
17#[inline]
18pub const fn vec2(x: f32, y: f32) -> Vec2 {
19    Vec2 { x, y }
20}
21
22impl Vec2 {
23    pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
24    pub const ONE: Self = Self { x: 1.0, y: 1.0 };
25    pub const INFINITY: Self = Self::splat(f32::INFINITY);
26
27    #[inline]
28    pub const fn new(x: f32, y: f32) -> Self {
29        Self { x, y }
30    }
31
32    /// Both axes set to the same value.
33    #[inline]
34    pub const fn splat(v: f32) -> Self {
35        Self { x: v, y: v }
36    }
37
38    /// The position this vector reaches from the origin.
39    #[inline]
40    pub const fn to_pos2(self) -> Pos2 {
41        Pos2 {
42            x: self.x,
43            y: self.y,
44        }
45    }
46
47    /// Unit vector in the same direction; the zero vector normalizes to itself.
48    #[must_use]
49    #[inline]
50    pub fn normalized(self) -> Self {
51        let len = self.length();
52        if len <= 0.0 { self } else { self / len }
53    }
54
55    #[inline]
56    pub fn length(self) -> f32 {
57        self.x.hypot(self.y)
58    }
59
60    #[inline]
61    pub fn length_sq(self) -> f32 {
62        self.x * self.x + self.y * self.y
63    }
64
65    #[must_use]
66    #[inline]
67    pub fn floor(self) -> Self {
68        vec2(self.x.floor(), self.y.floor())
69    }
70
71    #[must_use]
72    #[inline]
73    pub fn round(self) -> Self {
74        vec2(self.x.round(), self.y.round())
75    }
76
77    #[must_use]
78    #[inline]
79    pub fn ceil(self) -> Self {
80        vec2(self.x.ceil(), self.y.ceil())
81    }
82
83    #[must_use]
84    #[inline]
85    pub fn abs(self) -> Self {
86        vec2(self.x.abs(), self.y.abs())
87    }
88
89    #[inline]
90    pub fn is_finite(self) -> bool {
91        self.x.is_finite() && self.y.is_finite()
92    }
93
94    /// Per-axis minimum.
95    #[must_use]
96    #[inline]
97    pub fn min(self, other: Self) -> Self {
98        vec2(self.x.min(other.x), self.y.min(other.y))
99    }
100
101    /// Per-axis maximum.
102    #[must_use]
103    #[inline]
104    pub fn max(self, other: Self) -> Self {
105        vec2(self.x.max(other.x), self.y.max(other.y))
106    }
107
108    #[inline]
109    pub fn dot(self, other: Self) -> f32 {
110        self.x * other.x + self.y * other.y
111    }
112
113    #[must_use]
114    #[inline]
115    pub fn min_elem(self) -> f32 {
116        self.x.min(self.y)
117    }
118
119    #[must_use]
120    #[inline]
121    pub fn max_elem(self) -> f32 {
122        self.x.max(self.y)
123    }
124
125    #[must_use]
126    #[inline]
127    pub fn clamp(self, min: Self, max: Self) -> Self {
128        Self {
129            x: self.x.clamp(min.x, max.x),
130            y: self.y.clamp(min.y, max.y),
131        }
132    }
133}
134
135// Sound in the same sense emath's is: nothing constructs a NaN component
136// deliberately, and `==` on grid-derived coordinates is an exact test.
137impl Eq for Vec2 {}
138
139impl From<[f32; 2]> for Vec2 {
140    #[inline]
141    fn from([x, y]: [f32; 2]) -> Self {
142        Self { x, y }
143    }
144}
145
146impl From<Vec2> for [f32; 2] {
147    #[inline]
148    fn from(v: Vec2) -> Self {
149        [v.x, v.y]
150    }
151}
152
153impl From<(f32, f32)> for Vec2 {
154    #[inline]
155    fn from((x, y): (f32, f32)) -> Self {
156        Self { x, y }
157    }
158}
159
160impl From<Vec2> for (f32, f32) {
161    #[inline]
162    fn from(v: Vec2) -> Self {
163        (v.x, v.y)
164    }
165}
166
167impl Neg for Vec2 {
168    type Output = Self;
169
170    #[inline]
171    fn neg(self) -> Self {
172        vec2(-self.x, -self.y)
173    }
174}
175
176impl Add for Vec2 {
177    type Output = Self;
178
179    #[inline]
180    fn add(self, rhs: Self) -> Self {
181        vec2(self.x + rhs.x, self.y + rhs.y)
182    }
183}
184
185impl AddAssign for Vec2 {
186    #[inline]
187    fn add_assign(&mut self, rhs: Self) {
188        *self = *self + rhs;
189    }
190}
191
192impl Sub for Vec2 {
193    type Output = Self;
194
195    #[inline]
196    fn sub(self, rhs: Self) -> Self {
197        vec2(self.x - rhs.x, self.y - rhs.y)
198    }
199}
200
201impl SubAssign for Vec2 {
202    #[inline]
203    fn sub_assign(&mut self, rhs: Self) {
204        *self = *self - rhs;
205    }
206}
207
208/// Element-wise multiplication.
209impl Mul<Self> for Vec2 {
210    type Output = Self;
211
212    #[inline]
213    fn mul(self, rhs: Self) -> Self {
214        vec2(self.x * rhs.x, self.y * rhs.y)
215    }
216}
217
218/// Element-wise division.
219impl Div<Self> for Vec2 {
220    type Output = Self;
221
222    #[inline]
223    fn div(self, rhs: Self) -> Self {
224        vec2(self.x / rhs.x, self.y / rhs.y)
225    }
226}
227
228impl Mul<f32> for Vec2 {
229    type Output = Self;
230
231    #[inline]
232    fn mul(self, factor: f32) -> Self {
233        vec2(self.x * factor, self.y * factor)
234    }
235}
236
237impl Mul<Vec2> for f32 {
238    type Output = Vec2;
239
240    #[inline]
241    fn mul(self, v: Vec2) -> Vec2 {
242        vec2(self * v.x, self * v.y)
243    }
244}
245
246impl MulAssign<f32> for Vec2 {
247    #[inline]
248    fn mul_assign(&mut self, rhs: f32) {
249        *self = *self * rhs;
250    }
251}
252
253impl Div<f32> for Vec2 {
254    type Output = Self;
255
256    #[inline]
257    fn div(self, factor: f32) -> Self {
258        vec2(self.x / factor, self.y / factor)
259    }
260}
261
262impl DivAssign<f32> for Vec2 {
263    #[inline]
264    fn div_assign(&mut self, rhs: f32) {
265        *self = *self / rhs;
266    }
267}
268
269impl fmt::Debug for Vec2 {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        if let Some(precision) = f.precision() {
272            write!(f, "[{1:.0$} {2:.0$}]", precision, self.x, self.y)
273        } else {
274            write!(f, "[{:.1} {:.1}]", self.x, self.y)
275        }
276    }
277}
278
279impl fmt::Display for Vec2 {
280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281        write!(f, "[{} {}]", self.x, self.y)
282    }
283}