1use point2i::Point2i;
4use point2u::Point2u;
5use vector2f::Vector2f;
6
7use std::ops::{Add, Sub};
8
9#[cfg(all(windows, feature = "d2d"))]
10use winapi::um::dcommon::D2D_POINT_2F;
11
12#[derive(Copy, Clone, Debug, Default, PartialEq)]
14#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
15#[repr(C)]
16pub struct Point2f {
17 pub x: f32,
19 pub y: f32,
21}
22
23pub const ORIGIN: Point2f = Point2f::ORIGIN;
25
26impl Point2f {
27 pub const ORIGIN: Point2f = Point2f { x: 0.0, y: 0.0 };
29
30 #[inline]
32 pub fn new(x: f32, y: f32) -> Self {
33 Point2f { x, y }
34 }
35
36 #[inline]
40 pub fn to_i32(self) -> Point2i {
41 Point2i {
42 x: self.x as i32,
43 y: self.y as i32,
44 }
45 }
46
47 #[inline]
52 pub fn to_u32(self) -> Point2u {
53 Point2u {
54 x: self.x as u32,
55 y: self.y as u32,
56 }
57 }
58
59 #[inline]
66 pub fn rounded(self) -> Point2f {
67 Point2f {
68 x: self.x.round(),
69 y: self.y.round(),
70 }
71 }
72
73 #[inline]
79 pub fn is_approx_eq(self, other: impl Into<Point2f>, epsilon: f32) -> bool {
80 let other = other.into();
81 return (self.x - other.x).abs() <= epsilon && (self.y - other.y).abs() <= epsilon;
82 }
83}
84
85impl<V> Add<V> for Point2f
86where
87 V: Into<Vector2f>,
88{
89 type Output = Point2f;
90
91 #[inline]
92 fn add(self, rhs: V) -> Point2f {
93 let rhs = rhs.into();
94 Point2f {
95 x: self.x + rhs.x,
96 y: self.y + rhs.y,
97 }
98 }
99}
100
101impl Sub for Point2f {
102 type Output = Vector2f;
103
104 #[inline]
105 fn sub(self, rhs: Point2f) -> Vector2f {
106 Vector2f {
107 x: self.x - rhs.x,
108 y: self.y - rhs.y,
109 }
110 }
111}
112
113impl Sub<(f32, f32)> for Point2f {
114 type Output = Vector2f;
115
116 #[inline]
117 fn sub(self, rhs: (f32, f32)) -> Vector2f {
118 Vector2f {
119 x: self.x - rhs.0,
120 y: self.y - rhs.1,
121 }
122 }
123}
124
125impl Sub<Point2f> for (f32, f32) {
126 type Output = Vector2f;
127
128 #[inline]
129 fn sub(self, rhs: Point2f) -> Vector2f {
130 Vector2f {
131 x: self.0 - rhs.x,
132 y: self.1 - rhs.y,
133 }
134 }
135}
136
137impl<V> Sub<V> for Point2f
138where
139 V: Into<Vector2f>,
140{
141 type Output = Point2f;
142
143 #[inline]
144 fn sub(self, rhs: V) -> Point2f {
145 let rhs = rhs.into();
146 Point2f {
147 x: self.x - rhs.x,
148 y: self.y - rhs.y,
149 }
150 }
151}
152
153impl From<(f32, f32)> for Point2f {
154 #[inline]
155 fn from((x, y): (f32, f32)) -> Point2f {
156 Point2f { x, y }
157 }
158}
159
160impl From<[f32; 2]> for Point2f {
161 #[inline]
162 fn from(p: [f32; 2]) -> Point2f {
163 Point2f { x: p[0], y: p[0] }
164 }
165}
166
167impl From<Point2f> for [f32; 2] {
168 #[inline]
169 fn from(p: Point2f) -> [f32; 2] {
170 [p.x, p.y]
171 }
172}
173
174#[cfg(all(windows, feature = "d2d"))]
175impl From<Point2f> for D2D_POINT_2F {
176 #[inline]
177 fn from(point: Point2f) -> D2D_POINT_2F {
178 D2D_POINT_2F {
179 x: point.x,
180 y: point.y,
181 }
182 }
183}
184
185#[cfg(all(windows, feature = "d2d"))]
186impl From<D2D_POINT_2F> for Point2f {
187 #[inline]
188 fn from(point: D2D_POINT_2F) -> Point2f {
189 Point2f {
190 x: point.x,
191 y: point.y,
192 }
193 }
194}
195
196#[cfg(feature = "mint")]
197impl From<Point2f> for mint::Point2<f32> {
198 #[inline]
199 fn from(p: Point2f) -> mint::Point2<f32> {
200 mint::Point2 { x: p.x, y: p.y }
201 }
202}
203
204#[cfg(feature = "mint")]
205impl From<mint::Point2<f32>> for Point2f {
206 #[inline]
207 fn from(p: mint::Point2<f32>) -> Point2f {
208 Point2f { x: p.x, y: p.y }
209 }
210}
211
212#[cfg(all(test, windows, feature = "d2d"))]
213#[test]
214fn pt2f_d2d_bin_compat() {
215 use std::mem::size_of_val;
216
217 fn ptr_eq<T>(a: &T, b: &T) -> bool {
218 (a as *const T) == (b as *const T)
219 }
220
221 let pt = Point2f::ORIGIN;
222 let d2d = unsafe { &*((&pt) as *const _ as *const D2D_POINT_2F) };
223
224 assert!(ptr_eq(&pt.x, &d2d.x));
225 assert!(ptr_eq(&pt.y, &d2d.y));
226 assert_eq!(size_of_val(&pt), size_of_val(d2d));
227}