math2d/
point2i.rs

1//! Mathematical point on the 2D (x, y) plane.
2
3use point2f::Point2f;
4use point2u::Point2u;
5use vector2i::Vector2i;
6
7use std::ops::{Add, Sub};
8
9#[cfg(all(windows, feature = "d2d"))]
10use winapi::um::dcommon::D2D_POINT_2L;
11
12/// Mathematical point on the 2D (x, y) plane.
13#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
14#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
15#[repr(C)]
16pub struct Point2i {
17    /// Horizontal component
18    pub x: i32,
19    /// Vertical component
20    pub y: i32,
21}
22
23impl Point2i {
24    /// Mathematical origin point
25    pub const ORIGIN: Point2i = Point2i { x: 0, y: 0 };
26
27    /// Construct a point from its components
28    #[inline]
29    pub fn new(x: i32, y: i32) -> Point2i {
30        Point2i { x, y }
31    }
32
33    /// Convert this value to a floating point
34    #[inline]
35    pub fn to_f32(self) -> Point2f {
36        Point2f {
37            x: self.x as f32,
38            y: self.y as f32,
39        }
40    }
41
42    /// Convert this value to an unsigned point. It is the caller's duty
43    /// to ensure the values are not negative to avoid casting underflow.
44    #[inline]
45    pub fn to_u32(self) -> Point2u {
46        Point2u {
47            x: self.x as u32,
48            y: self.y as u32,
49        }
50    }
51}
52
53impl<V> Add<V> for Point2i
54where
55    V: Into<Vector2i>,
56{
57    type Output = Point2i;
58
59    #[inline]
60    fn add(self, rhs: V) -> Point2i {
61        let rhs = rhs.into();
62        Point2i {
63            x: self.x + rhs.x,
64            y: self.y + rhs.y,
65        }
66    }
67}
68
69impl Add<Point2i> for Vector2i {
70    type Output = Point2i;
71
72    #[inline]
73    fn add(self, rhs: Point2i) -> Point2i {
74        rhs + self
75    }
76}
77
78impl Add<(i32, i32)> for Vector2i {
79    type Output = Point2i;
80
81    #[inline]
82    fn add(self, rhs: (i32, i32)) -> Point2i {
83        Point2i::from(rhs) + self
84    }
85}
86
87impl Sub for Point2i {
88    type Output = Vector2i;
89
90    #[inline]
91    fn sub(self, rhs: Point2i) -> Vector2i {
92        Vector2i {
93            x: self.x - rhs.x,
94            y: self.y - rhs.y,
95        }
96    }
97}
98
99impl Sub<(i32, i32)> for Point2i {
100    type Output = Vector2i;
101
102    #[inline]
103    fn sub(self, rhs: (i32, i32)) -> Vector2i {
104        Vector2i {
105            x: self.x - rhs.0,
106            y: self.y - rhs.0,
107        }
108    }
109}
110
111impl<V> Sub<V> for Point2i
112where
113    V: Into<Vector2i>,
114{
115    type Output = Point2i;
116
117    #[inline]
118    fn sub(self, rhs: V) -> Point2i {
119        let rhs = rhs.into();
120        Point2i {
121            x: self.x - rhs.x,
122            y: self.y - rhs.y,
123        }
124    }
125}
126
127impl From<(i32, i32)> for Point2i {
128    #[inline]
129    fn from((x, y): (i32, i32)) -> Point2i {
130        Point2i { x, y }
131    }
132}
133
134impl From<[i32; 2]> for Point2i {
135    #[inline]
136    fn from(p: [i32; 2]) -> Point2i {
137        Point2i { x: p[0], y: p[0] }
138    }
139}
140
141impl From<Point2i> for [i32; 2] {
142    #[inline]
143    fn from(p: Point2i) -> [i32; 2] {
144        [p.x, p.y]
145    }
146}
147
148#[cfg(all(windows, feature = "d2d"))]
149impl From<Point2i> for D2D_POINT_2L {
150    #[inline]
151    fn from(point: Point2i) -> D2D_POINT_2L {
152        D2D_POINT_2L {
153            x: point.x,
154            y: point.y,
155        }
156    }
157}
158
159#[cfg(all(windows, feature = "d2d"))]
160impl From<D2D_POINT_2L> for Point2i {
161    #[inline]
162    fn from(point: D2D_POINT_2L) -> Point2i {
163        Point2i {
164            x: point.x,
165            y: point.y,
166        }
167    }
168}
169
170#[cfg(feature = "mint")]
171impl From<Point2i> for mint::Point2<i32> {
172    #[inline]
173    fn from(p: Point2i) -> mint::Point2<i32> {
174        mint::Point2 { x: p.x, y: p.y }
175    }
176}
177
178#[cfg(feature = "mint")]
179impl From<mint::Point2<i32>> for Point2i {
180    #[inline]
181    fn from(p: mint::Point2<i32>) -> Point2i {
182        Point2i { x: p.x, y: p.y }
183    }
184}
185
186#[cfg(all(test, windows, feature = "d2d"))]
187#[test]
188fn pt2i_d2d_bin_compat() {
189    use std::mem::size_of_val;
190
191    fn ptr_eq<T>(a: &T, b: &T) -> bool {
192        (a as *const T) == (b as *const T)
193    }
194
195    let pt = Point2i::ORIGIN;
196    let d2d = unsafe { &*((&pt) as *const _ as *const D2D_POINT_2L) };
197
198    assert!(ptr_eq(&pt.x, &d2d.x));
199    assert!(ptr_eq(&pt.y, &d2d.y));
200    assert_eq!(size_of_val(&pt), size_of_val(d2d));
201}