rosu_map/util/
pos.rs

1use std::{
2    fmt::{Debug, Display, Formatter, Result as FmtResult},
3    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
4};
5
6/// Simple `(x, y)` coordinate / vector
7#[derive(Copy, Clone, Debug, Default, PartialEq)]
8pub struct Pos {
9    /// Position on the x-axis.
10    pub x: f32,
11    /// Position on the y-axis.
12    pub y: f32,
13}
14
15impl Pos {
16    /// Create a new position.
17    pub const fn new(x: f32, y: f32) -> Self {
18        Self { x, y }
19    }
20
21    /// Return the position's length squared.
22    pub fn length_squared(&self) -> f32 {
23        self.dot(*self)
24    }
25
26    /// Return the position's length.
27    pub fn length(&self) -> f32 {
28        f64::from(self.x * self.x + self.y * self.y).sqrt() as f32
29    }
30
31    /// Return the dot product.
32    pub fn dot(&self, other: Self) -> f32 {
33        (self.x * other.x) + (self.y * other.y)
34    }
35
36    /// Return the distance to another position.
37    pub fn distance(&self, other: Self) -> f32 {
38        (*self - other).length()
39    }
40
41    /// Normalize the coordinates with respect to the vector's length.
42    #[must_use]
43    pub fn normalize(mut self) -> Self {
44        let scale = self.length().recip();
45        self.x *= scale;
46        self.y *= scale;
47
48        self
49    }
50}
51
52impl Add for Pos {
53    type Output = Self;
54
55    fn add(self, rhs: Self) -> Self::Output {
56        Self::new(self.x + rhs.x, self.y + rhs.y)
57    }
58}
59
60impl AddAssign for Pos {
61    fn add_assign(&mut self, rhs: Self) {
62        self.x += rhs.x;
63        self.y += rhs.y;
64    }
65}
66
67impl Sub for Pos {
68    type Output = Self;
69
70    fn sub(self, rhs: Self) -> Self::Output {
71        Self::new(self.x - rhs.x, self.y - rhs.y)
72    }
73}
74
75impl SubAssign for Pos {
76    fn sub_assign(&mut self, rhs: Self) {
77        self.x -= rhs.x;
78        self.y -= rhs.y;
79    }
80}
81
82impl Mul<f32> for Pos {
83    type Output = Self;
84
85    fn mul(self, rhs: f32) -> Self::Output {
86        Self {
87            x: self.x * rhs,
88            y: self.y * rhs,
89        }
90    }
91}
92
93impl MulAssign<f32> for Pos {
94    fn mul_assign(&mut self, rhs: f32) {
95        self.x *= rhs;
96        self.y *= rhs;
97    }
98}
99
100impl Div<f32> for Pos {
101    type Output = Self;
102
103    fn div(self, rhs: f32) -> Self::Output {
104        Self {
105            x: self.x / rhs,
106            y: self.y / rhs,
107        }
108    }
109}
110
111impl DivAssign<f32> for Pos {
112    fn div_assign(&mut self, rhs: f32) {
113        self.x /= rhs;
114        self.y /= rhs;
115    }
116}
117
118impl Display for Pos {
119    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
120        write!(f, "({}, {})", self.x, self.y)
121    }
122}