1use num_traits::Zero;
2use std::ops::{Add, Mul, Neg, Sub};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct Point<T> {
6 pub x: T,
7 pub y: T,
8}
9
10impl<T> Point<T> {
11 pub fn new(x: T, y: T) -> Self {
12 Point { x, y }
13 }
14}
15
16impl<T> From<(T, T)> for Point<T> {
17 fn from((x, y): (T, T)) -> Self {
18 Point { x, y }
19 }
20}
21
22impl<T> Point<T>
23where
24 T: Copy + Zero + PartialEq,
25{
26 pub fn zero() -> Self {
27 Point {
28 x: T::zero(),
29 y: T::zero(),
30 }
31 }
32
33 pub fn is_zero(&self) -> bool {
34 self.x == T::zero() && self.y == T::zero()
35 }
36}
37
38impl<T> Add for Point<T>
39where
40 T: Add<Output = T> + Copy,
41{
42 type Output = Point<T>;
43 fn add(self, rhs: Point<T>) -> Self::Output {
44 Point {
45 x: self.x + rhs.x,
46 y: self.y + rhs.y,
47 }
48 }
49}
50
51impl<T> Sub for Point<T>
52where
53 T: Sub<Output = T> + Copy,
54{
55 type Output = Point<T>;
56 fn sub(self, rhs: Point<T>) -> Self::Output {
57 Point {
58 x: self.x - rhs.x,
59 y: self.y - rhs.y,
60 }
61 }
62}
63
64impl<T> Mul<T> for Point<T>
65where
66 T: Mul<Output = T> + Copy,
67{
68 type Output = Point<T>;
69 fn mul(self, rhs: T) -> Self::Output {
70 Point {
71 x: self.x * rhs,
72 y: self.y * rhs,
73 }
74 }
75}
76
77impl<T> Neg for Point<T>
78where
79 T: Neg<Output = T> + Copy,
80{
81 type Output = Point<T>;
82 fn neg(self) -> Self::Output {
83 Point {
84 x: -self.x,
85 y: -self.y,
86 }
87 }
88}
89
90impl<T> Point<T>
91where
92 T: Copy + Mul<Output = T> + Add<Output = T>,
93{
94 pub fn dot(self, other: Point<T>) -> T {
95 self.x * other.x + self.y * other.y
96 }
97}
98
99#[cfg(feature = "float")]
100impl<T> Point<T>
101where
102 T: Copy + Sub<Output = T> + Into<f64>,
103{
104 pub fn distance(self, other: Point<T>) -> f64 {
105 let dx: f64 = (self.x - other.x).into();
106 let dy: f64 = (self.y - other.y).into();
107 (dx * dx + dy * dy).sqrt()
108 }
109
110 pub fn magnitude(self) -> f64 {
111 let x: f64 = self.x.into();
112 let y: f64 = self.y.into();
113 (x * x + y * y).sqrt()
114 }
115}