1use std::marker::PhantomData;
4
5#[cfg(feature = "derive_serdes")]
6use serde::{Deserialize, Serialize};
7
8use crate::num_traits as num;
9use crate::traits::*;
10use super::*;
11
12macro_rules! impl_dimension {
13 ( $point:ident, $vector:ident, $matrix:ident, $position:ident, $displacement:ident,
14 [$($projective_base:ident, $projective:ident, $translation_column:ident)?],
15 $transform:ident, $cartesian:ident, $ndims:expr, $dimension:expr
16 ) => {
17 #[doc = $dimension]
18 #[doc = "cartesian coordinate space tagged with units"]
19 #[derive(Clone, Copy, Debug)]
20 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
21 #[repr(C)]
22 pub struct $cartesian <S, U> (PhantomData <(S, U)>);
23
24 #[doc = $dimension]
25 #[doc = "linear transformation between two coordinate systems tagged with units"]
26 #[derive(Debug, Default, Eq, Display)]
27 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
28 #[display("{}", _0)]
29 #[repr(C)]
30 pub struct $transform <S, U, V> (pub $matrix <S>, PhantomData <(U, V)>) where
31 S : num::Zero + num::One;
32
33 #[doc = $dimension]
34 #[doc = "point coordinates tagged with unit"]
35 #[derive(Debug, Default, Eq, Display)]
36 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
37 #[display("{}", _0)]
38 #[repr(C)]
39 pub struct $position <S, U> (pub $point <S>, PhantomData <U>);
40
41 #[doc = $dimension]
42 #[doc = "linear displacement vector coordinates tagged with unit"]
43 #[derive(Debug, Default, Eq, Display)]
44 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
45 #[display("{}", _0)]
46 #[repr(C)]
47 pub struct $displacement <S, U> (pub $vector <S>, PhantomData <U>);
48
49 impl <S, U> EuclideanSpace <S> for $cartesian <S, U> where S : Real { }
57 impl <S, U> AffineSpace <S> for $cartesian <S, U> where S : Real {
58 type Point = $position <S, U>;
59 type Vector = $displacement <S, U>;
60 }
61
62 impl <S, U, V> LinearMap <S, $displacement <S, U>, $displacement <S, V>> for
66 $transform <S, U, V>
67 where S : Ring {
68 fn determinant (self) -> S {
69 self.0.determinant()
70 }
71 fn transpose (self) -> Self {
72 $transform (self.0.transpose(), PhantomData::default())
73 }
74 }
75 impl <S, U, V> MultiplicativeMonoid for $transform <S, U, V> where S : Ring { }
76 impl <S, U, V> num::One for $transform <S, U, V> where S : Ring {
77 fn one() -> Self {
78 Self ($matrix::one(), PhantomData::default())
79 }
80 }
81 impl <S, U, V> std::ops::Mul <Self> for $transform <S, U, V> where S : Ring {
82 type Output = Self;
83 fn mul (self, rhs : Self) -> Self {
84 (self.0 * rhs.0).into()
85 }
86 }
87 impl <S, U, V> std::ops::MulAssign <Self> for $transform <S, U, V> where S : Ring {
88 fn mul_assign (&mut self, rhs : Self) {
89 (self.0 *= rhs.0).into()
90 }
91 }
92 impl <S, U, V> std::ops::Mul <$displacement <S, U>> for $transform <S, U, V> where
93 S : Ring
94 {
95 type Output = $displacement <S, V>;
96 fn mul (self, rhs : $displacement <S, U>) -> $displacement <S, V> {
97 (self.0 * rhs.0).into()
98 }
99 }
100 impl <S, U, V> PartialEq for $transform <S, U, V> where
101 S : PartialEq + num::Zero + num::One
102 {
103 fn eq (&self, other : &Self) -> bool {
104 self.0 == other.0
105 }
106 }
107 impl <S, U, V> Copy for $transform <S, U, V> where S : Copy + num::Zero + num::One
108 { }
109 impl <S, U, V> Clone for $transform <S, U, V> where
110 S : Clone + num::Zero + num::One
111 {
112 fn clone (&self) -> Self {
113 self.0.clone().into()
114 }
115 }
116 impl <S, U, V> From <$matrix <S>> for $transform <S, U, V> where
117 S : num::Zero + num::One
118 {
119 fn from (matrix : $matrix <S>) -> Self {
120 $transform (matrix, PhantomData::default())
121 }
122 }
123
124 impl <S, U> Point <$displacement <S, U>> for $displacement <S, U> where S : Ring {
128 fn to_vector (self) -> $displacement <S, U> {
129 self
130 }
131 fn from_vector (displacement : $displacement <S, U>) -> Self {
132 displacement
133 }
134 }
135 impl <S, U> InnerProductSpace <S> for $displacement <S, U> where
136 $vector <S> : InnerProductSpace <S>,
137 S : Field
138 { }
139 impl <S, U> VectorSpace <S> for $displacement <S, U> where
140 $vector <S> : VectorSpace <S>,
141 S : Field
142 {
143 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
144 self.0.map (f).into()
145 }
146 }
147 impl <S, U> Dot <S> for $displacement <S, U> where
148 $vector <S> : Dot <S>,
149 S : Ring
150 {
151 fn dot (self, other : Self) -> S {
152 self.0.dot (other.0)
153 }
154 }
155 impl <S, U> std::ops::Div <S> for $displacement <S, U> where
156 $vector <S> : std::ops::Div <S, Output=$vector <S>>
157 {
158 type Output = Self;
159 fn div (self, scalar : S) -> Self {
160 (self.0 / scalar).into()
161 }
162 }
163 impl <S, U> Module <S> for $displacement <S, U> where
164 $vector <S> : Module <S>,
165 S : Ring
166 {
167 type LinearEndo = $transform <S, U, U>;
168 }
169 impl <S, U> std::ops::Mul <S> for $displacement <S, U> where
170 $vector <S> : std::ops::Mul <S, Output=$vector <S>>
171 {
172 type Output = Self;
173 fn mul (self, scalar : S) -> Self {
174 (self.0 * scalar).into()
175 }
176 }
177 impl <S, U> GroupAction <$position <S, U>> for $displacement <S, U> where
178 S : AdditiveGroup
179 {
180 fn action (self, position : $position <S, U>) -> $position <S, U> {
181 (position.0 + self.0).into()
182 }
183 }
184 impl <S, U> AdditiveGroup for $displacement <S, U> where
185 $vector <S> : AdditiveGroup,
186 S : Ring
187 { }
188 impl <S, U> AdditiveMonoid for $displacement <S, U> where
189 $vector <S> : AdditiveGroup,
190 S : Ring
191 { }
192 impl <S, U> Group for $displacement <S, U> where S : AdditiveGroup {
193 fn identity() -> Self {
194 use num::Zero;
195 Self::zero()
196 }
197 fn operation (a : Self, b : Self) -> Self {
198 a + b
199 }
200 }
201 impl <S, U> std::ops::Add <Self> for $displacement <S, U> where
202 $vector <S> : std::ops::Add <Output=$vector <S>>
203 {
204 type Output = Self;
205 fn add (self, other : Self) -> Self {
206 (self.0 + other.0).into()
207 }
208 }
209 impl <S, U> std::ops::Add <&Self> for $displacement <S, U> where
210 $vector <S> : std::ops::Add <Output=$vector <S>>,
211 S : Copy
212 {
213 type Output = Self;
214 fn add (self, other : &Self) -> Self {
215 (self.0 + other.0).into()
216 }
217 }
218 impl <S, U> std::ops::Sub <Self> for $displacement <S, U> where
219 $vector <S> : std::ops::Sub <Output=$vector <S>>
220 {
221 type Output = Self;
222 fn sub (self, other : Self) -> Self {
223 (self.0 - other.0).into()
224 }
225 }
226 impl <S, U> std::ops::Sub <&Self> for $displacement <S, U> where
227 $vector <S> : std::ops::Sub <Output=$vector <S>>,
228 S : Copy
229 {
230 type Output = Self;
231 fn sub (self, other : &Self) -> Self {
232 (self.0 - other.0).into()
233 }
234 }
235 impl <S, U> std::ops::AddAssign <Self> for $displacement <S, U> where
236 $vector <S> : std::ops::AddAssign
237 {
238 fn add_assign (&mut self, other : Self) {
239 self.0 += other.0
240 }
241 }
242 impl <S, U> std::ops::SubAssign <Self> for $displacement <S, U> where
243 $vector <S> : std::ops::SubAssign
244 {
245 fn sub_assign (&mut self, other : Self) {
246 self.0 -= other.0
247 }
248 }
249 impl <S, U> std::ops::Neg for $displacement <S, U> where
250 $vector <S> : std::ops::Neg <Output=$vector <S>>
251 {
252 type Output = Self;
253 fn neg (self) -> Self {
254 (-self.0).into()
255 }
256 }
257 impl <S, U> num::Zero for $displacement <S, U> where S : AdditiveGroup {
258 fn zero() -> Self {
259 $vector::zero().into()
260 }
261 fn is_zero (&self) -> bool {
262 self.0 == $vector::zero()
263 }
264 }
265 impl <S, U> PartialEq for $displacement <S, U> where $vector <S> : PartialEq {
266 fn eq (&self, other : &Self) -> bool {
267 self.0 == other.0
268 }
269 }
270 impl <S, U> Copy for $displacement <S, U> where S : Copy { }
271 impl <S, U> Clone for $displacement <S, U> where S : Clone {
272 fn clone (&self) -> Self {
273 self.0.clone().into()
274 }
275 }
276 impl <S, U> From <$vector <S>> for $displacement <S, U> {
277 fn from (vector : $vector <S>) -> Self {
278 $displacement (vector, PhantomData::default())
279 }
280 }
281 impl <S, U> From<[S; $ndims]> for $displacement <S, U> {
282 fn from (array : [S; $ndims]) -> Self {
283 $displacement (array.into(), PhantomData::default())
284 }
285 }
286 $(
288 impl <S, U> ProjectiveSpace <S, $displacement <S, U>> for $projective <S, U> where
289 S : Field + std::fmt::Display
290 {
291 fn homography <A> (
292 affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
293 ) -> Projectivity <
294 S, $displacement <S, U>, $displacement <S, U>, Self, Self, Self::LinearEndo
295 > where
296 A : AffineSpace <S, Vector=$displacement <S, U>>
297 {
298 let mut transform = Self::LinearEndo::from (*affinity.linear_iso);
299 transform.0.cols.$translation_column =
300 $projective_base::from ((affinity.translation.0, S::one()));
301 Projectivity::new (
302 LinearIso::<S, Self, Self, Self::LinearEndo>::new (transform).unwrap())
303 }
304 fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>) -> Self where
305 A : AffineSpace <S, Vector=$displacement <S, U>>,
306 $displacement <S, U> : GroupAction <A::Point>
307 {
308 match point_or_vector {
309 Either::Left (point) =>
310 $projective_base::from ((point.to_vector().0, S::one())).into(),
311 Either::Right (vector) =>
312 $projective_base::from ((vector.0, S::zero())).into()
313 }
314 }
315 }
316 )?
317
318 impl <S, U> Point <$displacement <S, U>> for $position <S, U> where S : Ring {
322 fn to_vector (self) -> $displacement <S, U> {
323 self.0.to_vector().into()
324 }
325 fn from_vector (displacement : $displacement <S, U>) -> Self {
326 $point::from_vector (displacement.0).into()
327 }
328 }
329 impl <S, U> std::ops::Sub <Self> for $position <S, U> where
330 $vector <S> : std::ops::Sub <Output=$vector <S>>,
331 S : AdditiveGroup
332 {
333 type Output = $displacement <S, U>;
334 fn sub (self, other : Self) -> $displacement <S, U> {
335 (self.0 - other.0).into()
336 }
337 }
338 impl <S, U> PartialEq for $position <S, U> where $point <S> : PartialEq {
339 fn eq (&self, other : &Self) -> bool {
340 self.0 == other.0
341 }
342 }
343 impl <S, U> Copy for $position <S, U> where S : Copy { }
344 impl <S, U> Clone for $position <S, U> where S : Clone {
345 fn clone (&self) -> Self {
346 self.0.clone().into()
347 }
348 }
349 impl <S, U> From <$point <S>> for $position <S, U> {
350 fn from (point : $point <S>) -> Self {
351 $position (point, PhantomData::default())
352 }
353 }
354 impl <S, U> From<[S; $ndims]> for $position <S, U> {
355 fn from (array : [S; $ndims]) -> Self {
356 $position (array.into(), PhantomData::default())
357 }
358 }
359 }
360}
361
362impl_dimension!(Point2, Vector2, Matrix2, Position2,
363 Displacement2, [Vector3, Displacement3, z], Transform2, Cartesian2, 2, "2D");
364impl_dimension!(Point3, Vector3, Matrix3, Position3,
365 Displacement3, [Vector4, Displacement4, w], Transform3, Cartesian3, 3, "3D");
366impl_dimension!(Point4, Vector4, Matrix4, Position4,
367 Displacement4, [], Transform4, Cartesian4, 4, "4D");
368
369impl <S, U> From <Displacement2 <S, U>> for Displacement3 <S, U> where S : Field {
373 fn from (transform : Displacement2 <S, U>) -> Self {
374 Displacement3 (transform.0.into(), PhantomData)
375 }
376}
377impl <S, U> From <Displacement3 <S, U>> for Displacement4 <S, U> where S : Field {
378 fn from (transform : Displacement3 <S, U>) -> Self {
379 Displacement4 (transform.0.into(), PhantomData)
380 }
381}
382
383impl <S, U, V> From <Transform2 <S, U, V>> for Transform3 <S, U, V> where S : Field {
387 fn from (transform : Transform2 <S, U, V>) -> Self {
388 Transform3 (transform.0.into(), PhantomData)
389 }
390}
391impl <S, U, V> From <Transform3 <S, U, V>> for Transform4 <S, U, V> where S : Field {
392 fn from (transform : Transform3 <S, U, V>) -> Self {
393 Transform4 (transform.0.into(), PhantomData)
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[derive(Default)]
402 struct Foo;
403 #[derive(Default)]
404 struct Bar;
405
406 #[test]
407 fn defaults() {
408 assert_eq!(Position3::<f32, Foo>::default().0, Point3::origin());
409 assert_eq!(Displacement3::<f32, Foo>::default().0, Vector3::zero());
410 assert_eq!(Transform3::<f32, Foo, Bar>::default().0, Matrix3::identity());
411 }
412}