iced_core/
point.rs

1use crate::Vector;
2
3use num_traits::{Float, Num};
4use std::fmt;
5
6/// A 2D point.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub struct Point<T = f32> {
9    /// The X coordinate.
10    pub x: T,
11
12    /// The Y coordinate.
13    pub y: T,
14}
15
16impl Point {
17    /// The origin (i.e. a [`Point`] at (0, 0)).
18    pub const ORIGIN: Self = Self::new(0.0, 0.0);
19}
20
21impl<T: Num> Point<T> {
22    /// Creates a new [`Point`] with the given coordinates.
23    pub const fn new(x: T, y: T) -> Self {
24        Self { x, y }
25    }
26
27    /// Computes the distance to another [`Point`].
28    pub fn distance(&self, to: Self) -> T
29    where
30        T: Float,
31    {
32        let a = self.x - to.x;
33        let b = self.y - to.y;
34
35        a.hypot(b)
36    }
37}
38
39impl<T> From<[T; 2]> for Point<T>
40where
41    T: Num,
42{
43    fn from([x, y]: [T; 2]) -> Self {
44        Point { x, y }
45    }
46}
47
48impl<T> From<(T, T)> for Point<T>
49where
50    T: Num,
51{
52    fn from((x, y): (T, T)) -> Self {
53        Self { x, y }
54    }
55}
56
57impl<T> From<Point<T>> for [T; 2] {
58    fn from(point: Point<T>) -> [T; 2] {
59        [point.x, point.y]
60    }
61}
62
63impl<T> std::ops::Add<Vector<T>> for Point<T>
64where
65    T: std::ops::Add<Output = T>,
66{
67    type Output = Self;
68
69    fn add(self, vector: Vector<T>) -> Self {
70        Self {
71            x: self.x + vector.x,
72            y: self.y + vector.y,
73        }
74    }
75}
76
77impl<T> std::ops::AddAssign<Vector<T>> for Point<T>
78where
79    T: std::ops::AddAssign,
80{
81    fn add_assign(&mut self, vector: Vector<T>) {
82        self.x += vector.x;
83        self.y += vector.y;
84    }
85}
86
87impl<T> std::ops::Sub<Vector<T>> for Point<T>
88where
89    T: std::ops::Sub<Output = T>,
90{
91    type Output = Self;
92
93    fn sub(self, vector: Vector<T>) -> Self {
94        Self {
95            x: self.x - vector.x,
96            y: self.y - vector.y,
97        }
98    }
99}
100
101impl<T> std::ops::SubAssign<Vector<T>> for Point<T>
102where
103    T: std::ops::SubAssign,
104{
105    fn sub_assign(&mut self, vector: Vector<T>) {
106        self.x -= vector.x;
107        self.y -= vector.y;
108    }
109}
110
111impl<T> std::ops::Sub<Point<T>> for Point<T>
112where
113    T: std::ops::Sub<Output = T>,
114{
115    type Output = Vector<T>;
116
117    fn sub(self, point: Self) -> Vector<T> {
118        Vector::new(self.x - point.x, self.y - point.y)
119    }
120}
121
122impl<T> fmt::Display for Point<T>
123where
124    T: fmt::Display,
125{
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
128    }
129}
130
131impl Point<f32> {
132    /// Snaps the [`Point`] to __unsigned__ integer coordinates.
133    pub fn snap(self) -> Point<u32> {
134        Point {
135            x: self.x.round() as u32,
136            y: self.y.round() as u32,
137        }
138    }
139}