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