1use num_traits::{Num, Signed};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6pub trait SpadeNum:
13 Num + PartialOrd + Into<f64> + From<f32> + Copy + Signed + core::fmt::Debug
14{
15}
16
17impl<T> SpadeNum for T where
18 T: Num + PartialOrd + Into<f64> + From<f32> + Copy + Signed + core::fmt::Debug
19{
20}
21
22#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy, Default, Hash)]
26#[cfg_attr(
27 feature = "serde",
28 derive(Serialize, Deserialize),
29 serde(crate = "serde")
30)]
31pub struct Point2<S> {
32 pub x: S,
34 pub y: S,
36}
37
38impl<S> Point2<S> {
39 #[inline]
41 pub const fn new(x: S, y: S) -> Self {
42 Point2 { x, y }
43 }
44}
45
46impl<S: SpadeNum> Point2<S> {
47 #[inline]
49 pub fn distance_2(&self, other: Self) -> S {
50 self.sub(other).length2()
51 }
52
53 pub(crate) fn to_f64(self) -> Point2<f64> {
54 Point2::new(self.x.into(), self.y.into())
55 }
56
57 pub(crate) fn mul(&self, factor: S) -> Self {
58 Point2 {
59 x: self.x * factor,
60 y: self.y * factor,
61 }
62 }
63
64 pub(crate) fn add(&self, other: Self) -> Self {
65 Point2 {
66 x: self.x + other.x,
67 y: self.y + other.y,
68 }
69 }
70
71 pub(crate) fn length2(&self) -> S {
72 self.x * self.x + self.y * self.y
73 }
74
75 pub(crate) fn sub(&self, other: Self) -> Self {
76 Point2 {
77 x: self.x - other.x,
78 y: self.y - other.y,
79 }
80 }
81
82 pub(crate) fn dot(&self, other: Self) -> S {
83 self.x * other.x + self.y * other.y
84 }
85
86 pub(crate) fn all_component_wise(&self, other: Self, f: impl Fn(S, S) -> bool) -> bool {
87 f(self.x, other.x) && f(self.y, other.y)
88 }
89}
90
91impl<S: SpadeNum> From<Point2<S>> for [S; 2] {
92 #[inline]
93 fn from(point: Point2<S>) -> Self {
94 [point.x, point.y]
95 }
96}
97
98impl<S: SpadeNum> From<Point2<S>> for (S, S) {
99 #[inline]
100 fn from(point: Point2<S>) -> (S, S) {
101 (point.x, point.y)
102 }
103}
104
105impl<S: SpadeNum> From<[S; 2]> for Point2<S> {
106 #[inline]
107 fn from(source: [S; 2]) -> Self {
108 Self::new(source[0], source[1])
109 }
110}
111
112impl<S: SpadeNum> From<(S, S)> for Point2<S> {
113 #[inline]
114 fn from(source: (S, S)) -> Self {
115 Self::new(source.0, source.1)
116 }
117}
118
119pub trait HasPosition {
123 type Scalar: SpadeNum;
125
126 fn position(&self) -> Point2<Self::Scalar>;
132}
133
134impl<S: SpadeNum> HasPosition for Point2<S> {
135 type Scalar = S;
136
137 fn position(&self) -> Point2<S> {
138 *self
139 }
140}