emath/
vec2.rs

1use std::fmt;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4use crate::Vec2b;
5
6/// A vector has a direction and length.
7/// A [`Vec2`] is often used to represent a size.
8///
9/// emath represents positions using [`crate::Pos2`].
10///
11/// Normally the units are points (logical pixels).
12#[repr(C)]
13#[derive(Clone, Copy, Default, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
15#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
16pub struct Vec2 {
17    /// Rightwards. Width.
18    pub x: f32,
19
20    /// Downwards. Height.
21    pub y: f32,
22}
23
24/// `vec2(x, y) == Vec2::new(x, y)`
25#[inline(always)]
26pub const fn vec2(x: f32, y: f32) -> Vec2 {
27    Vec2 { x, y }
28}
29
30// ----------------------------------------------------------------------------
31// Compatibility and convenience conversions to and from [f32; 2]:
32
33impl From<[f32; 2]> for Vec2 {
34    #[inline(always)]
35    fn from(v: [f32; 2]) -> Self {
36        Self { x: v[0], y: v[1] }
37    }
38}
39
40impl From<&[f32; 2]> for Vec2 {
41    #[inline(always)]
42    fn from(v: &[f32; 2]) -> Self {
43        Self { x: v[0], y: v[1] }
44    }
45}
46
47impl From<Vec2> for [f32; 2] {
48    #[inline(always)]
49    fn from(v: Vec2) -> Self {
50        [v.x, v.y]
51    }
52}
53
54impl From<&Vec2> for [f32; 2] {
55    #[inline(always)]
56    fn from(v: &Vec2) -> Self {
57        [v.x, v.y]
58    }
59}
60
61// ----------------------------------------------------------------------------
62// Compatibility and convenience conversions to and from (f32, f32):
63
64impl From<(f32, f32)> for Vec2 {
65    #[inline(always)]
66    fn from(v: (f32, f32)) -> Self {
67        Self { x: v.0, y: v.1 }
68    }
69}
70
71impl From<&(f32, f32)> for Vec2 {
72    #[inline(always)]
73    fn from(v: &(f32, f32)) -> Self {
74        Self { x: v.0, y: v.1 }
75    }
76}
77
78impl From<Vec2> for (f32, f32) {
79    #[inline(always)]
80    fn from(v: Vec2) -> Self {
81        (v.x, v.y)
82    }
83}
84
85impl From<&Vec2> for (f32, f32) {
86    #[inline(always)]
87    fn from(v: &Vec2) -> Self {
88        (v.x, v.y)
89    }
90}
91
92impl From<Vec2b> for Vec2 {
93    #[inline(always)]
94    fn from(v: Vec2b) -> Self {
95        Self {
96            x: v.x as i32 as f32,
97            y: v.y as i32 as f32,
98        }
99    }
100}
101
102// ----------------------------------------------------------------------------
103// Mint compatibility and convenience conversions
104
105#[cfg(feature = "mint")]
106impl From<mint::Vector2<f32>> for Vec2 {
107    #[inline]
108    fn from(v: mint::Vector2<f32>) -> Self {
109        Self::new(v.x, v.y)
110    }
111}
112
113#[cfg(feature = "mint")]
114impl From<Vec2> for mint::Vector2<f32> {
115    #[inline]
116    fn from(v: Vec2) -> Self {
117        Self { x: v.x, y: v.y }
118    }
119}
120
121// ----------------------------------------------------------------------------
122
123impl Vec2 {
124    /// Right
125    pub const X: Self = Self { x: 1.0, y: 0.0 };
126
127    /// Down
128    pub const Y: Self = Self { x: 0.0, y: 1.0 };
129
130    /// +X
131    pub const RIGHT: Self = Self { x: 1.0, y: 0.0 };
132
133    /// -X
134    pub const LEFT: Self = Self { x: -1.0, y: 0.0 };
135
136    /// -Y
137    pub const UP: Self = Self { x: 0.0, y: -1.0 };
138
139    /// +Y
140    pub const DOWN: Self = Self { x: 0.0, y: 1.0 };
141
142    pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
143    pub const INFINITY: Self = Self::splat(f32::INFINITY);
144    pub const NAN: Self = Self::splat(f32::NAN);
145
146    #[inline(always)]
147    pub const fn new(x: f32, y: f32) -> Self {
148        Self { x, y }
149    }
150
151    /// Set both `x` and `y` to the same value.
152    #[inline(always)]
153    pub const fn splat(v: f32) -> Self {
154        Self { x: v, y: v }
155    }
156
157    /// Treat this vector as a position.
158    /// `v.to_pos2()` is equivalent to `Pos2::default() + v`.
159    #[inline(always)]
160    pub fn to_pos2(self) -> crate::Pos2 {
161        crate::Pos2 {
162            x: self.x,
163            y: self.y,
164        }
165    }
166
167    /// Safe normalize: returns zero if input is zero.
168    #[must_use]
169    #[inline(always)]
170    pub fn normalized(self) -> Self {
171        let len = self.length();
172        if len <= 0.0 {
173            self
174        } else {
175            self / len
176        }
177    }
178
179    /// Rotates the vector by 90°, i.e positive X to positive Y
180    /// (clockwise in egui coordinates).
181    #[inline(always)]
182    pub fn rot90(self) -> Self {
183        vec2(self.y, -self.x)
184    }
185
186    #[inline(always)]
187    pub fn length(self) -> f32 {
188        self.x.hypot(self.y)
189    }
190
191    #[inline(always)]
192    pub fn length_sq(self) -> f32 {
193        self.x * self.x + self.y * self.y
194    }
195
196    /// Measures the angle of the vector.
197    ///
198    /// ```
199    /// # use emath::Vec2;
200    /// use std::f32::consts::TAU;
201    ///
202    /// assert_eq!(Vec2::ZERO.angle(), 0.0);
203    /// assert_eq!(Vec2::angled(0.0).angle(), 0.0);
204    /// assert_eq!(Vec2::angled(1.0).angle(), 1.0);
205    /// assert_eq!(Vec2::X.angle(), 0.0);
206    /// assert_eq!(Vec2::Y.angle(), 0.25 * TAU);
207    ///
208    /// assert_eq!(Vec2::RIGHT.angle(), 0.0);
209    /// assert_eq!(Vec2::DOWN.angle(), 0.25 * TAU);
210    /// assert_eq!(Vec2::UP.angle(), -0.25 * TAU);
211    /// ```
212    #[inline(always)]
213    pub fn angle(self) -> f32 {
214        self.y.atan2(self.x)
215    }
216
217    /// Create a unit vector with the given CW angle (in radians).
218    /// * An angle of zero gives the unit X axis.
219    /// * An angle of 𝞃/4 = 90° gives the unit Y axis.
220    ///
221    /// ```
222    /// # use emath::Vec2;
223    /// use std::f32::consts::TAU;
224    ///
225    /// assert_eq!(Vec2::angled(0.0), Vec2::X);
226    /// assert!((Vec2::angled(0.25 * TAU) - Vec2::Y).length() < 1e-5);
227    /// ```
228    #[inline(always)]
229    pub fn angled(angle: f32) -> Self {
230        let (sin, cos) = angle.sin_cos();
231        vec2(cos, sin)
232    }
233
234    #[must_use]
235    #[inline(always)]
236    pub fn floor(self) -> Self {
237        vec2(self.x.floor(), self.y.floor())
238    }
239
240    #[must_use]
241    #[inline(always)]
242    pub fn round(self) -> Self {
243        vec2(self.x.round(), self.y.round())
244    }
245
246    #[must_use]
247    #[inline(always)]
248    pub fn ceil(self) -> Self {
249        vec2(self.x.ceil(), self.y.ceil())
250    }
251
252    #[must_use]
253    #[inline]
254    pub fn abs(self) -> Self {
255        vec2(self.x.abs(), self.y.abs())
256    }
257
258    /// True if all members are also finite.
259    #[inline(always)]
260    pub fn is_finite(self) -> bool {
261        self.x.is_finite() && self.y.is_finite()
262    }
263
264    /// True if any member is NaN.
265    #[inline(always)]
266    pub fn any_nan(self) -> bool {
267        self.x.is_nan() || self.y.is_nan()
268    }
269
270    #[must_use]
271    #[inline]
272    pub fn min(self, other: Self) -> Self {
273        vec2(self.x.min(other.x), self.y.min(other.y))
274    }
275
276    #[must_use]
277    #[inline]
278    pub fn max(self, other: Self) -> Self {
279        vec2(self.x.max(other.x), self.y.max(other.y))
280    }
281
282    /// The dot-product of two vectors.
283    #[inline]
284    pub fn dot(self, other: Self) -> f32 {
285        self.x * other.x + self.y * other.y
286    }
287
288    /// Returns the minimum of `self.x` and `self.y`.
289    #[must_use]
290    #[inline(always)]
291    pub fn min_elem(self) -> f32 {
292        self.x.min(self.y)
293    }
294
295    /// Returns the maximum of `self.x` and `self.y`.
296    #[inline(always)]
297    #[must_use]
298    pub fn max_elem(self) -> f32 {
299        self.x.max(self.y)
300    }
301
302    /// Swizzle the axes.
303    #[inline]
304    #[must_use]
305    pub fn yx(self) -> Self {
306        Self {
307            x: self.y,
308            y: self.x,
309        }
310    }
311
312    #[must_use]
313    #[inline]
314    pub fn clamp(self, min: Self, max: Self) -> Self {
315        Self {
316            x: self.x.clamp(min.x, max.x),
317            y: self.y.clamp(min.y, max.y),
318        }
319    }
320}
321
322impl std::ops::Index<usize> for Vec2 {
323    type Output = f32;
324
325    #[inline(always)]
326    fn index(&self, index: usize) -> &f32 {
327        match index {
328            0 => &self.x,
329            1 => &self.y,
330            _ => panic!("Vec2 index out of bounds: {index}"),
331        }
332    }
333}
334
335impl std::ops::IndexMut<usize> for Vec2 {
336    #[inline(always)]
337    fn index_mut(&mut self, index: usize) -> &mut f32 {
338        match index {
339            0 => &mut self.x,
340            1 => &mut self.y,
341            _ => panic!("Vec2 index out of bounds: {index}"),
342        }
343    }
344}
345
346impl Eq for Vec2 {}
347
348impl Neg for Vec2 {
349    type Output = Self;
350
351    #[inline(always)]
352    fn neg(self) -> Self {
353        vec2(-self.x, -self.y)
354    }
355}
356
357impl AddAssign for Vec2 {
358    #[inline(always)]
359    fn add_assign(&mut self, rhs: Self) {
360        *self = Self {
361            x: self.x + rhs.x,
362            y: self.y + rhs.y,
363        };
364    }
365}
366
367impl SubAssign for Vec2 {
368    #[inline(always)]
369    fn sub_assign(&mut self, rhs: Self) {
370        *self = Self {
371            x: self.x - rhs.x,
372            y: self.y - rhs.y,
373        };
374    }
375}
376
377impl Add for Vec2 {
378    type Output = Self;
379
380    #[inline(always)]
381    fn add(self, rhs: Self) -> Self {
382        Self {
383            x: self.x + rhs.x,
384            y: self.y + rhs.y,
385        }
386    }
387}
388
389impl Sub for Vec2 {
390    type Output = Self;
391
392    #[inline(always)]
393    fn sub(self, rhs: Self) -> Self {
394        Self {
395            x: self.x - rhs.x,
396            y: self.y - rhs.y,
397        }
398    }
399}
400
401/// Element-wise multiplication
402impl Mul<Self> for Vec2 {
403    type Output = Self;
404
405    #[inline(always)]
406    fn mul(self, vec: Self) -> Self {
407        Self {
408            x: self.x * vec.x,
409            y: self.y * vec.y,
410        }
411    }
412}
413
414/// Element-wise division
415impl Div<Self> for Vec2 {
416    type Output = Self;
417
418    #[inline(always)]
419    fn div(self, rhs: Self) -> Self {
420        Self {
421            x: self.x / rhs.x,
422            y: self.y / rhs.y,
423        }
424    }
425}
426
427impl MulAssign<f32> for Vec2 {
428    #[inline(always)]
429    fn mul_assign(&mut self, rhs: f32) {
430        self.x *= rhs;
431        self.y *= rhs;
432    }
433}
434
435impl DivAssign<f32> for Vec2 {
436    #[inline(always)]
437    fn div_assign(&mut self, rhs: f32) {
438        self.x /= rhs;
439        self.y /= rhs;
440    }
441}
442
443impl Mul<f32> for Vec2 {
444    type Output = Self;
445
446    #[inline(always)]
447    fn mul(self, factor: f32) -> Self {
448        Self {
449            x: self.x * factor,
450            y: self.y * factor,
451        }
452    }
453}
454
455impl Mul<Vec2> for f32 {
456    type Output = Vec2;
457
458    #[inline(always)]
459    fn mul(self, vec: Vec2) -> Vec2 {
460        Vec2 {
461            x: self * vec.x,
462            y: self * vec.y,
463        }
464    }
465}
466
467impl Div<f32> for Vec2 {
468    type Output = Self;
469
470    #[inline(always)]
471    fn div(self, factor: f32) -> Self {
472        Self {
473            x: self.x / factor,
474            y: self.y / factor,
475        }
476    }
477}
478
479impl fmt::Debug for Vec2 {
480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481        if let Some(precision) = f.precision() {
482            write!(f, "[{1:.0$} {2:.0$}]", precision, self.x, self.y)
483        } else {
484            write!(f, "[{:.1} {:.1}]", self.x, self.y)
485        }
486    }
487}
488
489impl fmt::Display for Vec2 {
490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491        f.write_str("[")?;
492        self.x.fmt(f)?;
493        f.write_str(" ")?;
494        self.y.fmt(f)?;
495        f.write_str("]")?;
496        Ok(())
497    }
498}
499
500#[test]
501fn test_vec2() {
502    macro_rules! almost_eq {
503        ($left: expr, $right: expr) => {
504            let left = $left;
505            let right = $right;
506            assert!((left - right).abs() < 1e-6, "{} != {}", left, right);
507        };
508    }
509    use std::f32::consts::TAU;
510
511    assert_eq!(Vec2::ZERO.angle(), 0.0);
512    assert_eq!(Vec2::angled(0.0).angle(), 0.0);
513    assert_eq!(Vec2::angled(1.0).angle(), 1.0);
514    assert_eq!(Vec2::X.angle(), 0.0);
515    assert_eq!(Vec2::Y.angle(), 0.25 * TAU);
516
517    assert_eq!(Vec2::RIGHT.angle(), 0.0);
518    assert_eq!(Vec2::DOWN.angle(), 0.25 * TAU);
519    almost_eq!(Vec2::LEFT.angle(), 0.50 * TAU);
520    assert_eq!(Vec2::UP.angle(), -0.25 * TAU);
521
522    let mut assignment = vec2(1.0, 2.0);
523    assignment += vec2(3.0, 4.0);
524    assert_eq!(assignment, vec2(4.0, 6.0));
525
526    let mut assignment = vec2(4.0, 6.0);
527    assignment -= vec2(1.0, 2.0);
528    assert_eq!(assignment, vec2(3.0, 4.0));
529
530    let mut assignment = vec2(1.0, 2.0);
531    assignment *= 2.0;
532    assert_eq!(assignment, vec2(2.0, 4.0));
533
534    let mut assignment = vec2(2.0, 4.0);
535    assignment /= 2.0;
536    assert_eq!(assignment, vec2(1.0, 2.0));
537}