1use std::convert::{From, TryInto};
2use std::ops;
3use ultraviolet::Vec2;
4
5pub type PointF = Vec2;
7
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash)]
10pub struct Point {
12 pub x: i32,
14 pub y: i32,
16}
17
18#[cfg(feature = "specs")]
19impl specs::prelude::Component for Point {
20 type Storage = specs::prelude::VecStorage<Self>;
21}
22
23#[cfg(feature = "bevy")]
24impl bevy::ecs::component::Component for Point {
25 type Storage = bevy::ecs::component::TableStorage;
26}
27
28impl Point {
29 #[inline]
31 #[must_use]
32 pub fn new<T>(x: T, y: T) -> Point
33 where
34 T: TryInto<i32>,
35 {
36 Point {
37 x: x.try_into().ok().unwrap_or(0),
38 y: y.try_into().ok().unwrap_or(0),
39 }
40 }
41
42 #[must_use]
44 pub const fn constant(x: i32, y: i32) -> Self {
45 Point { x, y }
46 }
47
48 #[inline]
50 pub fn zero() -> Self {
51 Point { x: 0, y: 0 }
52 }
53
54 #[inline]
55 pub fn from_tuple<T>(t: (T, T)) -> Self
57 where
58 T: TryInto<i32>,
59 {
60 Point::new(t.0, t.1)
61 }
62
63 #[inline]
64 #[must_use]
66 pub fn to_index<T>(self, width: T) -> usize
67 where
68 T: TryInto<usize>,
69 {
70 let x: usize = self.x.try_into().ok().unwrap();
71 let y: usize = self.y.try_into().ok().unwrap();
72 let w: usize = width.try_into().ok().unwrap();
73 (y * w) + x
74 }
75
76 #[must_use]
78 pub fn to_tuple(self) -> (i32, i32) {
79 (self.x, self.y)
80 }
81
82 #[must_use]
88 pub fn to_unsigned_tuple(self) -> (usize, usize) {
89 (
90 self.x.try_into().ok().unwrap(),
91 self.y.try_into().ok().unwrap(),
92 )
93 }
94
95 #[must_use]
97 pub fn to_vec2(self) -> Vec2 {
98 Vec2::new(self.x as f32, self.y as f32)
99 }
100
101 pub fn from_vec2(v: Vec2) -> Self {
111 Self::new(v.x as i32, v.y as i32)
112 }
113
114 }
121
122impl From<(i32, i32)> for Point {
123 fn from(item: (i32, i32)) -> Self {
124 Self {
125 x: item.0,
126 y: item.1,
127 }
128 }
129}
130
131impl From<(f32, f32)> for Point {
132 fn from(item: (f32, f32)) -> Self {
133 Self {
134 x: item.0 as i32,
135 y: item.1 as i32,
136 }
137 }
138}
139
140impl From<Vec2> for Point {
141 fn from(item: Vec2) -> Self {
142 Self {
143 x: item.x as i32,
144 y: item.y as i32,
145 }
146 }
147}
148
149impl ops::Add<Point> for Point {
165 type Output = Point;
166 fn add(mut self, rhs: Point) -> Point {
167 self.x += rhs.x;
168 self.y += rhs.y;
169 self
170 }
171}
172
173impl ops::Add<i32> for Point {
175 type Output = Point;
176 fn add(mut self, rhs: i32) -> Point {
177 self.x += rhs;
178 self.y += rhs;
179 self
180 }
181}
182
183impl ops::Sub<Point> for Point {
185 type Output = Point;
186 fn sub(mut self, rhs: Point) -> Point {
187 self.x -= rhs.x;
188 self.y -= rhs.y;
189 self
190 }
191}
192
193impl ops::Sub<i32> for Point {
195 type Output = Point;
196 fn sub(mut self, rhs: i32) -> Point {
197 self.x -= rhs;
198 self.y -= rhs;
199 self
200 }
201}
202
203impl ops::Mul<Point> for Point {
205 type Output = Point;
206 fn mul(mut self, rhs: Point) -> Point {
207 self.x *= rhs.x;
208 self.y *= rhs.y;
209 self
210 }
211}
212
213impl ops::Mul<i32> for Point {
215 type Output = Point;
216 fn mul(mut self, rhs: i32) -> Point {
217 self.x *= rhs;
218 self.y *= rhs;
219 self
220 }
221}
222
223impl ops::Mul<f32> for Point {
225 type Output = Point;
226 fn mul(mut self, rhs: f32) -> Point {
227 self.x = (self.x as f32 * rhs) as i32;
228 self.y = (self.y as f32 * rhs) as i32;
229 self
230 }
231}
232
233impl ops::Div<Point> for Point {
235 type Output = Point;
236 fn div(mut self, rhs: Point) -> Point {
237 self.x /= rhs.x;
238 self.y /= rhs.y;
239 self
240 }
241}
242
243impl ops::Div<i32> for Point {
245 type Output = Point;
246 fn div(mut self, rhs: i32) -> Point {
247 self.x /= rhs;
248 self.y /= rhs;
249 self
250 }
251}
252
253impl ops::Div<f32> for Point {
255 type Output = Point;
256 fn div(mut self, rhs: f32) -> Point {
257 self.x = (self.x as f32 / rhs) as i32;
258 self.y = (self.y as f32 / rhs) as i32;
259 self
260 }
261}
262
263impl ops::AddAssign for Point {
264 fn add_assign(&mut self, other: Self) {
265 *self = Self {
266 x: self.x + other.x,
267 y: self.y + other.y,
268 };
269 }
270}
271
272impl ops::SubAssign for Point {
273 fn sub_assign(&mut self, other: Self) {
274 *self = Self {
275 x: self.x - other.x,
276 y: self.y - other.y,
277 };
278 }
279}
280
281impl ops::MulAssign for Point {
282 fn mul_assign(&mut self, other: Self) {
283 *self = Self {
284 x: self.x * other.x,
285 y: self.y * other.y,
286 };
287 }
288}
289
290impl ops::DivAssign for Point {
291 fn div_assign(&mut self, other: Self) {
292 *self = Self {
293 x: self.x / other.x,
294 y: self.y / other.y,
295 };
296 }
297}
298
299#[cfg(test)]
301mod tests {
302 use super::Point;
303
304 #[test]
305 fn new_point() {
306 let pt = Point::new(1, 2);
307 assert_eq!(pt.x, 1);
308 assert_eq!(pt.y, 2);
309 }
310
311 #[test]
312 fn add_point_to_point() {
313 let pt = Point::new(0, 0);
314 let p2 = pt + Point::new(1, 2);
315 assert_eq!(p2.x, 1);
316 assert_eq!(p2.y, 2);
317 }
318
319 #[test]
320 fn add_assign_point_to_point() {
321 let mut pt = Point::new(0, 0);
322 pt += Point::new(1, 2);
323 assert_eq!(pt.x, 1);
324 assert_eq!(pt.y, 2);
325 }
326
327 #[test]
328 fn add_point_to_int() {
329 let pt = Point::new(0, 0);
330 let p2 = pt + 2;
331 assert_eq!(p2.x, 2);
332 assert_eq!(p2.y, 2);
333 }
334
335 #[test]
336 fn sub_point_to_point() {
337 let pt = Point::new(0, 0);
338 let p2 = pt - Point::new(1, 2);
339 assert_eq!(p2.x, -1);
340 assert_eq!(p2.y, -2);
341 }
342
343 #[test]
344 fn sub_assign_point_to_point() {
345 let mut pt = Point::new(0, 0);
346 pt -= Point::new(1, 2);
347 assert_eq!(pt.x, -1);
348 assert_eq!(pt.y, -2);
349 }
350
351 #[test]
352 fn sub_point_to_int() {
353 let pt = Point::new(0, 0);
354 let p2 = pt - 2;
355 assert_eq!(p2.x, -2);
356 assert_eq!(p2.y, -2);
357 }
358
359 #[test]
360 fn mul_point_to_point() {
361 let pt = Point::new(1, 1);
362 let p2 = pt * Point::new(1, 2);
363 assert_eq!(p2.x, 1);
364 assert_eq!(p2.y, 2);
365 }
366
367 #[test]
368 fn mul_assign_point_to_point() {
369 let mut pt = Point::new(1, 1);
370 pt *= Point::new(1, 2);
371 assert_eq!(pt.x, 1);
372 assert_eq!(pt.y, 2);
373 }
374
375 #[test]
376 fn mul_point_to_int() {
377 let pt = Point::new(1, 1);
378 let p2 = pt * 2;
379 assert_eq!(p2.x, 2);
380 assert_eq!(p2.y, 2);
381 }
382
383 #[test]
384 fn mul_point_to_float() {
385 let pt = Point::new(1, 1);
386 let p2 = pt * 4.0;
387 assert_eq!(p2.x, 4);
388 assert_eq!(p2.y, 4);
389 }
390
391 #[test]
392 fn div_point_to_point() {
393 let pt = Point::new(4, 4);
394 let p2 = pt / Point::new(2, 4);
395 assert_eq!(p2.x, 2);
396 assert_eq!(p2.y, 1);
397 }
398
399 #[test]
400 fn div_assign_point_to_point() {
401 let mut pt = Point::new(4, 4);
402 pt /= Point::new(2, 4);
403 assert_eq!(pt.x, 2);
404 assert_eq!(pt.y, 1);
405 }
406
407 #[test]
408 fn div_point_to_int() {
409 let pt = Point::new(4, 4);
410 let p2 = pt / 2;
411 assert_eq!(p2.x, 2);
412 assert_eq!(p2.y, 2);
413 }
414
415 #[test]
416 fn div_point_to_float() {
417 let pt = Point::new(4, 4);
418 let p2 = pt / 2.0;
419 assert_eq!(p2.x, 2);
420 assert_eq!(p2.y, 2);
421 }
422}