1use crate::Vector;
2
3use num_traits::{Float, Num};
4use std::fmt;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub struct Point<T = f32> {
9 pub x: T,
11
12 pub y: T,
14}
15
16impl Point {
17 pub const ORIGIN: Self = Self::new(0.0, 0.0);
19}
20
21impl<T: Num> Point<T> {
22 pub const fn new(x: T, y: T) -> Self {
24 Self { x, y }
25 }
26
27 pub fn distance(&self, to: Self) -> T
29 where
30 T: Float,
31 {
32 let a = self.x - to.x;
33 let b = self.y - to.y;
34
35 a.hypot(b)
36 }
37}
38
39impl<T> From<[T; 2]> for Point<T>
40where
41 T: Num,
42{
43 fn from([x, y]: [T; 2]) -> Self {
44 Point { x, y }
45 }
46}
47
48impl<T> From<(T, T)> for Point<T>
49where
50 T: Num,
51{
52 fn from((x, y): (T, T)) -> Self {
53 Self { x, y }
54 }
55}
56
57impl<T> From<Point<T>> for [T; 2] {
58 fn from(point: Point<T>) -> [T; 2] {
59 [point.x, point.y]
60 }
61}
62
63impl<T> std::ops::Add<Vector<T>> for Point<T>
64where
65 T: std::ops::Add<Output = T>,
66{
67 type Output = Self;
68
69 fn add(self, vector: Vector<T>) -> Self {
70 Self {
71 x: self.x + vector.x,
72 y: self.y + vector.y,
73 }
74 }
75}
76
77impl<T> std::ops::Sub<Vector<T>> for Point<T>
78where
79 T: std::ops::Sub<Output = T>,
80{
81 type Output = Self;
82
83 fn sub(self, vector: Vector<T>) -> Self {
84 Self {
85 x: self.x - vector.x,
86 y: self.y - vector.y,
87 }
88 }
89}
90
91impl<T> std::ops::Sub<Point<T>> for Point<T>
92where
93 T: std::ops::Sub<Output = T>,
94{
95 type Output = Vector<T>;
96
97 fn sub(self, point: Self) -> Vector<T> {
98 Vector::new(self.x - point.x, self.y - point.y)
99 }
100}
101
102impl<T> fmt::Display for Point<T>
103where
104 T: fmt::Display,
105{
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
108 }
109}