1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3use either::Either;
4
5use crate::approx;
6use crate::num_traits as num;
7
8#[cfg(feature = "derive_serdes")]
9use serde::{Deserialize, Serialize};
10
11use crate::traits::*;
12
13pub mod coordinate;
14
15pub use vek::Vec2 as Vector2;
16pub use vek::Mat2 as Matrix2;
17pub use vek::Vec3 as Vector3;
18pub use vek::Mat3 as Matrix3;
19pub use vek::Vec4 as Vector4;
20pub use vek::Mat4 as Matrix4;
21pub use vek::Quaternion as Quaternion;
22
23pub use self::enums::{Axis2, Axis3, Axis4, Octant, Quadrant, Sign, SignedAxis1,
24 SignedAxis2, SignedAxis3, SignedAxis4};
25
26mod enums {
33 use strum::{EnumCount, EnumIter, FromRepr};
34 #[cfg(feature = "derive_serdes")]
35 use serde::{Deserialize, Serialize};
36
37 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
39 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
40 #[repr(u8)]
41 pub enum Sign {
42 Negative,
43 Zero,
44 Positive
45 }
46
47 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
49 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
50 #[repr(u8)]
51 pub enum Quadrant {
52 PosPos,
54 NegPos,
56 PosNeg,
58 NegNeg
60 }
61
62 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
64 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
65 #[repr(u8)]
66 pub enum Octant {
67 PosPosPos,
69 NegPosPos,
71 PosNegPos,
73 NegNegPos,
75 PosPosNeg,
77 NegPosNeg,
79 PosNegNeg,
81 NegNegNeg
83 }
84
85 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
87 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
88 #[repr(u8)]
89 pub enum Axis2 {
90 X=0,
91 Y
92 }
93
94 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
96 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
97 #[repr(u8)]
98 pub enum Axis3 {
99 X=0,
100 Y,
101 Z
102 }
103
104 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
106 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
107 #[repr(u8)]
108 pub enum Axis4 {
109 X=0,
110 Y,
111 Z,
112 W
113 }
114
115 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
117 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
118 #[repr(u8)]
119 pub enum SignedAxis1 {
120 NegX, PosX
121 }
122
123 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
125 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
126 #[repr(u8)]
127 pub enum SignedAxis2 {
128 NegX, PosX,
129 NegY, PosY
130 }
131
132 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
134 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
135 #[repr(u8)]
136 pub enum SignedAxis3 {
137 NegX, PosX,
138 NegY, PosY,
139 NegZ, PosZ
140 }
141
142 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
144 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
145 #[repr(u8)]
146 pub enum SignedAxis4 {
147 NegX, PosX,
148 NegY, PosY,
149 NegZ, PosZ,
150 NegW, PosW
151 }
152}
153
154#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
160#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
161pub struct Positive <S> (S);
162
163#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
165#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
166pub struct NonNegative <S> (S);
167
168#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
170#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
171pub struct NonZero <S> (S);
172
173#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
175#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
176pub struct Normalized <S> (S);
177
178#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
180#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
181pub struct NormalSigned <S> (S);
182
183#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
189#[derive(Clone, Copy, Debug, Default, PartialEq)]
190pub struct Angles3 <S> {
191 pub yaw : AngleWrapped <S>,
192 pub pitch : AngleWrapped <S>,
193 pub roll : AngleWrapped <S>
194}
195
196#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
198#[derive(Clone, Copy, Debug, Default, PartialEq)]
199pub struct Pose3 <S> {
200 pub position : Point3 <S>,
201 pub angles : Angles3 <S>
202}
203
204#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
206#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
207#[display("{}", _0)]
208pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
209
210#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
212#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
213#[display("{}", _0)]
214pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
215 V : Module <S>,
216 V::LinearEndo : MaybeSerDes,
217 S : Ring;
218
219#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
222#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
223#[derive(Clone, Copy, Debug, Default, PartialEq)]
224pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where
225 S : Ring + MaybeSerDes;
226
227#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
230#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
231#[derive(Clone, Copy, Debug, Default, PartialEq)]
232pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where
233 S : Ring + MaybeSerDes;
234
235#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
237#[derive(Clone, Copy, Debug, Default, PartialEq)]
238pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
239
240#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
243#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
244#[display("({}, {})", linear_map, translation)]
245pub struct AffineMap <S, A, B, M> where
246 B : AffineSpace <S>,
247 S : Field + std::fmt::Display,
248 B::Vector : std::fmt::Display
249{
250 pub linear_map : M,
251 pub translation : B::Vector,
252 pub _phantom : PhantomData <A>
253}
254
255#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
257#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
258#[display("({}, {})", linear_iso, translation)]
259pub struct Affinity <S, A, B, M> where
260 A : AffineSpace <S>,
261 B : AffineSpace <S>,
262 S : Field + std::fmt::Display,
263 B::Vector : std::fmt::Display
264{
265 pub linear_iso : LinearIso <S, A::Vector, B::Vector, M>,
266 pub translation : B::Vector,
267 pub _phantom : PhantomData <A>
268}
269
270#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
273#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
274#[display("{}", _0)]
275pub struct Projectivity <S, V, W, P, Q, M> (
276 pub LinearIso <S, P, Q, M>,
277 pub PhantomData <(V, W)>
278);
279
280impl <S : Real> Angle <S> for Deg <S> {
288 fn full_turn() -> Self {
289 Deg (S::ten() * S::nine() * S::two() * S::two())
290 }
291 fn half_turn() -> Self {
292 Deg (S::ten() * S::nine() * S::two())
293 }
294}
295impl <S : Real> Trig for Deg <S> {
296 fn sin (self) -> Self {
297 Rad::from (self).sin().into()
298 }
299 fn sin_cos (self) -> (Self, Self) {
300 let (sin, cos) = Rad::from (self).sin_cos();
301 (sin.into(), cos.into())
302 }
303 fn cos (self) -> Self {
304 Rad::from (self).cos().into()
305 }
306 fn tan (self) -> Self {
307 Rad::from (self).tan().into()
308 }
309 fn asin (self) -> Self {
310 Rad::from (self).asin().into()
311 }
312 fn acos (self) -> Self {
313 Rad::from (self).acos().into()
314 }
315 fn atan (self) -> Self {
316 Rad::from (self).atan().into()
317 }
318 fn atan2 (self, other : Self) -> Self {
319 Rad::from (self).atan2 (Rad::from (other)).into()
320 }
321}
322impl <S : Real> From <Rad <S>> for Deg <S> {
323 fn from (radians : Rad <S>) -> Self {
324 let full_turns = radians / Rad::full_turn();
325 Deg::full_turn() * full_turns
326 }
327}
328impl <S : Real> From <Turn <S>> for Deg <S> {
329 fn from (turns : Turn <S>) -> Self {
330 Deg (turns.0 * Deg::full_turn().0)
331 }
332}
333
334impl <S : Real> Angle <S> for Rad <S> {
338 fn full_turn() -> Self {
339 Rad (S::pi() * S::two())
340 }
341}
342impl <S : Real> Trig for Rad <S> {
343 fn sin (self) -> Self {
344 Rad (self.0.sin())
345 }
346 fn sin_cos (self) -> (Self, Self) {
347 let (sin, cos) = self.0.sin_cos();
348 (Rad (sin), Rad (cos))
349 }
350 fn cos (self) -> Self {
351 Rad (self.0.cos())
352 }
353 fn tan (self) -> Self {
354 Rad (self.0.tan())
355 }
356 fn asin (self) -> Self {
357 Rad (self.0.asin())
358 }
359 fn acos (self) -> Self {
360 Rad (self.0.acos())
361 }
362 fn atan (self) -> Self {
363 Rad (self.0.atan())
364 }
365 fn atan2 (self, other : Self) -> Self {
366 Rad (self.0.atan2 (other.0))
367 }
368}
369impl <S : Real> From <Deg <S>> for Rad <S> {
370 fn from (degrees : Deg <S>) -> Self {
371 let full_turns = degrees / Deg::full_turn();
372 Rad::full_turn() * full_turns
373 }
374}
375impl <S : Real> From <Turn <S>> for Rad <S> {
376 fn from (turns : Turn <S>) -> Self {
377 Rad (turns.0 * Rad::full_turn().0)
378 }
379}
380
381impl <S : Real> Angle <S> for Turn <S> {
385 fn full_turn() -> Self {
386 Turn (S::one())
387 }
388 fn half_turn() -> Self {
389 Turn (S::half())
390 }
391}
392impl <S : Real> Trig for Turn <S> {
393 fn sin (self) -> Self {
394 Rad::from (self).sin().into()
395 }
396 fn sin_cos (self) -> (Self, Self) {
397 let (sin, cos) = Rad::from (self).sin_cos();
398 (sin.into(), cos.into())
399 }
400 fn cos (self) -> Self {
401 Rad::from (self).cos().into()
402 }
403 fn tan (self) -> Self {
404 Rad::from (self).tan().into()
405 }
406 fn asin (self) -> Self {
407 Rad::from (self).asin().into()
408 }
409 fn acos (self) -> Self {
410 Rad::from (self).acos().into()
411 }
412 fn atan (self) -> Self {
413 Rad::from (self).atan().into()
414 }
415 fn atan2 (self, other : Self) -> Self {
416 Rad::from (self).atan2 (Rad::from (other)).into()
417 }
418}
419impl <S : Real> From <Rad <S>> for Turn <S> {
420 fn from (radians : Rad <S>) -> Self {
421 Turn (radians.0 / Rad::full_turn().0)
422 }
423}
424impl <S : Real> From <Deg <S>> for Turn <S> {
425 fn from (degrees : Deg <S>) -> Self {
426 Turn (degrees.0 / Deg::full_turn().0)
427 }
428}
429
430impl <S : Real> AngleWrapped <S> {
434 pub fn wrap (angle : Rad <S>) -> Self {
435 AngleWrapped (angle.wrap_unsigned())
436 }
437
438 pub fn map <F> (self, f : F) -> Self where
439 F : FnOnce (Rad <S>) -> Rad <S>
440 {
441 AngleWrapped (f (self.0).wrap_unsigned())
442 }
443}
444
445impl <S : Real> AngleWrappedSigned <S> {
449 pub fn wrap (angle : Rad <S>) -> Self {
450 AngleWrappedSigned (angle.wrap_signed())
451 }
452
453 pub fn map <F> (self, f : F) -> Self where
454 F : FnOnce (Rad <S>) -> Rad <S>
455 {
456 AngleWrappedSigned (f (self.0).wrap_signed())
457 }
458}
459
460impl <S : Real> Angles3 <S> {
465 pub const fn new (
466 yaw : AngleWrapped <S>,
467 pitch : AngleWrapped <S>,
468 roll : AngleWrapped <S>
469 ) -> Self {
470 Angles3 { yaw, pitch, roll }
471 }
472
473 pub fn zero() -> Self {
474 use num::Zero;
475 Angles3::new (
476 AngleWrapped::zero(),
477 AngleWrapped::zero(),
478 AngleWrapped::zero())
479 }
480
481 pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
482 let yaw = AngleWrapped::wrap (yaw);
483 let pitch = AngleWrapped::wrap (pitch);
484 let roll = AngleWrapped::wrap (roll);
485 Angles3 { yaw, pitch, roll }
486 }
487}
488
489impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
490 fn from (rotation : Rotation3 <S>) -> Self {
491 let (yaw, pitch, roll) = {
492 let (yaw, pitch, roll) = rotation.intrinsic_angles();
493 ( AngleWrapped::wrap (yaw),
494 AngleWrapped::wrap (pitch),
495 AngleWrapped::wrap (roll)
496 )
497 };
498 Angles3 { yaw, pitch, roll }
499 }
500}
501
502impl Axis2 {
506 #[inline]
507 pub fn component (self) -> usize {
508 self as usize
509 }
510}
511
512impl Axis3 {
516 #[inline]
517 pub fn component (self) -> usize {
518 self as usize
519 }
520}
521
522impl SignedAxis3 {
526 pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
527 if *vector == [ S::one(), S::zero(), S::zero()].into() {
528 Some (SignedAxis3::PosX)
529 } else if *vector == [-S::one(), S::zero(), S::zero()].into() {
530 Some (SignedAxis3::NegX)
531 } else if *vector == [ S::zero(), S::one(), S::zero()].into() {
532 Some (SignedAxis3::PosY)
533 } else if *vector == [ S::zero(), -S::one(), S::zero()].into() {
534 Some (SignedAxis3::NegY)
535 } else if *vector == [ S::zero(), S::zero(), S::one() ].into() {
536 Some (SignedAxis3::PosZ)
537 } else if *vector == [ S::zero(), S::zero(), -S::one() ].into() {
538 Some (SignedAxis3::NegZ)
539 } else {
540 None
541 }
542 }
543
544 pub fn to_vec <S : Field> (self) -> Vector3 <S> {
545 match self {
546 SignedAxis3::NegX => [-S::one(), S::zero(), S::zero()].into(),
547 SignedAxis3::PosX => [ S::one(), S::zero(), S::zero()].into(),
548 SignedAxis3::NegY => [ S::zero(), -S::one(), S::zero()].into(),
549 SignedAxis3::PosY => [ S::zero(), S::one(), S::zero()].into(),
550 SignedAxis3::NegZ => [ S::zero(), S::zero(), -S::one() ].into(),
551 SignedAxis3::PosZ => [ S::zero(), S::zero(), S::one() ].into()
552 }
553 }
554 #[inline]
555 pub fn to_unit <S> (self) -> Unit3 <S> where S : Real + std::fmt::Debug {
556 Unit3::unchecked (self.to_vec())
557 }
558}
559
560impl Quadrant {
564 pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
567 S : Ring + SignedExt
568 {
569 let sign_x = vector.x.sign();
570 let sign_y = vector.y.sign();
571 let quadrant = match (sign_x, sign_y) {
572 (Sign::Zero, _) |
573 ( _, Sign::Zero) => return None,
574 (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
575 (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
576 (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
577 (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
578 };
579 Some (quadrant)
580 }
581 #[inline]
583 pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
584 S : Ring + SignedExt
585 {
586 Quadrant::from_vec_strict (&point.to_vector())
587 }
588}
589impl Octant {
595 pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
598 S : Ring + SignedExt
599 {
600 let sign_x = vector.x.sign();
601 let sign_y = vector.y.sign();
602 let sign_z = vector.z.sign();
603 let octant = match (sign_x, sign_y, sign_z) {
604 (Sign::Zero, _, _) |
605 ( _, Sign::Zero, _) |
606 ( _, _, Sign::Zero) => return None,
607 (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
608 (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
609 (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
610 (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
611 (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
612 (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
613 (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
614 (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
615 };
616 Some (octant)
617 }
618 #[inline]
620 pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
621 S : Ring + SignedExt
622 {
623 Octant::from_vec_strict (&point.to_vector())
624 }
625}
626impl <S : Ring> Positive <S> {
632 pub fn new (value : S) -> Option <Self> {
643 if value > S::zero() {
644 Some (Positive (value))
645 } else {
646 None
647 }
648 }
649 pub fn infinity() -> Self where S : num::float::FloatCore {
651 Positive (S::infinity())
652 }
653 pub fn noisy (value : S) -> Self {
662 assert!(value > S::zero());
663 Positive (value)
664 }
665 pub fn unchecked (value : S) -> Self {
675 debug_assert!(value > S::zero());
676 Positive (value)
677 }
678 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
699 Self::noisy (fun (self.0))
700 }
701}
702impl <S : Field> num::One for Positive <S> {
703 fn one() -> Self {
704 Positive (S::one())
705 }
706}
707impl <S : Ring> std::ops::Deref for Positive <S> {
708 type Target = S;
709 fn deref (&self) -> &S {
710 &self.0
711 }
712}
713impl <S : Ring> std::ops::Mul for Positive <S> {
714 type Output = Self;
715 fn mul (self, rhs : Self) -> Self::Output {
716 Positive (self.0 * rhs.0)
717 }
718}
719impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
720 type Output = NonNegative <S>;
721 fn mul (self, rhs : NonNegative <S>) -> Self::Output {
722 NonNegative (self.0 * *rhs)
723 }
724}
725impl <S : Field> std::ops::Div for Positive <S> {
726 type Output = Self;
727 fn div (self, rhs : Self) -> Self::Output {
728 Positive (self.0 / rhs.0)
729 }
730}
731impl <S : Ring> std::ops::Add for Positive <S> {
732 type Output = Self;
733 fn add (self, rhs : Self) -> Self::Output {
734 Positive (self.0 + rhs.0)
735 }
736}
737impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
738 type Output = Self;
739 fn add (self, rhs : NonNegative <S>) -> Self::Output {
740 Positive (self.0 + rhs.0)
741 }
742}
743impl <S : Ring> NonNegative <S> {
749 pub fn new (value : S) -> Option <Self> {
760 if value >= S::zero() {
761 Some (NonNegative (value))
762 } else {
763 None
764 }
765 }
766 pub fn abs (value : S) -> Self {
776 NonNegative (value.abs())
777 }
778 pub fn noisy (value : S) -> Self {
787 assert!(S::zero() <= value);
788 NonNegative (value)
789 }
790 pub fn unchecked (value : S) -> Self {
800 debug_assert!(value >= S::zero());
801 NonNegative (value)
802 }
803 pub fn map_abs (self, fun : fn (S) -> S) -> Self {
813 Self::abs (fun (self.0))
814 }
815 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
834 Self::noisy (fun (self.0))
835 }
836}
837impl <S : Ring> From <Positive <S>> for NonNegative <S> {
838 fn from (positive : Positive <S>) -> Self {
839 NonNegative (*positive)
840 }
841}
842impl <S : Ring> num::Zero for NonNegative <S> {
843 fn zero() -> Self {
844 NonNegative (S::zero())
845 }
846 fn is_zero (&self) -> bool {
847 self.0.is_zero()
848 }
849}
850impl <S : Field> num::One for NonNegative <S> {
851 fn one() -> Self {
852 NonNegative (S::one())
853 }
854}
855impl <S : Ring> std::ops::Deref for NonNegative <S> {
856 type Target = S;
857 fn deref (&self) -> &S {
858 &self.0
859 }
860}
861impl <S : Ring> std::ops::Mul for NonNegative <S> {
862 type Output = Self;
863 fn mul (self, rhs : Self) -> Self::Output {
864 NonNegative (self.0 * rhs.0)
865 }
866}
867impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
868 type Output = Self;
869 fn mul (self, rhs : Positive <S>) -> Self::Output {
870 NonNegative (self.0 * rhs.0)
871 }
872}
873impl <S : Field> std::ops::Div for NonNegative <S> {
874 type Output = Self;
875 fn div (self, rhs : Self) -> Self::Output {
876 NonNegative (self.0 / rhs.0)
877 }
878}
879impl <S : Ring> std::ops::Add for NonNegative <S> {
880 type Output = Self;
881 fn add (self, rhs : Self) -> Self::Output {
882 NonNegative (self.0 + rhs.0)
883 }
884}
885impl <S : Field> NonZero <S> {
891 #[inline]
902 pub fn new (value : S) -> Option <Self> {
903 if S::zero() != value {
904 Some (NonZero (value))
905 } else {
906 None
907 }
908 }
909 #[inline]
918 pub fn noisy (value : S) -> Self {
919 assert!(S::zero() != value);
920 NonZero (value)
921 }
922 #[inline]
943 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
944 Self::noisy (fun (self.0))
945 }
946}
947impl <S : Field> num::One for NonZero <S> {
948 fn one() -> Self {
949 NonZero (S::one())
950 }
951}
952impl <S : Field> std::ops::Deref for NonZero <S> {
953 type Target = S;
954 fn deref (&self) -> &S {
955 &self.0
956 }
957}
958impl <S : Field> std::ops::Mul for NonZero <S> {
959 type Output = Self;
960 fn mul (self, rhs : Self) -> Self::Output {
961 NonZero (self.0 * rhs.0)
962 }
963}
964impl <S : Field> Eq for NonZero <S> { }
965impl <S : Field> Normalized <S> {
971 #[inline]
973 pub fn zero() -> Self {
974 Normalized (S::zero())
975 }
976 #[inline]
977 pub fn is_zero (&self) -> bool {
978 self.0.is_zero()
979 }
980 #[inline]
994 pub fn new (value : S) -> Option <Self> {
995 if S::zero() <= value && value <= S::one() {
996 Some (Normalized (value))
997 } else {
998 None
999 }
1000 }
1001 #[inline]
1011 pub fn clamp (value : S) -> Self {
1012 let value = S::max (S::zero(), S::min (value, S::one()));
1013 Normalized (value)
1014 }
1015 #[inline]
1029 pub fn noisy (value : S) -> Self {
1030 assert!(value <= S::one());
1031 assert!(S::zero() <= value);
1032 Normalized (value)
1033 }
1034 #[inline]
1046 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1047 Self::clamp (fun (self.0))
1048 }
1049 #[inline]
1076 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1077 Self::noisy (fun (self.0))
1078 }
1079}
1080impl <S : Field> num::One for Normalized <S> {
1081 fn one() -> Self {
1082 Normalized (S::one())
1083 }
1084}
1085impl <S : Field> std::ops::Deref for Normalized <S> {
1086 type Target = S;
1087 fn deref (&self) -> &S {
1088 &self.0
1089 }
1090}
1091impl <S : Field> std::ops::Mul for Normalized <S> {
1092 type Output = Self;
1093 fn mul (self, rhs : Self) -> Self::Output {
1094 Normalized (self.0 * rhs.0)
1095 }
1096}
1097impl <S : Field> Eq for Normalized <S> { }
1098#[allow(clippy::derive_ord_xor_partial_ord)]
1099impl <S : Field> Ord for Normalized <S> {
1100 fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1101 self.partial_cmp (rhs).unwrap()
1103 }
1104}
1105impl <S : Field> NormalSigned <S> {
1111 #[inline]
1113 pub fn zero() -> Self {
1114 NormalSigned (S::zero())
1115 }
1116 #[inline]
1117 pub fn is_zero (&self) -> bool {
1118 self.0.is_zero()
1119 }
1120 #[inline]
1135 pub fn new (value : S) -> Option <Self> {
1136 if -S::one() <= value && value <= S::one() {
1137 Some (NormalSigned (value))
1138 } else {
1139 None
1140 }
1141 }
1142 #[inline]
1152 pub fn clamp (value : S) -> Self {
1153 let value = S::max (-S::one(), S::min (value, S::one()));
1154 NormalSigned (value)
1155 }
1156 #[inline]
1170 pub fn noisy (value : S) -> Self {
1171 assert!(value <= S::one());
1172 assert!(-S::one() <= value);
1173 NormalSigned (value)
1174 }
1175 #[inline]
1187 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1188 Self::clamp (fun (self.0))
1189 }
1190 #[inline]
1217 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1218 Self::noisy (fun (self.0))
1219 }
1220}
1221impl <S : Field> From <Normalized <S>> for NormalSigned <S> {
1222 fn from (Normalized (value) : Normalized <S>) -> Self {
1223 debug_assert!(S::zero() <= value);
1224 debug_assert!(value <= S::one());
1225 NormalSigned (value)
1226 }
1227}
1228impl <S : Field> num::One for NormalSigned <S> {
1229 fn one() -> Self {
1230 NormalSigned (S::one())
1231 }
1232}
1233impl <S : Field> std::ops::Deref for NormalSigned <S> {
1234 type Target = S;
1235 fn deref (&self) -> &S {
1236 &self.0
1237 }
1238}
1239impl <S : Field> std::ops::Mul for NormalSigned <S> {
1240 type Output = Self;
1241 fn mul (self, rhs : Self) -> Self::Output {
1242 NormalSigned (self.0 * rhs.0)
1243 }
1244}
1245impl <S : Field> Eq for NormalSigned <S> { }
1246#[allow(clippy::derive_ord_xor_partial_ord)]
1247impl <S : Field> Ord for NormalSigned <S> {
1248 fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1249 self.partial_cmp (rhs).unwrap()
1251 }
1252}
1253impl <S : Field> std::ops::Neg for NormalSigned <S> {
1254 type Output = Self;
1255 fn neg (self) -> Self::Output {
1256 NormalSigned (-self.0)
1257 }
1258}
1259impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1265 pub fn identity() -> Self {
1267 use num::One;
1268 Self::one()
1269 }
1270 pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1276 let transform = LinearAuto (LinearIso::new (mat)?);
1277 if !transform.is_rotation() {
1278 None
1279 } else {
1280 Some (Rotation2 (transform))
1281 }
1282 }
1283 pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1289 S : approx::RelativeEq <Epsilon=S>
1290 {
1291 let four = S::one() + S::one() + S::one() + S::one();
1292 let epsilon = S::default_epsilon() * four;
1293 let max_relative = S::default_max_relative() * four;
1294 if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1295 max_relative=max_relative, epsilon=epsilon
1296 ) || approx::relative_ne!(mat.determinant(), S::one(),
1297 max_relative=max_relative
1298 ) {
1299 None
1300 } else {
1301 Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData))))
1302 }
1303 }
1304 pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1306 Rotation2 (LinearAuto (LinearIso (
1307 Matrix2::rotation_z (angle.0), PhantomData)))
1308 }
1309 pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1314 assert_eq!(mat * mat.transposed(), Matrix2::identity());
1315 assert_eq!(mat.determinant(), S::one());
1316 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1317 }
1318 pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1323 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1324 {
1325 let four = S::one() + S::one() + S::one() + S::one();
1326 let epsilon = S::default_epsilon() * four;
1327 let max_relative = S::default_max_relative() * four;
1328 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1329 epsilon=epsilon, max_relative=max_relative);
1330 approx::assert_relative_eq!(mat.determinant(), S::one(),
1331 max_relative=max_relative);
1332 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1333 }
1334 pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1340 debug_assert!(mat * mat.transposed() == Matrix2::identity());
1341 debug_assert!(mat.determinant() == S::one());
1342 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1343 }
1344 pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1350 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1351 {
1352 if cfg!(debug_assertions) {
1353 let four = S::one() + S::one() + S::one() + S::one();
1354 let epsilon = S::default_epsilon() * four;
1355 let max_relative = S::default_max_relative() * four;
1356 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1357 max_relative=max_relative, epsilon=epsilon);
1358 approx::assert_relative_eq!(mat.determinant(), S::one(),
1359 max_relative=max_relative);
1360 }
1361 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1362 }
1363 pub fn rotate (self, point : Point2 <S>) -> Point2 <S> {
1365 Point2::from (self * point.0)
1366 }
1367}
1368impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1369 type Target = Matrix2 <S>;
1370 fn deref (&self) -> &Self::Target {
1371 &self.0
1372 }
1373}
1374impl <S> MultiplicativeGroup for Rotation2 <S> where
1375 S : Ring + MaybeSerDes
1376{ }
1377impl <S> MultiplicativeMonoid for Rotation2 <S> where
1378 S : Ring + MaybeSerDes
1379{ }
1380impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1381 type Output = Self;
1382 fn inv (self) -> Self::Output {
1383 Rotation2 (LinearAuto (LinearIso (
1384 self.0.0.0.transpose(), PhantomData
1385 )))
1386 }
1387}
1388impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where
1389 S : Ring + MaybeSerDes
1390{
1391 type Output = Vector2 <S>;
1392 fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1393 self.0 * rhs
1394 }
1395}
1396impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where
1397 S : Ring + MaybeSerDes
1398{
1399 type Output = Vector2 <S>;
1400 fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1401 self * rhs.0
1402 }
1403}
1404impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1405 type Output = Self;
1406 fn mul (self, rhs : Self) -> Self::Output {
1407 Rotation2 (self.0 * rhs.0)
1408 }
1409}
1410impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where
1411 S : Ring + MaybeSerDes
1412{
1413 fn mul_assign (&mut self, rhs : Self) {
1414 self.0 *= rhs.0
1415 }
1416}
1417impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1418 type Output = Self;
1419 #[allow(clippy::suspicious_arithmetic_impl)]
1420 fn div (self, rhs : Self) -> Self::Output {
1421 use num::Inv;
1422 self * rhs.inv()
1423 }
1424}
1425impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where
1426 S : Ring + MaybeSerDes
1427{
1428 #[allow(clippy::suspicious_op_assign_impl)]
1429 fn div_assign (&mut self, rhs : Self) {
1430 use num::Inv;
1431 *self *= rhs.inv()
1432 }
1433}
1434impl <S> num::One for Rotation2 <S> where
1435 S : Ring + MaybeSerDes + num::Zero + num::One
1436{
1437 fn one() -> Self {
1438 Rotation2 (LinearAuto (
1439 LinearIso (Matrix2::identity(), PhantomData)))
1440 }
1441}
1442
1443impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1447 pub fn identity() -> Self {
1449 use num::One;
1450 Self::one()
1451 }
1452 pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1456 Rotation3 (LinearAuto (LinearIso (
1457 Matrix3::rotation_x (angle.0), PhantomData)))
1458 }
1459 pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1463 Rotation3 (LinearAuto (LinearIso (
1464 Matrix3::rotation_y (angle.0), PhantomData)))
1465 }
1466 pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1470 Rotation3 (LinearAuto (LinearIso (
1471 Matrix3::rotation_z (angle.0), PhantomData)))
1472 }
1473 pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1479 -> Self where S : num::real::Real
1480 {
1481 let rotation1 = Rotation3::from_angle_z (yaw);
1482 let rotation2 =
1483 Rotation3::from_axis_angle (rotation1.cols.x, pitch) * rotation1;
1484 Rotation3::from_axis_angle (rotation2.cols.y, roll) * rotation2
1485 }
1486 pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1488 S : num::real::Real
1489 {
1490 Rotation3 (LinearAuto (LinearIso (
1491 Matrix3::rotation_3d (angle.0, axis), PhantomData)))
1492 }
1493 pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1496 -> Option <Self> where S : Field + Sqrt
1497 {
1498 if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array))
1499 .determinant() == S::zero()
1500 {
1501 None
1502 } else {
1503 let project =
1504 |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1505 let u1 = v1;
1506 let u2 = v2 - project (u1, v2);
1507 let u3 = v3 - project (u1, v3) - project (u2, v3);
1508 Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1509 u1.normalize().into_array(),
1510 u2.normalize().into_array(),
1511 u3.normalize().into_array()
1512 ]), PhantomData))))
1513 }
1514 }
1515
1516 pub fn look_at (point : Point3 <S>) -> Self where
1520 S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> +
1521 std::fmt::Debug
1522 {
1523 if point == Point::origin() {
1524 Self::identity()
1525 } else {
1526 use num::Zero;
1527 let forward = point.0.normalized();
1528 let right = {
1529 let projected = forward.with_z (S::zero());
1530 if !projected.is_zero() {
1531 Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1532 } else {
1533 Vector3::unit_x()
1534 }
1535 };
1536 let up = right.cross (forward);
1537 let mat = Matrix3::from_col_arrays (
1538 [right, forward, up].map (Vector3::into_array));
1539 Self::noisy_approx (mat)
1540 }
1541 }
1542
1543 pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1549 if mat * mat.transposed() != Matrix3::identity() ||
1550 mat.determinant() != S::one()
1551 {
1552 None
1553 } else {
1554 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1555 }
1556 }
1557 pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1563 S : approx::RelativeEq <Epsilon=S>
1564 {
1565 let four = S::one() + S::one() + S::one() + S::one();
1566 let epsilon = S::default_epsilon() * four;
1567 let max_relative = S::default_max_relative() * four;
1568 if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1569 max_relative=max_relative, epsilon=epsilon
1570 ) || approx::relative_ne!(mat.determinant(), S::one(),
1571 max_relative=max_relative
1572 ) {
1573 None
1574 } else {
1575 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1576 }
1577 }
1578 pub fn noisy (mat : Matrix3 <S>) -> Self {
1583 assert!(mat * mat.transposed() == Matrix3::identity());
1584 assert!(mat.determinant() == S::one());
1585 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1586 }
1587 pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1592 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1593 {
1594 let four = S::one() + S::one() + S::one() + S::one();
1595 let eight = four + S::one() + S::one() + S::one() + S::one();
1596 let epsilon = S::default_epsilon() * four;
1597 let max_relative = S::default_max_relative() * eight;
1598 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1599 max_relative=max_relative, epsilon=epsilon);
1600 approx::assert_relative_eq!(mat.determinant(), S::one(),
1601 max_relative=max_relative);
1602 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1603 }
1604 pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1610 debug_assert!(mat * mat.transposed() == Matrix3::identity());
1611 debug_assert!(mat.determinant() == S::one());
1612 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1613 }
1614 pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1620 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1621 {
1622 if cfg!(debug_assertions) {
1623 let four = S::one() + S::one() + S::one() + S::one();
1624 let epsilon = S::default_epsilon() * four;
1625 let max_relative = S::default_max_relative() * four;
1626 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1627 max_relative=max_relative, epsilon=epsilon);
1628 approx::assert_relative_eq!(mat.determinant(), S::one(),
1629 max_relative=max_relative);
1630 }
1631 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1632 }
1633 pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1639 let cols = &self.cols;
1640 let yaw = Rad (S::atan2 (-cols.y.x, cols.y.y));
1641 let pitch = Rad (
1642 S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z))
1643 );
1644 let roll = Rad (S::atan2 (-cols.x.z, cols.z.z));
1645
1646 (yaw, pitch, roll)
1647 }
1648
1649 pub fn versor (self) -> Versor <S> where
1653 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1654 {
1655 let diagonal = self.diagonal();
1656 let t = diagonal.sum();
1657 let m = MinMax::max (MinMax::max (MinMax::max (
1658 diagonal.x, diagonal.y), diagonal.z), t);
1659 let qmax = S::half() * Sqrt::sqrt (S::one() - t + S::two() * m);
1660 let qmax4_recip = (S::four() * qmax).recip();
1661 let [qx, qy, qz, qw] : [S; 4];
1662 let cols = self.cols;
1663 if m == diagonal.x {
1664 qx = qmax;
1665 qy = qmax4_recip * (cols.x.y + cols.y.x);
1666 qz = qmax4_recip * (cols.x.z + cols.z.x);
1667 qw = -qmax4_recip * (cols.z.y - cols.y.z);
1668 } else if m == diagonal.y {
1669 qx = qmax4_recip * (cols.x.y + cols.y.x);
1670 qy = qmax;
1671 qz = qmax4_recip * (cols.y.z + cols.z.y);
1672 qw = -qmax4_recip * (cols.x.z - cols.z.x);
1673 } else if m == diagonal.z {
1674 qx = qmax4_recip * (cols.x.z + cols.z.x);
1675 qy = qmax4_recip * (cols.y.z + cols.z.y);
1676 qz = qmax;
1677 qw = -qmax4_recip * (cols.y.x - cols.x.y);
1678 } else {
1679 qx = -qmax4_recip * (cols.z.y - cols.y.z);
1680 qy = -qmax4_recip * (cols.x.z - cols.z.x);
1681 qz = -qmax4_recip * (cols.y.x - cols.x.y);
1682 qw = qmax;
1683 }
1684 let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1685 Versor::unchecked_approx (quat)
1686 }
1687 pub fn rotate (self, point : Point3 <S>) -> Point3 <S> {
1689 Point3::from (self * point.0)
1690 }
1691}
1692impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1693 type Target = Matrix3 <S>;
1694 fn deref (&self) -> &Self::Target {
1695 &self.0
1696 }
1697}
1698impl <S> MultiplicativeGroup for Rotation3 <S> where S : Ring + MaybeSerDes { }
1699impl <S> MultiplicativeMonoid for Rotation3 <S> where S : Ring + MaybeSerDes { }
1700impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1701 type Output = Self;
1702 fn inv (self) -> Self::Output {
1703 Rotation3 (LinearAuto (LinearIso (
1704 self.0.0.0.transpose(), PhantomData
1705 )))
1706 }
1707}
1708impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where
1709 S : Ring + MaybeSerDes
1710{
1711 type Output = Vector3 <S>;
1712 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1713 self.0 * rhs
1714 }
1715}
1716impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where
1717 S : Ring + MaybeSerDes
1718{
1719 type Output = Vector3 <S>;
1720 fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1721 self * rhs.0
1722 }
1723}
1724impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1725 type Output = Self;
1726 fn mul (self, rhs : Self) -> Self::Output {
1727 Rotation3 (self.0 * rhs.0)
1728 }
1729}
1730impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where
1731 S : Ring + MaybeSerDes
1732{
1733 fn mul_assign (&mut self, rhs : Self) {
1734 self.0 *= rhs.0
1735 }
1736}
1737impl <S> std::ops::Div for Rotation3 <S> where S : Ring + MaybeSerDes {
1738 type Output = Self;
1739 #[allow(clippy::suspicious_arithmetic_impl)]
1740 fn div (self, rhs : Self) -> Self::Output {
1741 use num::Inv;
1742 self * rhs.inv()
1743 }
1744}
1745impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where
1746 S : Ring + MaybeSerDes
1747{
1748 #[allow(clippy::suspicious_op_assign_impl)]
1749 fn div_assign (&mut self, rhs : Self) {
1750 use num::Inv;
1751 *self *= rhs.inv()
1752 }
1753}
1754impl <S> num::One for Rotation3 <S> where
1755 S : Ring + MaybeSerDes + num::Zero + num::One
1756{
1757 fn one() -> Self {
1758 Rotation3 (LinearAuto (
1759 LinearIso (Matrix3::identity(), PhantomData)))
1760 }
1761}
1762impl <S> From <Angles3 <S>> for Rotation3 <S> where
1763 S : Real + MaybeSerDes + num::real::Real
1764{
1765 fn from (angles : Angles3 <S>) -> Self {
1766 Rotation3::from_angles_intrinsic (
1767 angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1768 }
1769}
1770
1771
1772impl <S : Real> Versor <S> {
1776 pub fn normalize (quaternion : Quaternion <S>) -> Self where
1780 S : std::fmt::Debug
1781 {
1782 assert_ne!(quaternion, Quaternion::zero());
1783 Versor (normalize_quaternion (quaternion))
1784 }
1785 pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
1789 S : std::fmt::Debug
1790 {
1791 assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1792 Versor (unit_quaternion)
1793 }
1794 pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1798 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1799 {
1800 assert!(unit_quaternion.into_vec4().is_normalized());
1801 Versor (unit_quaternion)
1802 }
1803 pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where
1807 S : std::fmt::Debug
1808 {
1809 debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1810 Versor (unit_quaternion)
1811 }
1812 pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1816 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1817 {
1818 debug_assert!(unit_quaternion.into_vec4().is_normalized());
1819 Versor (unit_quaternion)
1820 }
1821 pub fn from_scaled_axis (scaled_axis : &Vector3 <S>) -> Self where
1825 S : std::fmt::Debug + num::Float
1826 {
1827 if *scaled_axis == Vector3::zero() {
1828 let versor = Quaternion::rotation_3d (S::zero(), *scaled_axis);
1829 debug_assert_eq!(versor.magnitude(), S::one());
1830 Versor (versor)
1831 } else {
1832 let angle = scaled_axis.magnitude();
1833 debug_assert!(S::zero() < angle);
1834 let axis = *scaled_axis / angle;
1835 Versor (Quaternion::rotation_3d (angle, axis))
1836 }
1837 }
1838}
1839impl <S> From <Rotation3 <S>> for Versor <S> where
1840 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1841{
1842 fn from (rot : Rotation3 <S>) -> Self {
1843 rot.versor()
1844 }
1845}
1846impl <S : Real> std::ops::Deref for Versor <S> {
1847 type Target = Quaternion <S>;
1848 fn deref (&self) -> &Quaternion <S> {
1849 &self.0
1850 }
1851}
1852impl <S, A, B, M> AffineMap <S, A, B, M> where
1858 A : AffineSpace <S>,
1859 B : AffineSpace <S>,
1860 M : LinearMap <S, A::Vector, B::Vector>,
1861 S : Field + std::fmt::Display,
1862 B::Vector : std::fmt::Display
1863{
1864 pub fn new (linear_map : M, translation : B::Vector) -> Self {
1865 AffineMap { linear_map, translation, _phantom: PhantomData }
1866 }
1867 pub fn transform (self, point : A::Point) -> B::Point {
1868 B::Point::from_vector (
1869 self.linear_map * point.to_vector() + self.translation)
1870 }
1871}
1872
1873impl <S, V, W, M> LinearIso <S, V, W, M> where
1877 M : LinearMap <S, V, W> + Copy,
1878 V : Module <S>,
1879 W : Module <S>,
1880 S : Ring
1881{
1882 pub fn is_invertible (linear_map : M) -> bool {
1884 linear_map.determinant() != S::zero()
1885 }
1886 pub fn is_invertible_approx (linear_map : M) -> bool where
1888 S : approx::RelativeEq <Epsilon=S>
1889 {
1890 let four = S::one() + S::one() + S::one() + S::one();
1891 let epsilon = S::default_epsilon() * four;
1892 let max_relative = S::default_max_relative() * four;
1893 approx::relative_ne!(linear_map.determinant(), S::zero(),
1894 max_relative=max_relative, epsilon=epsilon)
1895 }
1896 pub fn new (linear_map : M) -> Option <Self> {
1898 if Self::is_invertible (linear_map) {
1899 Some (LinearIso (linear_map, PhantomData))
1900 } else {
1901 None
1902 }
1903 }
1904 pub fn new_approx (linear_map : M) -> Option <Self> where
1906 S : approx::RelativeEq <Epsilon=S>
1907 {
1908 if Self::is_invertible_approx (linear_map) {
1909 Some (LinearIso (linear_map, PhantomData))
1910 } else {
1911 None
1912 }
1913 }
1914}
1915impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1916 M : LinearMap <S, V, W>,
1917 V : Module <S>,
1918 W : Module <S>,
1919 S : Ring
1920{
1921 type Target = M;
1922 fn deref (&self) -> &Self::Target {
1923 &self.0
1924 }
1925}
1926impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1927 V : Module <S>,
1928 S : Ring
1929{
1930 fn one () -> Self {
1931 LinearIso (V::LinearEndo::one(), PhantomData)
1932 }
1933}
1934impl <S, V, W, M> std::ops::Mul <V> for LinearIso <S, V, W, M> where
1935 M : LinearMap <S, V, W>,
1936 V : Module <S>,
1937 W : Module <S>,
1938 S : Ring
1939{
1940 type Output = W;
1941 fn mul (self, rhs : V) -> Self::Output {
1942 self.0 * rhs
1943 }
1944}
1945impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1946 V : Module <S>,
1947 S : Ring
1948{
1949 type Output = Self;
1950 fn mul (self, rhs : Self) -> Self::Output {
1951 LinearIso (self.0 * rhs.0, PhantomData)
1952 }
1953}
1954impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1955 V : Module <S>,
1956 S : Ring
1957{
1958 fn mul_assign (&mut self, rhs : Self) {
1959 self.0 *= rhs.0
1960 }
1961}
1962
1963impl <S, V> LinearAuto <S, V> where
1967 V : Module <S>,
1968 V::LinearEndo : MaybeSerDes,
1969 S : Ring
1970{
1971 pub fn is_orthonormal (&self) -> bool {
1977 use num::One;
1978 let determinant = self.0.0.determinant();
1979 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1980 (determinant == S::one() || determinant == -S::one())
1981 }
1982 pub fn is_orthonormal_approx (&self) -> bool where
1988 S : approx::RelativeEq <Epsilon=S>,
1989 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1990 {
1991 use num::One;
1992 let four = S::one() + S::one() + S::one() + S::one();
1993 let epsilon = S::default_epsilon() * four;
1994 let max_relative = S::default_max_relative() * four;
1995 let determinant = self.0.0.determinant();
1996 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1997 max_relative=max_relative, epsilon=epsilon) &&
1998 ( approx::relative_eq!(determinant, S::one(), max_relative=max_relative) ||
1999 approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
2000 }
2001 pub fn is_rotation (&self) -> bool {
2006 use num::One;
2007 let determinant = self.0.0.determinant();
2008 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
2009 determinant == S::one()
2010 }
2011 pub fn is_rotation_approx (&self) -> bool where
2016 S : approx::RelativeEq <Epsilon=S>,
2017 V::LinearEndo : approx::RelativeEq <Epsilon=S>
2018 {
2019 use num::One;
2020 let four = S::one() + S::one() + S::one() + S::one();
2021 let epsilon = S::default_epsilon() * four;
2022 let max_relative = S::default_max_relative() * four;
2023 let determinant = self.0.0.determinant();
2024 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
2025 max_relative=max_relative, epsilon=epsilon) &&
2026 approx::relative_eq!(determinant, S::one(), max_relative=max_relative)
2027 }
2028}
2029impl <S, V> MultiplicativeMonoid for LinearAuto <S, V> where
2030 V : Module <S>,
2031 V::LinearEndo : MaybeSerDes + PartialEq,
2032 S : Ring
2033{ }
2034impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
2035 V : Module <S>,
2036 V::LinearEndo : MaybeSerDes,
2037 S : Ring
2038{
2039 type Output = V;
2040 fn mul (self, rhs : V) -> Self::Output {
2041 self.0 * rhs
2042 }
2043}
2044impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2045 V : Module <S>,
2046 V::LinearEndo : MaybeSerDes,
2047 S : Ring
2048{
2049 type Output = Self;
2050 fn mul (self, rhs : Self) -> Self::Output {
2051 LinearAuto (self.0 * rhs.0)
2052 }
2053}
2054impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2055 V : Module <S>,
2056 V::LinearEndo : MaybeSerDes,
2057 S : Ring
2058{
2059 fn mul_assign (&mut self, rhs : Self) {
2060 self.0 *= rhs.0
2061 }
2062}
2063impl <S, V> num::One for LinearAuto <S, V> where
2064 V : Module <S>,
2065 V::LinearEndo : MaybeSerDes,
2066 S : Ring
2067{
2068 fn one() -> Self {
2069 LinearAuto (LinearIso::one())
2070 }
2071}
2072
2073impl <S, A, B, M> Affinity <S, A, B, M> where
2077 M : LinearMap <S, A::Vector, B::Vector>,
2078 A : AffineSpace <S>,
2079 B : AffineSpace <S>,
2080 S : Field + std::fmt::Display,
2081 B::Vector : std::fmt::Display
2082{
2083 pub fn new (
2084 linear_iso : LinearIso <S, A::Vector, B::Vector, M>,
2085 translation : B::Vector
2086 ) -> Self {
2087 Affinity { linear_iso, translation, _phantom: PhantomData }
2088 }
2089}
2090
2091impl <S, V, W, P, Q, M> Projectivity <S, V, W, P, Q, M> where
2095 M : LinearMap <S, P, Q>,
2096 P : ProjectiveSpace <S, V>,
2097 Q : ProjectiveSpace <S, W>,
2098 V : VectorSpace <S> + std::fmt::Display,
2099 W : VectorSpace <S> + std::fmt::Display,
2100 S : Field + std::fmt::Display
2101{
2102 pub fn new (linear_iso : LinearIso <S, P, Q, M>) -> Self {
2103 Projectivity (linear_iso, PhantomData)
2104 }
2105 pub fn transform (self, vector : P) -> Q {
2106 **self * vector
2107 }
2108}
2109impl <S, V, W, P, Q, M> std::ops::Deref for Projectivity <S, V, W, P, Q, M> where
2110 M : LinearMap <S, P, Q>,
2111 P : ProjectiveSpace <S, V>,
2112 Q : ProjectiveSpace <S, W>,
2113 V : VectorSpace <S> + std::fmt::Display,
2114 W : VectorSpace <S> + std::fmt::Display,
2115 S : Field + std::fmt::Display
2116{
2117 type Target = LinearIso <S, P, Q, M>;
2118 fn deref (&self) -> &Self::Target {
2119 &self.0
2120 }
2121}
2122
2123macro_rules! impl_angle {
2124 ( $angle:ident, $docname:expr ) => {
2125 #[doc = $docname]
2126 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2127 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2129 pub struct $angle <S> (pub S);
2130 impl_numcast_primitive!($angle);
2131 impl <S : Real> AdditiveGroup for $angle <S> { }
2132 impl <S : Real> AdditiveMonoid for $angle <S> { }
2133 impl <S : Ring> std::ops::Neg for $angle <S> {
2134 type Output = Self;
2135 fn neg (self) -> Self::Output {
2136 $angle (-self.0)
2137 }
2138 }
2139 impl <S : Ring> std::ops::Add for $angle <S> {
2140 type Output = Self;
2141 fn add (self, other : Self) -> Self::Output {
2142 $angle (self.0 + other.0)
2143 }
2144 }
2145 impl <S : Ring> std::ops::AddAssign for $angle <S> {
2146 fn add_assign (&mut self, other : Self) {
2147 self.0 += other.0
2148 }
2149 }
2150 impl <S : Ring> std::ops::Sub for $angle <S> {
2151 type Output = Self;
2152 fn sub (self, other : Self) -> Self::Output {
2153 $angle (self.0 - other.0)
2154 }
2155 }
2156 impl <S : Ring> std::ops::SubAssign for $angle <S> {
2157 fn sub_assign (&mut self, other : Self) {
2158 self.0 -= other.0
2159 }
2160 }
2161 impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2162 type Output = Self;
2163 fn mul (self, scalar : S) -> Self::Output {
2164 $angle (scalar * self.0)
2165 }
2166 }
2167 impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2168 fn mul_assign (&mut self, scalar : S) {
2169 self.0 *= scalar
2170 }
2171 }
2172 impl <S : Ring> std::ops::Div for $angle <S> {
2173 type Output = S;
2174 fn div (self, other : Self) -> Self::Output {
2175 self.0 / other.0
2176 }
2177 }
2178 impl <S : Ring> std::ops::Div <S> for $angle <S> {
2179 type Output = Self;
2180 fn div (self, scalar : S) -> Self::Output {
2181 $angle (self.0 / scalar)
2182 }
2183 }
2184 impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2185 fn div_assign (&mut self, scalar : S) {
2186 self.0 /= scalar
2187 }
2188 }
2189 impl <S : Ring> std::ops::Rem for $angle <S> {
2190 type Output = Self;
2191 fn rem (self, other : Self) -> Self::Output {
2192 $angle (self.0 % other.0)
2193 }
2194 }
2195 impl <S : Ring> num::Zero for $angle <S> {
2196 fn zero() -> Self {
2197 $angle (S::zero())
2198 }
2199 fn is_zero (&self) -> bool {
2200 self.0.is_zero()
2201 }
2202 }
2203 }
2204}
2205
2206macro_rules! impl_angle_wrapped {
2207 ( $angle:ident, $comment:expr ) => {
2208 #[doc = $comment]
2209 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2210 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2211 pub struct $angle <S> (Rad <S>);
2212
2213 impl_numcast!($angle);
2214 impl <S : Real> $angle <S> {
2215 pub fn angle (&self) -> Rad <S> {
2216 self.0
2217 }
2218 }
2219 impl <S : Real> AdditiveGroup for $angle <S> { }
2220 impl <S : Real> AdditiveMonoid for $angle <S> { }
2221 impl <S : Real> std::ops::Neg for $angle <S> {
2222 type Output = Self;
2223 fn neg (self) -> Self::Output {
2224 self.map (Rad::neg)
2225 }
2226 }
2227 impl <S : Real> std::ops::Add for $angle <S> {
2228 type Output = Self;
2229 fn add (self, other : Self) -> Self::Output {
2230 self.map (|angle| angle + other.0)
2231 }
2232 }
2233 impl <S : Real> std::ops::AddAssign for $angle <S> {
2234 fn add_assign (&mut self, other : Self) {
2235 *self = *self + other
2236 }
2237 }
2238 impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2239 type Output = Self;
2240 fn add (self, angle : Rad <S>) -> Self::Output {
2241 self.map (|a| a + angle)
2242 }
2243 }
2244 impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2245 fn add_assign (&mut self, angle : Rad <S>) {
2246 *self = *self + angle
2247 }
2248 }
2249 impl <S : Real> std::ops::Sub for $angle <S> {
2250 type Output = Self;
2251 fn sub (self, other : Self) -> Self::Output {
2252 self.map (|angle| angle - other.0)
2253 }
2254 }
2255 impl <S : Real> std::ops::SubAssign for $angle <S> {
2256 fn sub_assign (&mut self, other : Self) {
2257 *self = *self - other
2258 }
2259 }
2260 impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2261 type Output = Self;
2262 fn sub (self, angle : Rad <S>) -> Self::Output {
2263 self.map (|a| a - angle)
2264 }
2265 }
2266 impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2267 fn sub_assign (&mut self, angle : Rad <S>) {
2268 *self = *self - angle
2269 }
2270 }
2271 impl <S : Real> std::ops::Mul <S> for $angle <S> {
2272 type Output = Self;
2273 fn mul (self, scalar : S) -> Self::Output {
2274 self.map (|angle| angle * scalar)
2275 }
2276 }
2277 impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2278 fn mul_assign (&mut self, scalar : S) {
2279 *self = *self * scalar
2280 }
2281 }
2282 impl <S : Real> std::ops::Div for $angle <S> {
2283 type Output = S;
2284 fn div (self, other : Self) -> Self::Output {
2285 self.0 / other.0
2286 }
2287 }
2288 impl <S : Real> std::ops::Div <S> for $angle <S> {
2289 type Output = Self;
2290 fn div (self, scalar : S) -> Self::Output {
2291 self.map (|angle| angle / scalar)
2292 }
2293 }
2294 impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2295 fn div_assign (&mut self, scalar : S) {
2296 *self = *self / scalar
2297 }
2298 }
2299 impl <S : Real> std::ops::Rem for $angle <S> {
2300 type Output = Self;
2301 fn rem (self, other : Self) -> Self::Output {
2302 self.map (|angle| angle % other.0)
2303 }
2304 }
2305 impl <S : Real> num::Zero for $angle <S> {
2306 fn zero() -> Self {
2307 $angle (Rad::zero())
2308 }
2309 fn is_zero (&self) -> bool {
2310 self.0.is_zero()
2311 }
2312 }
2313 }
2314}
2315
2316macro_rules! impl_dimension {
2317 ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2318 $point_fun:ident, $vector_fun:ident,
2319 [$($component:ident),+],
2320 [$(($axis_method:ident, $unit_method:ident)),+], [$($projective:ident)?],
2321 $matrix:ident, $affine:ident, $euclidean:ident, $ndims:expr, $dimension:expr
2322 ) => {
2323 #[doc = $dimension]
2324 #[doc = "position"]
2325 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2326 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2327 #[display("{}", _0)]
2328 #[repr(C)]
2329 pub struct $point <S> (pub $vector <S>);
2330
2331 #[doc = $dimension]
2332 #[doc = "affine space"]
2333 #[derive(Debug)]
2334 pub struct $affine <S> (PhantomData <S>);
2335 impl <S : Field> AffineSpace <S> for $affine <S> {
2336 type Point = $point <S>;
2337 type Vector = $vector <S>;
2338 }
2339
2340 #[doc = $dimension]
2341 #[doc = "euclidean space"]
2342 #[derive(Debug)]
2343 pub struct $euclidean <S> (PhantomData <S>);
2344 impl <S : Real> EuclideanSpace <S> for $euclidean <S> { }
2345 impl <S : Real> AffineSpace <S> for $euclidean <S> {
2346 type Point = $point <S>;
2347 type Vector = $vector <S>;
2348 }
2349
2350 #[doc = $dimension]
2351 #[doc = "non-zero vector"]
2352 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2353 #[derive(Clone, Copy, Debug, PartialEq, Display)]
2354 #[display("{}", _0)]
2355 #[repr(C)]
2356 pub struct $nonzero <S> ($vector <S>);
2357
2358 #[doc = $dimension]
2359 #[doc = "unit vector"]
2360 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2361 #[derive(Clone, Copy, Debug, PartialEq, Display)]
2362 #[display("{}", _0)]
2363 #[repr(C)]
2364 pub struct $unit <S> ($vector <S>);
2365
2366 #[doc = "Construct a"]
2370 #[doc = $dimension]
2371 #[doc = "point"]
2372 pub const fn $point_fun <S> ($($component : S),+) -> $point <S> {
2373 $point::new ($($component),+)
2374 }
2375 impl_numcast!($point);
2376 impl <S> $point <S> {
2377 pub const fn new ($($component : S),+) -> Self {
2378 $point ($vector::new ($($component),+))
2379 }
2380 }
2381 impl <S> Point <$vector <S>> for $point <S> where S : Ring {
2382 fn to_vector (self) -> $vector <S> {
2383 self.0
2384 }
2385 fn from_vector (vector : $vector <S>) -> Self {
2386 $point (vector)
2387 }
2388 }
2389 impl <S> From<[S; $ndims]> for $point <S> {
2390 fn from (array : [S; $ndims]) -> Self {
2391 $point (array.into())
2392 }
2393 }
2394 impl <S> std::cmp::PartialOrd for $point <S> where S : PartialOrd {
2395 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
2396 self.0.as_slice().partial_cmp (&other.0.as_slice())
2397 }
2398 }
2399 impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2400 type Output = Self;
2401 fn add (self, displacement : $vector <S>) -> Self::Output {
2402 $point (self.0 + displacement)
2403 }
2404 }
2405 impl <S> std::ops::Add <&$vector <S>> for $point <S> where
2406 S : AdditiveGroup + Copy
2407 {
2408 type Output = Self;
2409 fn add (self, displacement : &$vector <S>) -> Self::Output {
2410 $point (self.0 + *displacement)
2411 }
2412 }
2413 impl <S> std::ops::Add <$vector <S>> for &$point <S> where
2414 S : AdditiveGroup + Copy
2415 {
2416 type Output = $point <S>;
2417 fn add (self, displacement : $vector <S>) -> Self::Output {
2418 $point (self.0 + displacement)
2419 }
2420 }
2421 impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2422 S : AdditiveGroup + Copy
2423 {
2424 type Output = $point <S>;
2425 fn add (self, displacement : &$vector <S>) -> Self::Output {
2426 $point (self.0 + *displacement)
2427 }
2428 }
2429 impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where
2430 S : AdditiveGroup
2431 {
2432 fn add_assign (&mut self, displacement : $vector <S>) {
2433 self.0 += displacement
2434 }
2435 }
2436 impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2437 S : AdditiveGroup + Copy
2438 {
2439 fn add_assign (&mut self, displacement : &$vector <S>) {
2440 self.0 += *displacement
2441 }
2442 }
2443 impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2444 type Output = Self;
2445 fn sub (self, displacement : $vector <S>) -> Self::Output {
2446 $point (self.0 - displacement)
2447 }
2448 }
2449 impl <S> std::ops::Sub <&$vector <S>> for $point <S> where
2450 S : AdditiveGroup + Copy
2451 {
2452 type Output = Self;
2453 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2454 $point (self.0 - *displacement)
2455 }
2456 }
2457 impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2458 type Output = $vector <S>;
2459 fn sub (self, other : Self) -> Self::Output {
2460 self.0 - other.0
2461 }
2462 }
2463 impl <S> std::ops::Sub <&$point <S>> for $point <S> where
2464 S : AdditiveGroup + Copy
2465 {
2466 type Output = $vector <S>;
2467 fn sub (self, other : &Self) -> Self::Output {
2468 self.0 - other.0
2469 }
2470 }
2471 impl <S> std::ops::Sub <$vector <S>> for &$point <S> where
2472 S : AdditiveGroup + Copy
2473 {
2474 type Output = $point <S>;
2475 fn sub (self, displacement : $vector <S>) -> Self::Output {
2476 $point (self.0 - displacement)
2477 }
2478 }
2479 impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2480 S : AdditiveGroup + Copy
2481 {
2482 type Output = $point <S>;
2483 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2484 $point (self.0 - *displacement)
2485 }
2486 }
2487 impl <S> std::ops::Sub <$point <S>> for &$point <S> where
2488 S : AdditiveGroup + Copy
2489 {
2490 type Output = $vector <S>;
2491 fn sub (self, other : $point <S>) -> Self::Output {
2492 self.0 - other.0
2493 }
2494 }
2495 impl <S> std::ops::Sub <&$point <S>> for &$point <S> where
2496 S : AdditiveGroup + Copy
2497 {
2498 type Output = $vector <S>;
2499 fn sub (self, other : &$point <S>) -> Self::Output {
2500 self.0 - other.0
2501 }
2502 }
2503 impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2504 S : AdditiveGroup
2505 {
2506 fn sub_assign (&mut self, displacement : $vector <S>) {
2507 self.0 -= displacement
2508 }
2509 }
2510 impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2511 S : AdditiveGroup + Copy
2512 {
2513 fn sub_assign (&mut self, displacement : &$vector <S>) {
2514 self.0 -= *displacement
2515 }
2516 }
2517 impl <S> approx::AbsDiffEq for $point <S> where
2518 S : approx::AbsDiffEq,
2519 S::Epsilon : Copy
2520 {
2521 type Epsilon = S::Epsilon;
2522 fn default_epsilon() -> Self::Epsilon {
2523 S::default_epsilon()
2524 }
2525 #[inline]
2526 fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2527 self.0.abs_diff_eq (&other.0, epsilon)
2528 }
2529 }
2530 impl <S> approx::RelativeEq for $point <S> where
2531 S : approx::RelativeEq,
2532 S::Epsilon : Copy
2533 {
2534 fn default_max_relative() -> Self::Epsilon {
2535 S::default_max_relative()
2536 }
2537 #[inline]
2538 fn relative_eq (&self,
2539 other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2540 ) -> bool {
2541 self.0.relative_eq (&other.0, epsilon, max_relative)
2542 }
2543 }
2544 impl <S> approx::UlpsEq for $point <S> where
2545 S : approx::UlpsEq,
2546 S::Epsilon : Copy
2547 {
2548 fn default_max_ulps() -> u32 {
2549 S::default_max_ulps()
2550 }
2551 #[inline]
2552 fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2553 -> bool
2554 {
2555 self.0.ulps_eq (&other.0, epsilon, max_ulps)
2556 }
2557 }
2558 #[doc = "Construct a"]
2562 #[doc = $dimension]
2563 #[doc = "vector"]
2564 pub const fn $vector_fun <S> ($($component : S),+) -> $vector <S> {
2565 $vector::new ($($component),+)
2566 }
2567 impl <S : Field> InnerProductSpace <S> for $vector <S> { }
2568 impl <S : Ring> Dot <S> for $vector <S> {
2569 fn dot (self, other : Self) -> S {
2570 self.dot (other)
2571 }
2572 }
2573 impl <S : Field> VectorSpace <S> for $vector <S> {
2574 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2575 self.map (f)
2576 }
2577 }
2578 impl <S : Ring> Module <S> for $vector <S> {
2579 type LinearEndo = $matrix <S>;
2580 }
2581 impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2582 fn determinant (self) -> S {
2583 self.determinant()
2584 }
2585 fn transpose (self) -> Self {
2586 self.transposed()
2587 }
2588 }
2589 impl <S : Ring> MultiplicativeMonoid for $matrix <S> { }
2590 impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2591 fn action (self, point : $point <S>) -> $point <S> {
2592 point + self
2593 }
2594 }
2595 impl <S : Ring> AdditiveGroup for $vector <S> { }
2596 impl <S : Ring> AdditiveMonoid for $vector <S> { }
2597 impl <S : AdditiveGroup> Group for $vector <S> {
2598 fn identity() -> Self {
2599 Self::zero()
2600 }
2601 fn operation (a : Self, b : Self) -> Self {
2602 a + b
2603 }
2604 }
2605 impl <S> Point <$vector <S>> for $vector <S> where S : Ring {
2606 fn to_vector (self) -> $vector <S> {
2607 self
2608 }
2609 fn from_vector (vector : $vector <S>) -> Self {
2610 vector
2611 }
2612 }
2613 impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2614 S : Ring + MaybeSerDes
2615 {
2616 type Output = Self;
2617 fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2618 self * rhs.0
2619 }
2620 }
2621 impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for
2622 $vector <S>
2623 where
2624 S : Ring + MaybeSerDes
2625 {
2626 type Output = Self;
2627 fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>)
2628 -> Self::Output
2629 {
2630 self * rhs.0
2631 }
2632 }
2633 impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2634 S : Ring + num::Float + MaybeSerDes
2635 {
2636 type Output = Self;
2637 fn inv (self) -> Self::Output {
2638 LinearAuto (self.0.inv())
2639 }
2640 }
2641 impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2642 S : Ring + num::Float + MaybeSerDes
2643 {
2644 type Output = Self;
2645 fn div (self, rhs : Self) -> Self::Output {
2646 LinearAuto (self.0 / rhs.0)
2647 }
2648 }
2649 impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2650 S : Ring + num::Float + MaybeSerDes
2651 {
2652 fn div_assign (&mut self, rhs : Self) {
2653 self.0 /= rhs.0
2654 }
2655 }
2656 impl <S> MultiplicativeGroup for LinearAuto <S, $vector <S>> where
2657 S : Ring + num::Float + MaybeSerDes
2658 { }
2659 $(
2661 impl <S> ProjectiveSpace <S, $vector <S>> for $projective <S> where
2662 S : Field + std::fmt::Display
2663 {
2664 fn homography <A> (
2665 affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
2666 ) -> Projectivity <
2667 S, $vector <S>, $vector <S>, Self, Self, Self::LinearEndo
2668 > where
2669 A : AffineSpace <S, Vector=$vector <S>>
2670 {
2671 Projectivity::new (
2672 LinearIso::<S, Self, Self, Self::LinearEndo>::new (
2673 (*affinity.linear_iso).into()
2674 ).unwrap()
2675 )
2676 }
2677 fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>)
2678 -> Self
2679 where
2680 A : AffineSpace <S, Vector=$vector <S>>,
2681 $vector <S> : GroupAction <A::Point>
2682 {
2683 match point_or_vector {
2684 Either::Left (point) => (point.to_vector(), S::one()).into(),
2685 Either::Right (vector) => (vector, S::zero()).into(),
2686 }
2687 }
2688 }
2689 )?
2690 impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2694 V : Module <S>,
2695 W : Module <S>,
2696 S : Ring + num::Float
2697 {
2698 type Output = LinearIso <S, W, V, $matrix <S>>;
2699 fn inv (self) -> Self::Output {
2700 let mat4 = Matrix4::from (self.0);
2702 LinearIso (mat4.inverted().into(), PhantomData::default())
2703 }
2704 }
2705 impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2706 V : Module <S, LinearEndo=$matrix <S>>,
2707 S : Ring + num::Float
2708 {
2709 type Output = Self;
2710 #[allow(clippy::suspicious_arithmetic_impl)]
2711 fn div (self, rhs : Self) -> Self::Output {
2712 use num::Inv;
2713 self * rhs.inv()
2714 }
2715 }
2716 impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2717 V : Module <S, LinearEndo=$matrix <S>>,
2718 S : Ring + num::Float
2719 {
2720 #[allow(clippy::suspicious_op_assign_impl)]
2721 fn div_assign (&mut self, rhs : Self) {
2722 use num::Inv;
2723 *self *= rhs.inv()
2724 }
2725 }
2726 impl_numcast!($nonzero);
2730 impl <S : Ring> $nonzero <S> {
2731 pub fn new (vector : $vector <S>) -> Option <Self> {
2741 use num::Zero;
2742 if !vector.is_zero() {
2743 Some ($nonzero (vector))
2744 } else {
2745 None
2746 }
2747 }
2748 pub fn noisy (vector : $vector <S>) -> Self {
2757 use num::Zero;
2758 assert!(!vector.is_zero());
2759 $nonzero (vector)
2760 }
2761 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2774 Self::noisy (fun (self.0))
2775 }
2776 }
2777 impl <S : Ring> std::ops::Deref for $nonzero <S> {
2778 type Target = $vector <S>;
2779 fn deref (&self) -> &$vector <S> {
2780 &self.0
2781 }
2782 }
2783 impl_numcast!($unit);
2787 impl <S : Real> $unit <S> {
2788 $(
2794 #[inline]
2795 pub fn $axis_method() -> Self {
2796 $unit ($vector::$unit_method())
2797 }
2798 )+
2799 pub fn new (vector : $vector <S>) -> Option <Self> {
2803 let normalized = vector.normalize();
2804 if vector == normalized {
2805 Some ($unit (vector))
2806 } else {
2807 None
2808 }
2809 }
2810 pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2816 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2817 {
2818 if vector.is_normalized() {
2819 Some ($unit (vector))
2820 } else {
2821 None
2822 }
2823 }
2824 pub fn normalize (vector : $vector <S>) -> Self {
2845 use num::Zero;
2846 assert!(!vector.is_zero());
2847 $unit (vector.normalize())
2848 }
2849 pub fn normalize_approx (vector : $vector <S>) -> Self where
2852 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2853 {
2854 use num::Zero;
2855 assert!(!vector.is_zero());
2856 let vector = if vector.is_normalized() {
2857 vector
2858 } else {
2859 vector.normalize()
2860 };
2861 $unit (vector)
2862 }
2863 pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2872 assert_eq!(vector, vector.normalize());
2873 $unit (vector)
2874 }
2875 pub fn noisy_approx (vector : $vector <S>) -> Self where
2884 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2885 {
2886 assert!(vector.is_normalized());
2887 $unit (vector)
2888 }
2889 #[inline]
2893 pub fn unchecked (vector : $vector <S>) -> Self where
2894 S : std::fmt::Debug
2895 {
2896 debug_assert_eq!(vector, vector.normalize());
2897 $unit (vector)
2898 }
2899 #[inline]
2908 pub fn unchecked_approx (vector : $vector <S>) -> Self where
2909 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2910 {
2911 debug_assert!(vector.is_normalized());
2912 $unit (vector)
2913 }
2914 pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2916 S : rand::distr::uniform::SampleUniform
2917 {
2918 let vector = $vector {
2919 $($component: rng.random_range (-S::one()..S::one())),+
2920 };
2921 $unit (vector.normalize())
2922 }
2923 pub fn invert (mut self) -> Self {
2926 self.0 = -self.0;
2927 self
2928 }
2929 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>)
2942 -> Self
2943 where
2944 S : std::fmt::Debug
2945 {
2946 Self::noisy (fun (self.0))
2947 }
2948 pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>)
2961 -> Self
2962 where
2963 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2964 {
2965 Self::noisy_approx (fun (self.0))
2966 }
2967 }
2968 impl <S : Real> std::ops::Deref for $unit <S> {
2969 type Target = $vector <S>;
2970 fn deref (&self) -> &$vector <S> {
2971 &self.0
2972 }
2973 }
2974 impl <S : Real> std::ops::Neg for $unit <S> {
2975 type Output = Self;
2976 fn neg (self) -> Self::Output {
2977 Self (-self.0)
2978 }
2979 }
2980 }
2982}
2983
2984macro_rules! impl_numcast {
2985 ($type:ident) => {
2986 impl <S> $type <S> {
2987 #[inline]
2988 pub fn numcast <T> (self) -> Option <$type <T>> where
2989 S : num::NumCast,
2990 T : num::NumCast
2991 {
2992 self.0.numcast().map ($type)
2993 }
2994 }
2995 }
2996}
2997
2998macro_rules! impl_numcast_primitive {
2999 ($type:ident) => {
3000 impl <S> $type <S> {
3001 #[inline]
3002 pub fn numcast <T> (self) -> Option <$type <T>> where
3003 S : num::NumCast,
3004 T : num::NumCast
3005 {
3006 T::from (self.0).map ($type)
3007 }
3008 }
3009 }
3010}
3011
3012#[doc(hidden)]
3013#[macro_export]
3014macro_rules! impl_numcast_fields {
3015 ($type:ident, $($field:ident),+) => {
3016 impl <S> $type <S> {
3017 #[inline]
3018 pub fn numcast <T> (self) -> Option <$type <T>> where
3019 S : num::NumCast,
3020 T : num::NumCast
3021 {
3022 Some ($type {
3023 $(
3024 $field: self.$field.numcast()?
3025 ),+
3026 })
3027 }
3028 }
3029 }
3030}
3031
3032impl_angle!(Deg, "Degrees");
3033impl_angle!(Rad, "Radians");
3034impl_angle!(Turn, "Turns");
3035impl_angle_wrapped!(AngleWrapped,
3036 "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
3037impl_angle_wrapped!(AngleWrappedSigned,
3038 "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
3039
3040impl_dimension!(Point2, Vector2, NonZero2, Unit2,
3041 point2, vector2,
3042 [x, y],
3043 [(axis_x, unit_x), (axis_y, unit_y)], [Vector3], Matrix2, Affine2, Euclidean2,
3044 2, "2D");
3045impl_dimension!(Point3, Vector3, NonZero3, Unit3,
3046 point3, vector3,
3047 [x, y, z],
3048 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3049 [Vector4], Matrix3, Affine3, Euclidean3, 3, "3D");
3050impl_dimension!(Point4, Vector4, NonZero4, Unit4,
3051 point4, vector4,
3052 [x, y, z, w],
3053 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3054 [], Matrix4, Affine4, Euclidean4, 4, "4D");
3055
3056impl_numcast_primitive!(Positive);
3057impl_numcast_primitive!(NonNegative);
3058impl_numcast_primitive!(NonZero);
3059impl_numcast_primitive!(Normalized);
3060impl_numcast_primitive!(NormalSigned);
3061impl_numcast_fields!(Angles3, yaw, pitch, roll);
3062
3063#[inline]
3067fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>)
3068 -> Quaternion <S>
3069{
3070 Quaternion::from_vec4 (quaternion.into_vec4().normalize())
3071}
3072
3073#[cfg(test)]
3074mod tests {
3075 use super::*;
3076 use crate::num_traits;
3077 use approx;
3078 use rand;
3079 use rand_xorshift;
3080
3081 #[test]
3082 fn defaults() {
3083 use num_traits::Zero;
3084
3085 assert_eq!(Positive::<f32>::default().0, 0.0);
3086 assert_eq!(NonNegative::<f32>::default().0, 0.0);
3087 assert_eq!(Normalized::<f32>::default().0, 0.0);
3088 assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3089 assert_eq!(Deg::<f32>::default().0, 0.0);
3090 assert_eq!(Rad::<f32>::default().0, 0.0);
3091 assert_eq!(Turn::<f32>::default().0, 0.0);
3092 assert_eq!(
3093 Angles3::<f32>::default(),
3094 Angles3::new (
3095 AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero())
3096 );
3097 assert_eq!(
3098 Pose3::<f32>::default(),
3099 Pose3 { position: Point3::origin(), angles: Angles3::default() });
3100 assert_eq!(
3101 LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3102 Matrix3::identity());
3103 assert_eq!(
3104 LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3105 assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3106 assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3107 assert_eq!(
3108 Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3109 assert_eq!(
3110 AffineMap::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3111 AffineMap::new (Matrix3::identity(), Vector3::zero()));
3112 assert_eq!(
3113 Affinity::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3114 Affinity::new (
3115 LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3116 assert_eq!(
3117 Projectivity::<
3118 f32, Vector3 <f32>, Vector3 <f32>, Vector4 <f32>, Vector4 <f32>,
3119 Matrix4 <f32>
3120 >::default().0,
3121 LinearIso::new (Matrix4::identity()).unwrap());
3122 }
3123
3124 #[test]
3125 fn rotation3_noisy_approx() {
3126 use rand::{Rng, SeedableRng};
3127 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3130 let up = Vector3::unit_z();
3131 for _ in 0..1000 {
3132 let forward = vector3 (
3133 rng.random_range (-1000.0f32..1000.0),
3134 rng.random_range (-1000.0f32..1000.0),
3135 0.0
3136 ).normalized();
3137 let right = forward.cross (up);
3138 let mat = Matrix3::from_col_arrays ([
3139 right.into_array(),
3140 forward.into_array(),
3141 up.into_array()
3142 ]);
3143 let _ = Rotation3::noisy_approx (mat);
3144 }
3145 }
3146
3147 #[test]
3148 fn rotation3_intrinsic_angles() {
3149 use std::f32::consts::PI;
3150 use num_traits::Zero;
3151 use rand::{Rng, SeedableRng};
3152 let rot = Rotation3::from_angles_intrinsic (
3154 Turn (0.25).into(), Rad::zero(), Rad::zero());
3155 approx::assert_relative_eq!(*rot,
3156 Matrix3::from_col_arrays ([
3157 [ 0.0, 1.0, 0.0],
3158 [-1.0, 0.0, 0.0],
3159 [ 0.0, 0.0, 1.0]
3160 ])
3161 );
3162 assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()),
3163 rot.intrinsic_angles());
3164 let rot = Rotation3::from_angles_intrinsic (
3165 Turn (0.5).into(), Rad::zero(), Rad::zero());
3166 approx::assert_relative_eq!(*rot,
3167 Matrix3::from_col_arrays ([
3168 [-1.0, 0.0, 0.0],
3169 [ 0.0, -1.0, 0.0],
3170 [ 0.0, 0.0, 1.0]
3171 ])
3172 );
3173 assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()),
3174 rot.intrinsic_angles());
3175 let rot = Rotation3::from_angles_intrinsic (
3177 Rad::zero(), Turn (0.25).into(), Rad::zero());
3178 approx::assert_relative_eq!(*rot,
3179 Matrix3::from_col_arrays ([
3180 [1.0, 0.0, 0.0],
3181 [0.0, 0.0, 1.0],
3182 [0.0, -1.0, 0.0]
3183 ])
3184 );
3185 assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()),
3186 rot.intrinsic_angles());
3187 let rot = Rotation3::from_angles_intrinsic (
3189 Rad::zero(), Rad::zero(), Turn (0.25).into());
3190 approx::assert_relative_eq!(*rot,
3191 Matrix3::from_col_arrays ([
3192 [0.0, 0.0, -1.0],
3193 [0.0, 1.0, 0.0],
3194 [1.0, 0.0, 0.0]
3195 ])
3196 );
3197 assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()),
3198 rot.intrinsic_angles());
3199 let rot = Rotation3::from_angles_intrinsic (
3201 Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3202 approx::assert_relative_eq!(*rot,
3203 Matrix3::from_col_arrays ([
3204 [0.0, 1.0, 0.0],
3205 [0.0, 0.0, 1.0],
3206 [1.0, 0.0, 0.0]
3207 ])
3208 );
3209 let angles = rot.intrinsic_angles();
3210 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3211 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3212 approx::assert_relative_eq!(0.0, angles.2.0);
3213 let rot = Rotation3::from_angles_intrinsic (
3215 Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3216 approx::assert_relative_eq!(*rot,
3217 Matrix3::from_col_arrays ([
3218 [-1.0, 0.0, 0.0],
3219 [ 0.0, 0.0, 1.0],
3220 [ 0.0, 1.0, 0.0]
3221 ])
3222 );
3223 let angles = rot.intrinsic_angles();
3224 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3225 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3226 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3227
3228 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3231 let mut random_vector = || vector3 (
3232 rng.random_range (-100.0f32..100.0),
3233 rng.random_range (-100.0f32..100.0),
3234 rng.random_range (-100.0f32..100.0)
3235 );
3236 for _ in 0..1000 {
3237 let rot = Rotation3::orthonormalize (
3238 random_vector(), random_vector(), random_vector()
3239 ).unwrap();
3240 let (yaw, pitch, roll) = rot.intrinsic_angles();
3241 assert!(yaw.0 < PI);
3242 assert!(yaw.0 > -PI);
3243 assert!(pitch.0 < PI);
3244 assert!(pitch.0 > -PI);
3245 assert!(roll.0 < PI);
3246 assert!(roll.0 > -PI);
3247 }
3248 }
3249
3250 #[test]
3251 fn rotation3_into_versor() {
3252 use std::f32::consts::PI;
3253 let rot = Rotation3::from_angle_x (Rad (0.01));
3254 let quat = rot.versor().0;
3255 approx::assert_relative_eq!(*rot, quat.into());
3256 let rot = Rotation3::from_angle_x (Rad (-0.01));
3257 let quat = rot.versor().0;
3258 approx::assert_relative_eq!(*rot, quat.into());
3259
3260 let rot = Rotation3::from_angle_y (Rad (0.01));
3261 let quat = rot.versor().0;
3262 approx::assert_relative_eq!(*rot, quat.into());
3263 let rot = Rotation3::from_angle_y (Rad (-0.01));
3264 let quat = rot.versor().0;
3265 approx::assert_relative_eq!(*rot, quat.into());
3266
3267 let rot = Rotation3::from_angle_z (Rad (0.01));
3268 let quat = rot.versor().0;
3269 approx::assert_relative_eq!(*rot, quat.into());
3270 let rot = Rotation3::from_angle_z (Rad (-0.01));
3271 let quat = rot.versor().0;
3272 approx::assert_relative_eq!(*rot, quat.into());
3273
3274 let rot = Rotation3::from_angle_x (Rad (PI / 2.0));
3275 let quat = rot.versor().0;
3276 approx::assert_relative_eq!(*rot, quat.into());
3277 let rot = Rotation3::from_angle_x (Rad (-PI / 2.0));
3278 let quat = rot.versor().0;
3279 approx::assert_relative_eq!(*rot, quat.into());
3280
3281 let rot = Rotation3::from_angle_y (Rad (PI / 2.0));
3282 let quat = rot.versor().0;
3283 approx::assert_relative_eq!(*rot, quat.into());
3284 let rot = Rotation3::from_angle_y (Rad (-PI / 2.0));
3285 let quat = rot.versor().0;
3286 approx::assert_relative_eq!(*rot, quat.into());
3287
3288 let rot = Rotation3::from_angle_z (Rad (PI / 2.0));
3289 let quat = rot.versor().0;
3290 approx::assert_relative_eq!(*rot, quat.into());
3291 let rot = Rotation3::from_angle_z (Rad (-PI / 2.0));
3292 let quat = rot.versor().0;
3293 approx::assert_relative_eq!(*rot, quat.into());
3294 }
3295}