firefly_rust/graphics/
point.rs

1use super::*;
2use core::num::TryFromIntError;
3use core::ops::*;
4#[cfg(feature = "nalgebra")]
5use nalgebra::{base::Scalar, Vector2};
6
7/// A point on the screen.
8///
9/// Typically, the upper-left corner of a bounding box of a shape.
10#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
11pub struct Point {
12    /// Pixel distance from left.
13    pub x: i32,
14    /// Pixel distance from the top.
15    pub y: i32,
16}
17
18impl Point {
19    /// The coordinate of the bottom-right corner on the screen.
20    pub const MAX: Point = Point {
21        x: WIDTH,
22        y: HEIGHT,
23    };
24    /// The coordinate of the top-left corner on the screen.
25    pub const MIN: Point = Point { x: 0, y: 0 };
26
27    /// Create a new point casting the argument types.
28    #[must_use]
29    pub fn new<I: Into<i32>>(x: I, y: I) -> Self {
30        Self {
31            x: x.into(),
32            y: y.into(),
33        }
34    }
35
36    /// Set x and y to their absolute (non-negative) value.
37    #[must_use]
38    pub const fn abs(self) -> Self {
39        Self {
40            x: self.x.abs(),
41            y: self.y.abs(),
42        }
43    }
44
45    /// Set both x and y to their minimum in the two given points.
46    #[must_use]
47    pub fn component_min(self, other: Self) -> Self {
48        Self {
49            x: self.x.min(other.x),
50            y: self.y.min(other.y),
51        }
52    }
53
54    /// Set both x and y to their maximum in the two given points.
55    #[must_use]
56    pub fn component_max(self, other: Self) -> Self {
57        Self {
58            x: self.x.max(other.x),
59            y: self.y.max(other.y),
60        }
61    }
62}
63
64impl Add for Point {
65    type Output = Self;
66
67    fn add(self, other: Point) -> Self {
68        Self {
69            x: self.x + other.x,
70            y: self.y + other.y,
71        }
72    }
73}
74
75impl Add<Size> for Point {
76    type Output = Self;
77
78    fn add(self, other: Size) -> Self {
79        Self {
80            x: self.x + other.width,
81            y: self.y + other.height,
82        }
83    }
84}
85
86impl AddAssign for Point {
87    fn add_assign(&mut self, other: Point) {
88        self.x += other.x;
89        self.y += other.y;
90    }
91}
92
93impl AddAssign<Size> for Point {
94    fn add_assign(&mut self, other: Size) {
95        self.x += other.width;
96        self.y += other.height;
97    }
98}
99
100impl Sub for Point {
101    type Output = Self;
102
103    fn sub(self, other: Point) -> Self {
104        Self {
105            x: self.x - other.x,
106            y: self.y - other.y,
107        }
108    }
109}
110
111impl Sub<Size> for Point {
112    type Output = Self;
113
114    fn sub(self, other: Size) -> Self {
115        Self {
116            x: self.x - other.width,
117            y: self.y - other.height,
118        }
119    }
120}
121
122impl SubAssign for Point {
123    fn sub_assign(&mut self, other: Point) {
124        self.x -= other.x;
125        self.y -= other.y;
126    }
127}
128
129impl SubAssign<Size> for Point {
130    fn sub_assign(&mut self, other: Size) {
131        self.x -= other.width;
132        self.y -= other.height;
133    }
134}
135
136impl Mul<i32> for Point {
137    type Output = Self;
138
139    fn mul(self, rhs: i32) -> Self {
140        Self {
141            x: self.x * rhs,
142            y: self.y * rhs,
143        }
144    }
145}
146
147impl MulAssign<i32> for Point {
148    fn mul_assign(&mut self, rhs: i32) {
149        self.x *= rhs;
150        self.y *= rhs;
151    }
152}
153
154impl Div<i32> for Point {
155    type Output = Self;
156
157    fn div(self, rhs: i32) -> Self {
158        Self {
159            x: self.x / rhs,
160            y: self.y / rhs,
161        }
162    }
163}
164
165impl DivAssign<i32> for Point {
166    fn div_assign(&mut self, rhs: i32) {
167        self.x /= rhs;
168        self.y /= rhs;
169    }
170}
171
172impl Index<usize> for Point {
173    type Output = i32;
174
175    fn index(&self, idx: usize) -> &i32 {
176        match idx {
177            0 => &self.x,
178            1 => &self.y,
179            _ => panic!("index out of bounds: the len is 2 but the index is {idx}"),
180        }
181    }
182}
183
184impl Neg for Point {
185    type Output = Self;
186
187    fn neg(self) -> Self {
188        Self {
189            x: -self.x,
190            y: -self.y,
191        }
192    }
193}
194
195impl From<Size> for Point {
196    fn from(value: Size) -> Self {
197        Self {
198            x: value.width,
199            y: value.height,
200        }
201    }
202}
203
204impl From<(i32, i32)> for Point {
205    fn from(other: (i32, i32)) -> Self {
206        Self {
207            x: other.0,
208            y: other.1,
209        }
210    }
211}
212
213impl From<[i32; 2]> for Point {
214    fn from(other: [i32; 2]) -> Self {
215        Self {
216            x: other[0],
217            y: other[1],
218        }
219    }
220}
221
222impl From<&[i32; 2]> for Point {
223    fn from(other: &[i32; 2]) -> Self {
224        Self {
225            x: other[0],
226            y: other[1],
227        }
228    }
229}
230
231impl From<Point> for (i32, i32) {
232    fn from(other: Point) -> (i32, i32) {
233        (other.x, other.y)
234    }
235}
236
237impl From<Point> for [i32; 2] {
238    fn from(other: Point) -> [i32; 2] {
239        [other.x, other.y]
240    }
241}
242
243impl From<&Point> for (i32, i32) {
244    fn from(other: &Point) -> (i32, i32) {
245        (other.x, other.y)
246    }
247}
248
249impl TryFrom<Point> for (u32, u32) {
250    type Error = TryFromIntError;
251
252    fn try_from(point: Point) -> Result<Self, Self::Error> {
253        Ok((point.x.try_into()?, point.y.try_into()?))
254    }
255}
256
257impl TryFrom<(u32, u32)> for Point {
258    type Error = TryFromIntError;
259
260    fn try_from(point: (u32, u32)) -> Result<Self, Self::Error> {
261        let x = point.0.try_into()?;
262        let y = point.1.try_into()?;
263
264        Ok(Self { x, y })
265    }
266}
267
268impl TryFrom<Point> for [u32; 2] {
269    type Error = TryFromIntError;
270
271    fn try_from(point: Point) -> Result<Self, Self::Error> {
272        Ok([point.x.try_into()?, point.y.try_into()?])
273    }
274}
275
276impl TryFrom<[u32; 2]> for Point {
277    type Error = TryFromIntError;
278
279    fn try_from(point: [u32; 2]) -> Result<Self, Self::Error> {
280        let x = point[0].try_into()?;
281        let y = point[1].try_into()?;
282
283        Ok(Self { x, y })
284    }
285}
286
287impl TryFrom<&[u32; 2]> for Point {
288    type Error = TryFromIntError;
289
290    fn try_from(point: &[u32; 2]) -> Result<Self, Self::Error> {
291        let x = point[0].try_into()?;
292        let y = point[1].try_into()?;
293
294        Ok(Self { x, y })
295    }
296}
297
298#[cfg(feature = "nalgebra")]
299impl<N> From<Vector2<N>> for Point
300where
301    N: Into<i32> + Scalar + Copy,
302{
303    fn from(other: Vector2<N>) -> Self {
304        Self {
305            x: other[0].into(),
306            y: other[1].into(),
307        }
308    }
309}
310
311#[cfg(feature = "nalgebra")]
312impl<N> From<&Vector2<N>> for Point
313where
314    N: Into<i32> + Scalar + Copy,
315{
316    fn from(other: &Vector2<N>) -> Self {
317        Self {
318            x: other[0].into(),
319            y: other[1].into(),
320        }
321    }
322}