1use std::{fmt, ops};
2
3use super::{
4 coordinates::{Uv, Xyz, T},
5 Scalar, Vector,
6};
7
8#[derive(Clone, Copy, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
13#[repr(C)]
14pub struct Point<const D: usize> {
15 pub coords: Vector<D>,
17}
18
19impl<const D: usize> Point<D> {
20 pub fn origin() -> Self {
22 nalgebra::Point::<_, D>::origin().into()
23 }
24
25 pub fn from_array(array: [f64; D]) -> Self {
27 Self {
28 coords: array.map(Scalar::from_f64).into(),
29 }
30 }
31
32 pub fn from_na(point: nalgebra::Point<f64, D>) -> Self {
34 Self {
35 coords: point.coords.into(),
36 }
37 }
38
39 pub fn to_na(self) -> nalgebra::Point<f64, D> {
41 nalgebra::Point {
42 coords: self.coords.into(),
43 }
44 }
45
46 pub fn to_t(self) -> Point<1> {
48 Point {
49 coords: self.coords.to_t(),
50 }
51 }
52
53 pub fn to_xyz(self) -> Point<3> {
57 Point {
58 coords: self.coords.to_xyz(),
59 }
60 }
61
62 pub fn distance_to(&self, other: &Self) -> Scalar {
64 (self.coords - other.coords).magnitude()
65 }
66}
67
68impl ops::Deref for Point<1> {
69 type Target = T;
70
71 fn deref(&self) -> &Self::Target {
72 self.coords.deref()
73 }
74}
75
76impl ops::Deref for Point<2> {
77 type Target = Uv;
78
79 fn deref(&self) -> &Self::Target {
80 self.coords.deref()
81 }
82}
83
84impl ops::Deref for Point<3> {
85 type Target = Xyz;
86
87 fn deref(&self) -> &Self::Target {
88 self.coords.deref()
89 }
90}
91
92impl ops::DerefMut for Point<1> {
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 self.coords.deref_mut()
95 }
96}
97
98impl ops::DerefMut for Point<2> {
99 fn deref_mut(&mut self) -> &mut Self::Target {
100 self.coords.deref_mut()
101 }
102}
103
104impl ops::DerefMut for Point<3> {
105 fn deref_mut(&mut self) -> &mut Self::Target {
106 self.coords.deref_mut()
107 }
108}
109
110impl<const D: usize> From<[Scalar; D]> for Point<D> {
111 fn from(array: [Scalar; D]) -> Self {
112 Self {
113 coords: array.into(),
114 }
115 }
116}
117
118impl<const D: usize> From<[f64; D]> for Point<D> {
119 fn from(array: [f64; D]) -> Self {
120 Self::from_array(array)
121 }
122}
123
124impl<const D: usize> From<nalgebra::Point<f64, D>> for Point<D> {
125 fn from(point: nalgebra::Point<f64, D>) -> Self {
126 Self::from_na(point)
127 }
128}
129
130impl<const D: usize> From<Point<D>> for [f32; D] {
131 fn from(point: Point<D>) -> Self {
132 point.coords.into()
133 }
134}
135
136impl<const D: usize> From<Point<D>> for [f64; D] {
137 fn from(point: Point<D>) -> Self {
138 point.coords.into()
139 }
140}
141
142impl<const D: usize> From<Point<D>> for [Scalar; D] {
143 fn from(point: Point<D>) -> Self {
144 point.coords.into()
145 }
146}
147
148impl<const D: usize> ops::Neg for Point<D> {
149 type Output = Self;
150
151 fn neg(self) -> Self::Output {
152 self.to_na().neg().into()
153 }
154}
155
156impl<V, const D: usize> ops::Add<V> for Point<D>
157where
158 V: Into<Vector<D>>,
159{
160 type Output = Self;
161
162 fn add(self, rhs: V) -> Self::Output {
163 self.to_na().add(rhs.into().to_na()).into()
164 }
165}
166
167impl<V, const D: usize> ops::AddAssign<V> for Point<D>
168where
169 V: Into<Vector<D>>,
170{
171 fn add_assign(&mut self, rhs: V) {
172 *self = *self + rhs;
173 }
174}
175
176impl<V, const D: usize> ops::Sub<V> for Point<D>
177where
178 V: Into<Vector<D>>,
179{
180 type Output = Self;
181
182 fn sub(self, rhs: V) -> Self::Output {
183 self.to_na().sub(rhs.into().to_na()).into()
184 }
185}
186
187impl<const D: usize> ops::Sub<Self> for Point<D> {
188 type Output = Vector<D>;
189
190 fn sub(self, rhs: Self) -> Self::Output {
191 self.to_na().sub(rhs.to_na()).into()
192 }
193}
194
195impl<const D: usize> ops::Sub<Point<D>> for &Point<D> {
196 type Output = Vector<D>;
197
198 fn sub(self, rhs: Point<D>) -> Self::Output {
199 self.to_na().sub(rhs.to_na()).into()
200 }
201}
202
203impl<const D: usize> ops::Mul<f64> for Point<D> {
204 type Output = Self;
205
206 fn mul(self, rhs: f64) -> Self::Output {
207 self.to_na().mul(rhs).into()
208 }
209}
210
211impl<const D: usize> fmt::Debug for Point<D> {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 self.coords.fmt(f)
214 }
215}
216
217impl<const D: usize> approx::AbsDiffEq for Point<D> {
218 type Epsilon = <Vector<D> as approx::AbsDiffEq>::Epsilon;
219
220 fn default_epsilon() -> Self::Epsilon {
221 Scalar::default_epsilon()
222 }
223
224 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
225 self.coords.abs_diff_eq(&other.coords, epsilon)
226 }
227}