1use crate::traits::{BoundingBox, MapPointwise, TryBoundingBox, TryCastCoord};
9use crate::vector::Vector;
10
11use std::cmp::{Ord, Ordering};
12use std::fmt;
13
14use crate::prelude::{Orientation2D, Rect};
15pub use num_traits::Zero;
16use num_traits::{Float, NumCast};
17pub use std::ops::Deref;
18use std::ops::{Add, AddAssign, DerefMut, Div, Mul, MulAssign, Neg, Sub, SubAssign};
19
20#[macro_export]
33macro_rules! point {
34 ($x:expr, $y:expr) => {
35 Point::new($x, $y)
36 };
37}
38
39#[derive(Copy, Clone, Default, Hash, PartialEq, Eq)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42pub struct Point<T> {
43 location: Vector<T>,
45}
46
47impl<T> Deref for Point<T> {
48 type Target = Vector<T>;
49
50 #[inline]
51 fn deref(&self) -> &Self::Target {
52 &self.location
53 }
54}
55
56impl<T> DerefMut for Point<T> {
57 #[inline]
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 &mut self.location
60 }
61}
62
63impl<T> From<Vector<T>> for Point<T> {
64 #[inline]
65 fn from(v: Vector<T>) -> Self {
66 Point { location: v }
67 }
68}
69
70impl<T: Copy> From<&Vector<T>> for Point<T> {
71 #[inline]
72 fn from(v: &Vector<T>) -> Self {
73 Self::from(*v)
74 }
75}
76
77impl<T> From<Point<T>> for Vector<T> {
78 #[inline]
79 fn from(p: Point<T>) -> Self {
80 p.location
81 }
82}
83
84impl<T: Copy> From<&Point<T>> for Vector<T> {
85 #[inline]
86 fn from(p: &Point<T>) -> Self {
87 p.location
88 }
89}
90
91impl<T> Point<T> {
92 #[inline]
94 pub fn new(x: T, y: T) -> Self {
95 Point {
96 location: Vector::new(x, y),
97 }
98 }
99}
100
101impl<T: Copy> Point<T> {
102 #[inline]
104 pub fn v(&self) -> Vector<T> {
105 self.location
106 }
107
108 #[inline]
110 pub fn get(&self, coord: Orientation2D) -> T {
111 match coord {
112 Orientation2D::Horizontal => self.x,
113 Orientation2D::Vertical => self.y,
114 }
115 }
116
117 #[inline]
119 pub fn set(&mut self, coord: Orientation2D, value: T) {
120 match coord {
121 Orientation2D::Horizontal => self.x = value,
122 Orientation2D::Vertical => self.y = value,
123 }
124 }
125}
126
127impl<T: Zero> Point<T> {
128 #[inline]
140 pub fn zero() -> Self {
141 Vector::zero().into()
142 }
143
144 #[inline]
153 pub fn is_zero(&self) -> bool {
154 self.x.is_zero() && self.y.is_zero()
155 }
156}
157
158impl<T: Copy + Mul<Output = T> + Add<Output = T> + Sub<Output = T>> Point<T> {
159 #[inline]
170 pub fn distance_sq(self, other: &Point<T>) -> T {
171 let diff = self - *other;
172 diff.norm2_squared()
173 }
174
175 #[inline]
196 pub fn cross_prod3(&self, b: Point<T>, c: Point<T>) -> T {
197 (b.x - self.x) * (c.y - b.y) - (b.y - self.y) * (c.x - b.x)
198 }
199}
200
201impl<T: Copy + Sub<Output = T> + NumCast> Point<T> {
202 #[inline]
204 pub fn distance<F: Float>(self, other: &Point<T>) -> F {
205 let diff = self - *other;
206 diff.length()
207 }
208}
209
210impl<T: PartialOrd> PartialOrd for Point<T> {
217 #[inline]
218 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
219 match self.x.partial_cmp(&rhs.x) {
220 Some(Ordering::Equal) => self.y.partial_cmp(&rhs.y),
221 maybe_ordering => maybe_ordering,
222 }
223 }
224}
225
226impl<T: Ord> Ord for Point<T> {
233 #[inline]
234 fn cmp(&self, rhs: &Self) -> Ordering {
235 match self.x.cmp(&rhs.x) {
236 Ordering::Equal => self.y.cmp(&rhs.y),
237 ordering => ordering,
238 }
239 }
240}
241
242impl<T: Copy> MapPointwise<T> for Point<T> {
244 #[inline]
246 fn transform<F>(&self, transformation: F) -> Self
247 where
248 F: Fn(Point<T>) -> Point<T>,
249 {
250 transformation(*self)
251 }
252}
253
254impl<T: Copy> From<Point<T>> for (T, T) {
255 #[inline]
256 fn from(p: Point<T>) -> Self {
257 (p.x, p.y)
258 }
259}
260
261impl<T: Copy> From<&Point<T>> for (T, T) {
262 #[inline]
263 fn from(p: &Point<T>) -> Self {
264 (p.x, p.y)
265 }
266}
267
268impl<T: Copy> From<(T, T)> for Point<T> {
269 #[inline]
270 fn from(coords: (T, T)) -> Self {
271 Point::new(coords.0, coords.1)
272 }
273}
274
275impl<'a, T: Copy> From<&'a (T, T)> for Point<T> {
276 #[inline]
277 fn from(coords: &'a (T, T)) -> Self {
278 Point::new(coords.0, coords.1)
279 }
280}
281
282impl<'a, T: Copy> From<&'a Point<T>> for Point<T> {
283 #[inline]
284 fn from(v: &'a Point<T>) -> Self {
285 Point::new(v.x, v.y)
286 }
287}
288
289impl<T: Copy> From<[T; 2]> for Point<T> {
290 #[inline]
291 fn from(coords: [T; 2]) -> Self {
292 Point::new(coords[0], coords[1])
293 }
294}
295
296impl<T: Copy> From<Point<T>> for [T; 2] {
297 #[inline]
298 fn from(p: Point<T>) -> Self {
299 [p.x, p.y]
300 }
301}
302
303impl<T> fmt::Debug for Point<T>
304where
305 T: fmt::Debug,
306{
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 write!(f, "Point({:?}, {:?})", self.x, self.y)
309 }
310}
311
312impl<T> fmt::Display for Point<T>
313where
314 T: fmt::Display,
315{
316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317 write!(f, "({}, {})", self.x, self.y)
318 }
319}
320
321impl<T: Copy + NumCast> Point<T> {
322 #[inline]
324 pub fn cast_to_float<F: Float + NumCast>(&self) -> Point<F> {
325 Point::new(F::from(self.x).unwrap(), F::from(self.y).unwrap())
327 }
328}
329
330impl<T: Copy + NumCast, Dst: Copy + NumCast> TryCastCoord<T, Dst> for Point<T> {
331 type Output = Point<Dst>;
332
333 #[inline]
334 fn try_cast(&self) -> Option<Self::Output> {
335 match (Dst::from(self.x), Dst::from(self.y)) {
336 (Some(x), Some(y)) => Some(Point::new(x, y)),
337 _ => None,
338 }
339 }
340}
341
342impl<T, V> Add<V> for Point<T>
344where
345 T: Copy + Add<Output = T>,
346 V: Into<Point<T>>,
347{
348 type Output = Self;
349
350 #[inline]
351 fn add(self, rhs: V) -> Self {
352 let rhs = rhs.into();
353 Point::new(self.x + rhs.x, self.y + rhs.y)
354 }
355}
356
357impl<T, V> AddAssign<V> for Point<T>
358where
359 T: Copy + AddAssign<T>,
360 V: Into<Vector<T>>,
361{
362 #[inline]
363 fn add_assign(&mut self, rhs: V) {
364 let rhs = rhs.into();
365 self.location += rhs;
366 }
367}
368
369impl<T> Sub<Point<T>> for Point<T>
371where
372 T: Copy + Sub<Output = T>,
373{
374 type Output = Vector<T>;
375
376 #[inline]
377 fn sub(self, rhs: Point<T>) -> Self::Output {
378 Vector::new(self.x - rhs.x, self.y - rhs.y)
379 }
380}
381
382impl<T> Sub<Vector<T>> for Point<T>
384where
385 T: Copy + Sub<Output = T>,
386{
387 type Output = Point<T>;
388
389 #[inline]
390 fn sub(self, rhs: Vector<T>) -> Self::Output {
391 Point::new(self.x - rhs.x, self.y - rhs.y)
392 }
393}
394
395impl<T, V> SubAssign<V> for Point<T>
396where
397 T: Copy + SubAssign<T>,
398 V: Into<Vector<T>>,
399{
400 #[inline]
401 fn sub_assign(&mut self, rhs: V) {
402 let rhs = rhs.into();
403 self.location -= rhs;
404 }
405}
406
407impl<T> Neg for Point<T>
408where
409 T: Copy + Neg<Output = T>,
410{
411 type Output = Self;
412
413 #[inline]
414 fn neg(self) -> Self {
415 Point::new(-self.x, -self.y)
416 }
417}
418
419impl<T> Mul<T> for Point<T>
421where
422 T: Copy + Mul<Output = T>,
423{
424 type Output = Self;
425
426 #[inline]
427 fn mul(self, rhs: T) -> Self {
428 Point::new(self.x * rhs, self.y * rhs)
429 }
430}
431
432impl<T> MulAssign<T> for Point<T>
434where
435 T: Copy + MulAssign<T>,
436{
437 #[inline]
438 fn mul_assign(&mut self, rhs: T) {
439 self.location *= rhs;
440 }
441}
442
443impl<T> Div<T> for Point<T>
445where
446 T: Copy + Div<Output = T>,
447{
448 type Output = Self;
449
450 #[inline]
451 fn div(self, rhs: T) -> Self {
452 Point::new(self.x / rhs, self.y / rhs)
453 }
454}
455
456impl<T: Copy + Zero + Add<Output = T>> std::iter::Sum for Point<T> {
457 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
460 iter.fold(Self::zero(), |acc, p| acc + p)
461 }
462}
463
464impl<T: Copy> BoundingBox<T> for Point<T> {
465 fn bounding_box(&self) -> Rect<T> {
466 Rect {
467 lower_left: *self,
468 upper_right: *self,
469 }
470 }
471}
472
473impl<T: Copy> TryBoundingBox<T> for Point<T> {
474 fn try_bounding_box(&self) -> Option<Rect<T>> {
475 Some(self.bounding_box())
476 }
477}