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