1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3use either::Either;
4use vek;
5
6use crate::approx;
7use crate::num_traits as num;
8
9#[cfg(feature = "derive_serdes")]
10use serde::{Deserialize, Serialize};
11
12use crate::traits::*;
13
14pub mod coordinate;
15
16pub use vek::Vec2 as Vector2;
17pub use vek::Mat2 as Matrix2;
18pub use vek::Vec3 as Vector3;
19pub use vek::Mat3 as Matrix3;
20pub use vek::Vec4 as Vector4;
21pub use vek::Mat4 as Matrix4;
22pub use vek::Quaternion as Quaternion;
23
24pub use self::enums::{Axis2, Axis3, Axis4, Octant, Quadrant, Sign, SignedAxis1,
25 SignedAxis2, SignedAxis3, SignedAxis4};
26
27mod enums {
34 use strum::{EnumCount, EnumIter, FromRepr};
35 #[cfg(feature = "derive_serdes")]
36 use serde::{Deserialize, Serialize};
37
38 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
40 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
41 #[repr(u8)]
42 pub enum Sign {
43 Negative,
44 Zero,
45 Positive
46 }
47
48 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
50 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
51 #[repr(u8)]
52 pub enum Quadrant {
53 PosPos,
55 NegPos,
57 PosNeg,
59 NegNeg
61 }
62
63 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
65 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
66 #[repr(u8)]
67 pub enum Octant {
68 PosPosPos,
70 NegPosPos,
72 PosNegPos,
74 NegNegPos,
76 PosPosNeg,
78 NegPosNeg,
80 PosNegNeg,
82 NegNegNeg
84 }
85
86 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
88 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
89 #[repr(u8)]
90 pub enum Axis2 {
91 X=0,
92 Y
93 }
94
95 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
97 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
98 #[repr(u8)]
99 pub enum Axis3 {
100 X=0,
101 Y,
102 Z
103 }
104
105 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
107 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
108 #[repr(u8)]
109 pub enum Axis4 {
110 X=0,
111 Y,
112 Z,
113 W
114 }
115
116 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
118 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
119 #[repr(u8)]
120 pub enum SignedAxis1 {
121 NegX, PosX
122 }
123
124 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
126 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
127 #[repr(u8)]
128 pub enum SignedAxis2 {
129 NegX, PosX,
130 NegY, PosY
131 }
132
133 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
135 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
136 #[repr(u8)]
137 pub enum SignedAxis3 {
138 NegX, PosX,
139 NegY, PosY,
140 NegZ, PosZ
141 }
142
143 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
145 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
146 #[repr(u8)]
147 pub enum SignedAxis4 {
148 NegX, PosX,
149 NegY, PosY,
150 NegZ, PosZ,
151 NegW, PosW
152 }
153}
154
155#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
161#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
162pub struct Positive <S> (S);
163
164#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
166#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
167pub struct NonNegative <S> (S);
168
169#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
171#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
172pub struct NonZero <S> (S);
173
174#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
176#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
177pub struct Normalized <S> (S);
178
179#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
181#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
182pub struct NormalSigned <S> (S);
183
184#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
190#[derive(Clone, Copy, Debug, Default, PartialEq)]
191pub struct Angles3 <S> {
192 pub yaw : AngleWrapped <S>,
193 pub pitch : AngleWrapped <S>,
194 pub roll : AngleWrapped <S>
195}
196
197#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
199#[derive(Clone, Copy, Debug, Default, PartialEq)]
200pub struct Pose3 <S> {
201 pub position : Point3 <S>,
202 pub angles : Angles3 <S>
203}
204
205#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
207#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
208#[display("{}", _0)]
209pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
210
211#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
213#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
214#[display("{}", _0)]
215pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
216 V : Module <S>,
217 V::LinearEndo : MaybeSerDes,
218 S : Ring;
219
220#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
223#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
224#[derive(Clone, Copy, Debug, Default, PartialEq)]
225pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where
226 S : Ring + MaybeSerDes;
227
228#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
231#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
232#[derive(Clone, Copy, Debug, Default, PartialEq)]
233pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where
234 S : Ring + MaybeSerDes;
235
236#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
238#[derive(Clone, Copy, Debug, Default, PartialEq)]
239pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
240
241#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
244#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
245#[display("({}, {})", linear_map, translation)]
246pub struct AffineMap <S, A, B, M> where
247 B : AffineSpace <S>,
248 S : Field + std::fmt::Display,
249 B::Vector : std::fmt::Display
250{
251 pub linear_map : M,
252 pub translation : B::Vector,
253 pub _phantom : PhantomData <A>
254}
255
256#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
258#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
259#[display("({}, {})", linear_iso, translation)]
260pub struct Affinity <S, A, B, M> where
261 A : AffineSpace <S>,
262 B : AffineSpace <S>,
263 S : Field + std::fmt::Display,
264 B::Vector : std::fmt::Display
265{
266 pub linear_iso : LinearIso <S, A::Vector, B::Vector, M>,
267 pub translation : B::Vector,
268 pub _phantom : PhantomData <A>
269}
270
271#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
274#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
275#[display("{}", _0)]
276pub struct Projectivity <S, V, W, P, Q, M> (
277 pub LinearIso <S, P, Q, M>,
278 pub PhantomData <(V, W)>
279);
280
281impl <S : Real> Angle <S> for Deg <S> {
289 fn full_turn() -> Self {
290 Deg (S::ten() * S::nine() * S::two() * S::two())
291 }
292 fn half_turn() -> Self {
293 Deg (S::ten() * S::nine() * S::two())
294 }
295}
296impl <S : Real> Trig for Deg <S> {
297 fn sin (self) -> Self {
298 Rad::from (self).sin().into()
299 }
300 fn sin_cos (self) -> (Self, Self) {
301 let (sin, cos) = Rad::from (self).sin_cos();
302 (sin.into(), cos.into())
303 }
304 fn cos (self) -> Self {
305 Rad::from (self).cos().into()
306 }
307 fn tan (self) -> Self {
308 Rad::from (self).tan().into()
309 }
310 fn asin (self) -> Self {
311 Rad::from (self).asin().into()
312 }
313 fn acos (self) -> Self {
314 Rad::from (self).acos().into()
315 }
316 fn atan (self) -> Self {
317 Rad::from (self).atan().into()
318 }
319 fn atan2 (self, other : Self) -> Self {
320 Rad::from (self).atan2 (Rad::from (other)).into()
321 }
322}
323impl <S : Real> From <Rad <S>> for Deg <S> {
324 fn from (radians : Rad <S>) -> Self {
325 let full_turns = radians / Rad::full_turn();
326 Deg::full_turn() * full_turns
327 }
328}
329impl <S : Real> From <Turn <S>> for Deg <S> {
330 fn from (turns : Turn <S>) -> Self {
331 Deg (turns.0 * Deg::full_turn().0)
332 }
333}
334
335impl <S : Real> Angle <S> for Rad <S> {
339 fn full_turn() -> Self {
340 Rad (S::pi() * S::two())
341 }
342}
343impl <S : Real> Trig for Rad <S> {
344 fn sin (self) -> Self {
345 Rad (self.0.sin())
346 }
347 fn sin_cos (self) -> (Self, Self) {
348 let (sin, cos) = self.0.sin_cos();
349 (Rad (sin), Rad (cos))
350 }
351 fn cos (self) -> Self {
352 Rad (self.0.cos())
353 }
354 fn tan (self) -> Self {
355 Rad (self.0.tan())
356 }
357 fn asin (self) -> Self {
358 Rad (self.0.asin())
359 }
360 fn acos (self) -> Self {
361 Rad (self.0.acos())
362 }
363 fn atan (self) -> Self {
364 Rad (self.0.atan())
365 }
366 fn atan2 (self, other : Self) -> Self {
367 Rad (self.0.atan2 (other.0))
368 }
369}
370impl <S : Real> From <Deg <S>> for Rad <S> {
371 fn from (degrees : Deg <S>) -> Self {
372 let full_turns = degrees / Deg::full_turn();
373 Rad::full_turn() * full_turns
374 }
375}
376impl <S : Real> From <Turn <S>> for Rad <S> {
377 fn from (turns : Turn <S>) -> Self {
378 Rad (turns.0 * Rad::full_turn().0)
379 }
380}
381
382impl <S : Real> Angle <S> for Turn <S> {
386 fn full_turn() -> Self {
387 Turn (S::one())
388 }
389 fn half_turn() -> Self {
390 Turn (S::one() / S::two())
391 }
392}
393impl <S : Real> Trig for Turn <S> {
394 fn sin (self) -> Self {
395 Rad::from (self).sin().into()
396 }
397 fn sin_cos (self) -> (Self, Self) {
398 let (sin, cos) = Rad::from (self).sin_cos();
399 (sin.into(), cos.into())
400 }
401 fn cos (self) -> Self {
402 Rad::from (self).cos().into()
403 }
404 fn tan (self) -> Self {
405 Rad::from (self).tan().into()
406 }
407 fn asin (self) -> Self {
408 Rad::from (self).asin().into()
409 }
410 fn acos (self) -> Self {
411 Rad::from (self).acos().into()
412 }
413 fn atan (self) -> Self {
414 Rad::from (self).atan().into()
415 }
416 fn atan2 (self, other : Self) -> Self {
417 Rad::from (self).atan2 (Rad::from (other)).into()
418 }
419}
420impl <S : Real> From <Rad <S>> for Turn <S> {
421 fn from (radians : Rad <S>) -> Self {
422 Turn (radians.0 / Rad::full_turn().0)
423 }
424}
425impl <S : Real> From <Deg <S>> for Turn <S> {
426 fn from (degrees : Deg <S>) -> Self {
427 Turn (degrees.0 / Deg::full_turn().0)
428 }
429}
430
431impl <S : Real> AngleWrapped <S> {
435 pub fn wrap (angle : Rad <S>) -> Self {
436 AngleWrapped (angle.wrap_unsigned())
437 }
438
439 pub fn map <F> (self, f : F) -> Self where
440 F : FnOnce (Rad <S>) -> Rad <S>
441 {
442 AngleWrapped (f (self.0).wrap_unsigned())
443 }
444}
445
446impl <S : Real> AngleWrappedSigned <S> {
450 pub fn wrap (angle : Rad <S>) -> Self {
451 AngleWrappedSigned (angle.wrap_signed())
452 }
453
454 pub fn map <F> (self, f : F) -> Self where
455 F : FnOnce (Rad <S>) -> Rad <S>
456 {
457 AngleWrappedSigned (f (self.0).wrap_signed())
458 }
459}
460
461impl <S : Real> Angles3 <S> {
466 pub const fn new (
467 yaw : AngleWrapped <S>,
468 pitch : AngleWrapped <S>,
469 roll : AngleWrapped <S>
470 ) -> Self {
471 Angles3 { yaw, pitch, roll }
472 }
473
474 pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
475 let yaw = AngleWrapped::wrap (yaw);
476 let pitch = AngleWrapped::wrap (pitch);
477 let roll = AngleWrapped::wrap (roll);
478 Angles3 { yaw, pitch, roll }
479 }
480}
481
482impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
483 fn from (rotation : Rotation3 <S>) -> Self {
484 let (yaw, pitch, roll) = {
485 let (yaw, pitch, roll) = rotation.intrinsic_angles();
486 ( AngleWrapped::wrap (yaw),
487 AngleWrapped::wrap (pitch),
488 AngleWrapped::wrap (roll)
489 )
490 };
491 Angles3 { yaw, pitch, roll }
492 }
493}
494
495impl Axis2 {
499 #[inline]
500 pub fn component (self) -> usize {
501 self as usize
502 }
503}
504
505impl Axis3 {
509 #[inline]
510 pub fn component (self) -> usize {
511 self as usize
512 }
513}
514
515impl SignedAxis3 {
519 pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
520 return if *vector == [ S::one(), S::zero(), S::zero()].into() {
521 Some (SignedAxis3::PosX)
522 } else if *vector == [-S::one(), S::zero(), S::zero()].into() {
523 Some (SignedAxis3::NegX)
524 } else if *vector == [ S::zero(), S::one(), S::zero()].into() {
525 Some (SignedAxis3::PosY)
526 } else if *vector == [ S::zero(), -S::one(), S::zero()].into() {
527 Some (SignedAxis3::NegY)
528 } else if *vector == [ S::zero(), S::zero(), S::one() ].into() {
529 Some (SignedAxis3::PosZ)
530 } else if *vector == [ S::zero(), S::zero(), -S::one() ].into() {
531 Some (SignedAxis3::NegZ)
532 } else {
533 None
534 }
535 }
536
537 pub fn to_vec <S : Field> (self) -> Vector3 <S> {
538 match self {
539 SignedAxis3::NegX => [-S::one(), S::zero(), S::zero()].into(),
540 SignedAxis3::PosX => [ S::one(), S::zero(), S::zero()].into(),
541 SignedAxis3::NegY => [ S::zero(), -S::one(), S::zero()].into(),
542 SignedAxis3::PosY => [ S::zero(), S::one(), S::zero()].into(),
543 SignedAxis3::NegZ => [ S::zero(), S::zero(), -S::one() ].into(),
544 SignedAxis3::PosZ => [ S::zero(), S::zero(), S::one() ].into()
545 }
546 }
547 #[inline]
548 pub fn to_unit <S : Real> (self) -> Unit3 <S> where S : std::fmt::Debug {
549 Unit3::unchecked (self.to_vec())
550 }
551}
552
553impl Quadrant {
557 pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
560 S : Ring + SignedExt
561 {
562 let sign_x = vector.x.sign();
563 let sign_y = vector.y.sign();
564 let quadrant = match (sign_x, sign_y) {
565 (Sign::Zero, _) |
566 ( _, Sign::Zero) => return None,
567 (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
568 (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
569 (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
570 (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
571 };
572 Some (quadrant)
573 }
574 #[inline]
576 pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
577 S : Ring + SignedExt
578 {
579 Quadrant::from_vec_strict (&point.to_vector())
580 }
581}
582impl Octant {
588 pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
591 S : Ring + SignedExt
592 {
593 let sign_x = vector.x.sign();
594 let sign_y = vector.y.sign();
595 let sign_z = vector.z.sign();
596 let octant = match (sign_x, sign_y, sign_z) {
597 (Sign::Zero, _, _) |
598 ( _, Sign::Zero, _) |
599 ( _, _, Sign::Zero) => return None,
600 (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
601 (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
602 (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
603 (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
604 (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
605 (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
606 (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
607 (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
608 };
609 Some (octant)
610 }
611 #[inline]
613 pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
614 S : Ring + SignedExt
615 {
616 Octant::from_vec_strict (&point.to_vector())
617 }
618}
619impl <S : Ring> Positive <S> {
625 pub fn new (value : S) -> Option <Self> {
636 if value > S::zero() {
637 Some (Positive (value))
638 } else {
639 None
640 }
641 }
642 pub fn infinity() -> Self where S : num::float::FloatCore {
644 Positive (S::infinity())
645 }
646 pub fn noisy (value : S) -> Self {
655 assert!(value > S::zero());
656 Positive (value)
657 }
658 pub fn unchecked (value : S) -> Self {
668 debug_assert!(value > S::zero());
669 Positive (value)
670 }
671 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
692 Self::noisy (fun (self.0))
693 }
694}
695impl <S : Field> num::One for Positive <S> {
696 fn one() -> Self {
697 Positive (S::one())
698 }
699}
700impl <S : Ring> std::ops::Deref for Positive <S> {
701 type Target = S;
702 fn deref (&self) -> &S {
703 &self.0
704 }
705}
706impl <S : Ring> std::ops::Mul for Positive <S> {
707 type Output = Self;
708 fn mul (self, rhs : Self) -> Self::Output {
709 Positive (self.0 * rhs.0)
710 }
711}
712impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
713 type Output = NonNegative <S>;
714 fn mul (self, rhs : NonNegative <S>) -> Self::Output {
715 NonNegative (self.0 * *rhs)
716 }
717}
718impl <S : Field> std::ops::Div for Positive <S> {
719 type Output = Self;
720 fn div (self, rhs : Self) -> Self::Output {
721 Positive (self.0 / rhs.0)
722 }
723}
724impl <S : Ring> std::ops::Add for Positive <S> {
725 type Output = Self;
726 fn add (self, rhs : Self) -> Self::Output {
727 Positive (self.0 + rhs.0)
728 }
729}
730impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
731 type Output = Self;
732 fn add (self, rhs : NonNegative <S>) -> Self::Output {
733 Positive (self.0 + rhs.0)
734 }
735}
736impl <S : Ring> NonNegative <S> {
742 pub fn new (value : S) -> Option <Self> {
753 if value >= S::zero() {
754 Some (NonNegative (value))
755 } else {
756 None
757 }
758 }
759 pub fn abs (value : S) -> Self {
769 NonNegative (value.abs())
770 }
771 pub fn noisy (value : S) -> Self {
780 assert!(S::zero() <= value);
781 NonNegative (value)
782 }
783 pub fn unchecked (value : S) -> Self {
793 debug_assert!(value >= S::zero());
794 NonNegative (value)
795 }
796 pub fn map_abs (self, fun : fn (S) -> S) -> Self {
806 Self::abs (fun (self.0))
807 }
808 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
827 Self::noisy (fun (self.0))
828 }
829}
830impl <S : Ring> From <Positive <S>> for NonNegative <S> {
831 fn from (positive : Positive <S>) -> Self {
832 NonNegative (*positive)
833 }
834}
835impl <S : Ring> num::Zero for NonNegative <S> {
836 fn zero() -> Self {
837 NonNegative (S::zero())
838 }
839 fn is_zero (&self) -> bool {
840 self.0.is_zero()
841 }
842}
843impl <S : Field> num::One for NonNegative <S> {
844 fn one() -> Self {
845 NonNegative (S::one())
846 }
847}
848impl <S : Ring> std::ops::Deref for NonNegative <S> {
849 type Target = S;
850 fn deref (&self) -> &S {
851 &self.0
852 }
853}
854impl <S : Ring> std::ops::Mul for NonNegative <S> {
855 type Output = Self;
856 fn mul (self, rhs : Self) -> Self::Output {
857 NonNegative (self.0 * rhs.0)
858 }
859}
860impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
861 type Output = Self;
862 fn mul (self, rhs : Positive <S>) -> Self::Output {
863 NonNegative (self.0 * rhs.0)
864 }
865}
866impl <S : Field> std::ops::Div for NonNegative <S> {
867 type Output = Self;
868 fn div (self, rhs : Self) -> Self::Output {
869 NonNegative (self.0 / rhs.0)
870 }
871}
872impl <S : Ring> std::ops::Add for NonNegative <S> {
873 type Output = Self;
874 fn add (self, rhs : Self) -> Self::Output {
875 NonNegative (self.0 + rhs.0)
876 }
877}
878impl <S : Field> NonZero <S> {
884 #[inline]
895 pub fn new (value : S) -> Option <Self> {
896 if S::zero() != value {
897 Some (NonZero (value))
898 } else {
899 None
900 }
901 }
902 #[inline]
911 pub fn noisy (value : S) -> Self {
912 assert!(S::zero() != value);
913 NonZero (value)
914 }
915 #[inline]
936 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
937 Self::noisy (fun (self.0))
938 }
939}
940impl <S : Field> num::One for NonZero <S> {
941 fn one() -> Self {
942 NonZero (S::one())
943 }
944}
945impl <S : Field> std::ops::Deref for NonZero <S> {
946 type Target = S;
947 fn deref (&self) -> &S {
948 &self.0
949 }
950}
951impl <S : Field> std::ops::Mul for NonZero <S> {
952 type Output = Self;
953 fn mul (self, rhs : Self) -> Self::Output {
954 NonZero (self.0 * rhs.0)
955 }
956}
957impl <S : Field> Eq for NonZero <S> { }
958impl <S : Field> Normalized <S> {
964 #[inline]
966 pub fn zero() -> Self {
967 Normalized (S::zero())
968 }
969 #[inline]
970 pub fn is_zero (&self) -> bool {
971 self.0.is_zero()
972 }
973 #[inline]
987 pub fn new (value : S) -> Option <Self> {
988 if S::zero() <= value && value <= S::one() {
989 Some (Normalized (value))
990 } else {
991 None
992 }
993 }
994 #[inline]
1004 pub fn clamp (value : S) -> Self {
1005 let value = S::max (S::zero(), S::min (value, S::one()));
1006 Normalized (value)
1007 }
1008 #[inline]
1022 pub fn noisy (value : S) -> Self {
1023 assert!(value <= S::one());
1024 assert!(S::zero() <= value);
1025 Normalized (value)
1026 }
1027 #[inline]
1039 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1040 Self::clamp (fun (self.0))
1041 }
1042 #[inline]
1069 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1070 Self::noisy (fun (self.0))
1071 }
1072}
1073impl <S : Field> num::One for Normalized <S> {
1074 fn one() -> Self {
1075 Normalized (S::one())
1076 }
1077}
1078impl <S : Field> std::ops::Deref for Normalized <S> {
1079 type Target = S;
1080 fn deref (&self) -> &S {
1081 &self.0
1082 }
1083}
1084impl <S : Field> std::ops::Mul for Normalized <S> {
1085 type Output = Self;
1086 fn mul (self, rhs : Self) -> Self::Output {
1087 Normalized (self.0 * rhs.0)
1088 }
1089}
1090impl <S : Field> Eq for Normalized <S> { }
1091impl <S : Field> Ord for Normalized <S> {
1092 fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1093 self.partial_cmp (rhs).unwrap()
1095 }
1096}
1097impl <S : Field> NormalSigned <S> {
1103 #[inline]
1105 pub fn zero() -> Self {
1106 NormalSigned (S::zero())
1107 }
1108 #[inline]
1109 pub fn is_zero (&self) -> bool {
1110 self.0.is_zero()
1111 }
1112 #[inline]
1127 pub fn new (value : S) -> Option <Self> {
1128 if -S::one() <= value && value <= S::one() {
1129 Some (NormalSigned (value))
1130 } else {
1131 None
1132 }
1133 }
1134 #[inline]
1144 pub fn clamp (value : S) -> Self {
1145 let value = S::max (-S::one(), S::min (value, S::one()));
1146 NormalSigned (value)
1147 }
1148 #[inline]
1162 pub fn noisy (value : S) -> Self {
1163 assert!(value <= S::one());
1164 assert!(-S::one() <= value);
1165 NormalSigned (value)
1166 }
1167 #[inline]
1179 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1180 Self::clamp (fun (self.0))
1181 }
1182 #[inline]
1209 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1210 Self::noisy (fun (self.0))
1211 }
1212}
1213impl <S : Field> From <Normalized <S>> for NormalSigned <S> {
1214 fn from (Normalized (value) : Normalized <S>) -> Self {
1215 debug_assert!(S::zero() <= value);
1216 debug_assert!(value <= S::one());
1217 NormalSigned (value)
1218 }
1219}
1220impl <S : Field> num::One for NormalSigned <S> {
1221 fn one() -> Self {
1222 NormalSigned (S::one())
1223 }
1224}
1225impl <S : Field> std::ops::Deref for NormalSigned <S> {
1226 type Target = S;
1227 fn deref (&self) -> &S {
1228 &self.0
1229 }
1230}
1231impl <S : Field> std::ops::Mul for NormalSigned <S> {
1232 type Output = Self;
1233 fn mul (self, rhs : Self) -> Self::Output {
1234 NormalSigned (self.0 * rhs.0)
1235 }
1236}
1237impl <S : Field> Eq for NormalSigned <S> { }
1238impl <S : Field> Ord for NormalSigned <S> {
1239 fn cmp (&self, rhs : &Self) -> std::cmp::Ordering {
1240 self.partial_cmp (rhs).unwrap()
1242 }
1243}
1244impl <S : Field> std::ops::Neg for NormalSigned <S> {
1245 type Output = Self;
1246 fn neg (self) -> Self::Output {
1247 NormalSigned (-self.0)
1248 }
1249}
1250impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1256 pub fn identity() -> Self {
1258 use num::One;
1259 Self::one()
1260 }
1261 pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1267 let transform = LinearAuto (LinearIso::new (mat)?);
1268 if !transform.is_rotation() {
1269 None
1270 } else {
1271 Some (Rotation2 (transform))
1272 }
1273 }
1274 pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1280 S : approx::RelativeEq <Epsilon=S>
1281 {
1282 let four = S::one() + S::one() + S::one() + S::one();
1283 let epsilon = S::default_epsilon() * four;
1284 let max_relative = S::default_max_relative() * four;
1285 if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1286 max_relative=max_relative, epsilon=epsilon
1287 ) || approx::relative_ne!(mat.determinant(), S::one(),
1288 max_relative=max_relative
1289 ) {
1290 None
1291 } else {
1292 Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1293 }
1294 }
1295 pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1297 Rotation2 (LinearAuto (LinearIso (
1298 Matrix2::rotation_z (angle.0), PhantomData::default())))
1299 }
1300 pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1305 assert_eq!(mat * mat.transposed(), Matrix2::identity());
1306 assert_eq!(mat.determinant(), S::one());
1307 Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1308 }
1309 pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1314 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1315 {
1316 let four = S::one() + S::one() + S::one() + S::one();
1317 let epsilon = S::default_epsilon() * four;
1318 let max_relative = S::default_max_relative() * four;
1319 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1320 epsilon=epsilon, max_relative=max_relative);
1321 approx::assert_relative_eq!(mat.determinant(), S::one(),
1322 max_relative=max_relative);
1323 Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1324 }
1325 pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1331 debug_assert!(mat * mat.transposed() == Matrix2::identity());
1332 debug_assert!(mat.determinant() == S::one());
1333 Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1334 }
1335 pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1341 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1342 {
1343 if cfg!(debug_assertions) {
1344 let four = S::one() + S::one() + S::one() + S::one();
1345 let epsilon = S::default_epsilon() * four;
1346 let max_relative = S::default_max_relative() * four;
1347 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1348 max_relative=max_relative, epsilon=epsilon);
1349 approx::assert_relative_eq!(mat.determinant(), S::one(),
1350 max_relative=max_relative);
1351 }
1352 Rotation2 (LinearAuto (LinearIso (mat, PhantomData::default())))
1353 }
1354}
1355impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1356 type Target = Matrix2 <S>;
1357 fn deref (&self) -> &Self::Target {
1358 &self.0
1359 }
1360}
1361impl <S> MultiplicativeGroup for Rotation2 <S> where
1362 S : Ring + MaybeSerDes
1363{ }
1364impl <S> MultiplicativeMonoid for Rotation2 <S> where
1365 S : Ring + MaybeSerDes
1366{ }
1367impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1368 type Output = Self;
1369 fn inv (self) -> Self::Output {
1370 Rotation2 (LinearAuto (LinearIso (
1371 self.0.0.0.transpose(), PhantomData::default()
1372 )))
1373 }
1374}
1375impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where
1376 S : Ring + MaybeSerDes
1377{
1378 type Output = Vector2 <S>;
1379 fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1380 self.0 * rhs
1381 }
1382}
1383impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where
1384 S : Ring + MaybeSerDes
1385{
1386 type Output = Vector2 <S>;
1387 fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1388 self * rhs.0
1389 }
1390}
1391impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1392 type Output = Self;
1393 fn mul (self, rhs : Self) -> Self::Output {
1394 Rotation2 (self.0 * rhs.0)
1395 }
1396}
1397impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where
1398 S : Ring + MaybeSerDes
1399{
1400 fn mul_assign (&mut self, rhs : Self) {
1401 self.0 *= rhs.0
1402 }
1403}
1404impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1405 type Output = Self;
1406 fn div (self, rhs : Self) -> Self::Output {
1407 use num::Inv;
1408 self * rhs.inv()
1409 }
1410}
1411impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where
1412 S : Ring + MaybeSerDes
1413{
1414 fn div_assign (&mut self, rhs : Self) {
1415 use num::Inv;
1416 *self *= rhs.inv()
1417 }
1418}
1419impl <S> num::One for Rotation2 <S> where
1420 S : Ring + MaybeSerDes + num::Zero + num::One
1421{
1422 fn one() -> Self {
1423 Rotation2 (LinearAuto (
1424 LinearIso (Matrix2::identity(), PhantomData::default())))
1425 }
1426}
1427
1428impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1432 pub fn identity() -> Self {
1434 use num::One;
1435 Self::one()
1436 }
1437 pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1441 Rotation3 (LinearAuto (LinearIso (
1442 Matrix3::rotation_x (angle.0), PhantomData::default())))
1443 }
1444 pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1448 Rotation3 (LinearAuto (LinearIso (
1449 Matrix3::rotation_y (angle.0), PhantomData::default())))
1450 }
1451 pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1455 Rotation3 (LinearAuto (LinearIso (
1456 Matrix3::rotation_z (angle.0), PhantomData::default())))
1457 }
1458 pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1464 -> Self where S : num::real::Real
1465 {
1466 let rotation1 = Rotation3::from_angle_z (yaw);
1467 let rotation2 =
1468 Rotation3::from_axis_angle (rotation1.cols.x.into(), pitch) * rotation1;
1469 Rotation3::from_axis_angle (rotation2.cols.y.into(), roll) * rotation2
1470 }
1471 pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1473 S : num::real::Real
1474 {
1475 Rotation3 (LinearAuto (LinearIso (
1476 Matrix3::rotation_3d (angle.0, axis), PhantomData::default())))
1477 }
1478 pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1481 -> Option <Self> where S : Field + Sqrt
1482 {
1483 if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array))
1484 .determinant() == S::zero()
1485 {
1486 None
1487 } else {
1488 let project =
1489 |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1490 let u1 = v1;
1491 let u2 = v2 - project (u1, v2);
1492 let u3 = v3 - project (u1, v3) - project (u2, v3);
1493 Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1494 u1.normalize().into_array(),
1495 u2.normalize().into_array(),
1496 u3.normalize().into_array()
1497 ]), PhantomData::default()))))
1498 }
1499 }
1500
1501 pub fn look_at (point : Point3 <S>) -> Self where
1505 S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> +
1506 std::fmt::Debug
1507 {
1508 if point == Point::origin() {
1509 Self::identity()
1510 } else {
1511 use num::Zero;
1512 let forward = point.0.normalized();
1513 let right = {
1514 let projected = forward.with_z (S::zero());
1515 if !projected.is_zero() {
1516 Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1517 } else {
1518 Vector3::unit_x()
1519 }
1520 };
1521 let up = right.cross (forward);
1522 let mat = Matrix3::from_col_arrays (
1523 [right, forward, up].map (Vector3::into_array));
1524 Self::noisy_approx (mat)
1525 }
1526 }
1527
1528 pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1534 if mat * mat.transposed() != Matrix3::identity() ||
1535 mat.determinant() != S::one()
1536 {
1537 None
1538 } else {
1539 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1540 }
1541 }
1542 pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1548 S : approx::RelativeEq <Epsilon=S>
1549 {
1550 let four = S::one() + S::one() + S::one() + S::one();
1551 let epsilon = S::default_epsilon() * four;
1552 let max_relative = S::default_max_relative() * four;
1553 if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1554 max_relative=max_relative, epsilon=epsilon
1555 ) || approx::relative_ne!(mat.determinant(), S::one(),
1556 max_relative=max_relative
1557 ) {
1558 None
1559 } else {
1560 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default()))))
1561 }
1562 }
1563 pub fn noisy (mat : Matrix3 <S>) -> Self {
1568 assert!(mat * mat.transposed() == Matrix3::identity());
1569 assert!(mat.determinant() == S::one());
1570 Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1571 }
1572 pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1577 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1578 {
1579 let four = S::one() + S::one() + S::one() + S::one();
1580 let eight = four + S::one() + S::one() + S::one() + S::one();
1581 let epsilon = S::default_epsilon() * four;
1582 let max_relative = S::default_max_relative() * eight;
1583 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1584 max_relative=max_relative, epsilon=epsilon);
1585 approx::assert_relative_eq!(mat.determinant(), S::one(),
1586 max_relative=max_relative);
1587 Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1588 }
1589 pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1595 debug_assert!(mat * mat.transposed() == Matrix3::identity());
1596 debug_assert!(mat.determinant() == S::one());
1597 Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1598 }
1599 pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1605 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1606 {
1607 if cfg!(debug_assertions) {
1608 let four = S::one() + S::one() + S::one() + S::one();
1609 let epsilon = S::default_epsilon() * four;
1610 let max_relative = S::default_max_relative() * four;
1611 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1612 max_relative=max_relative, epsilon=epsilon);
1613 approx::assert_relative_eq!(mat.determinant(), S::one(),
1614 max_relative=max_relative);
1615 }
1616 Rotation3 (LinearAuto (LinearIso (mat, PhantomData::default())))
1617 }
1618 pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1624 let cols = &self.cols;
1625 let yaw = Rad (S::atan2 (-cols.y.x, cols.y.y));
1626 let pitch = Rad (
1627 S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z))
1628 );
1629 let roll = Rad (S::atan2 (-cols.x.z, cols.z.z));
1630
1631 (yaw, pitch, roll)
1632 }
1633
1634 pub fn versor (self) -> Versor <S> where
1638 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1639 {
1640 let diagonal = self.diagonal();
1641 let t = diagonal.sum();
1642 let m = MinMax::max (MinMax::max (MinMax::max (
1643 diagonal.x, diagonal.y), diagonal.z), t);
1644 let qmax = (S::one() / S::two()) * Sqrt::sqrt (S::one() - t + S::two() * m);
1645 let qmax4_recip = (S::four() * qmax).recip();
1646 let [qx, qy, qz, qw] : [S; 4];
1647 let cols = self.cols;
1648 if m == diagonal.x {
1649 qx = qmax;
1650 qy = qmax4_recip * (cols.x.y + cols.y.x);
1651 qz = qmax4_recip * (cols.x.z + cols.z.x);
1652 qw = -qmax4_recip * (cols.z.y - cols.y.z);
1653 } else if m == diagonal.y {
1654 qx = qmax4_recip * (cols.x.y + cols.y.x);
1655 qy = qmax;
1656 qz = qmax4_recip * (cols.y.z + cols.z.y);
1657 qw = -qmax4_recip * (cols.x.z - cols.z.x);
1658 } else if m == diagonal.z {
1659 qx = qmax4_recip * (cols.x.z + cols.z.x);
1660 qy = qmax4_recip * (cols.y.z + cols.z.y);
1661 qz = qmax;
1662 qw = -qmax4_recip * (cols.y.x - cols.x.y);
1663 } else {
1664 qx = -qmax4_recip * (cols.z.y - cols.y.z);
1665 qy = -qmax4_recip * (cols.x.z - cols.z.x);
1666 qz = -qmax4_recip * (cols.y.x - cols.x.y);
1667 qw = qmax;
1668 }
1669 let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1670 Versor::unchecked_approx (quat)
1671 }
1672}
1673impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1674 type Target = Matrix3 <S>;
1675 fn deref (&self) -> &Self::Target {
1676 &self.0
1677 }
1678}
1679impl <S> MultiplicativeGroup for Rotation3 <S> where S : Ring + MaybeSerDes { }
1680impl <S> MultiplicativeMonoid for Rotation3 <S> where S : Ring + MaybeSerDes { }
1681impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1682 type Output = Self;
1683 fn inv (self) -> Self::Output {
1684 Rotation3 (LinearAuto (LinearIso (
1685 self.0.0.0.transpose(), PhantomData::default()
1686 )))
1687 }
1688}
1689impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where
1690 S : Ring + MaybeSerDes
1691{
1692 type Output = Vector3 <S>;
1693 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1694 self.0 * rhs
1695 }
1696}
1697impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where
1698 S : Ring + MaybeSerDes
1699{
1700 type Output = Vector3 <S>;
1701 fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1702 self * rhs.0
1703 }
1704}
1705impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1706 type Output = Self;
1707 fn mul (self, rhs : Self) -> Self::Output {
1708 Rotation3 (self.0 * rhs.0)
1709 }
1710}
1711impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where
1712 S : Ring + MaybeSerDes
1713{
1714 fn mul_assign (&mut self, rhs : Self) {
1715 self.0 *= rhs.0
1716 }
1717}
1718impl <S> std::ops::Div for Rotation3 <S> where S : Ring + MaybeSerDes {
1719 type Output = Self;
1720 fn div (self, rhs : Self) -> Self::Output {
1721 use num::Inv;
1722 self * rhs.inv()
1723 }
1724}
1725impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where
1726 S : Ring + MaybeSerDes
1727{
1728 fn div_assign (&mut self, rhs : Self) {
1729 use num::Inv;
1730 *self *= rhs.inv()
1731 }
1732}
1733impl <S> num::One for Rotation3 <S> where
1734 S : Ring + MaybeSerDes + num::Zero + num::One
1735{
1736 fn one() -> Self {
1737 Rotation3 (LinearAuto (
1738 LinearIso (Matrix3::identity(), PhantomData::default())))
1739 }
1740}
1741impl <S> From <Angles3 <S>> for Rotation3 <S> where
1742 S : Real + MaybeSerDes + num::real::Real
1743{
1744 fn from (angles : Angles3 <S>) -> Self {
1745 Rotation3::from_angles_intrinsic (
1746 angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1747 }
1748}
1749
1750
1751impl <S : Real> Versor <S> {
1755 pub fn normalize (quaternion : Quaternion <S>) -> Self where
1759 S : std::fmt::Debug
1760 {
1761 assert_ne!(quaternion, Quaternion::zero());
1762 Versor (normalize_quaternion (quaternion))
1763 }
1764 pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
1768 S : std::fmt::Debug
1769 {
1770 assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1771 Versor (unit_quaternion)
1772 }
1773 pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1777 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1778 {
1779 assert!(unit_quaternion.into_vec4().is_normalized());
1780 Versor (unit_quaternion)
1781 }
1782 pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where
1786 S : std::fmt::Debug
1787 {
1788 debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1789 Versor (unit_quaternion)
1790 }
1791 pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1795 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1796 {
1797 debug_assert!(unit_quaternion.into_vec4().is_normalized());
1798 Versor (unit_quaternion)
1799 }
1800 pub fn from_scaled_axis (scaled_axis : &Vector3 <S>) -> Self where
1804 S : std::fmt::Debug + num::Float
1805 {
1806 if *scaled_axis == Vector3::zero() {
1807 let versor = Quaternion::rotation_3d (S::zero(), *scaled_axis);
1808 debug_assert_eq!(versor.magnitude(), S::one());
1809 Versor (versor)
1810 } else {
1811 let angle = scaled_axis.magnitude();
1812 debug_assert!(S::zero() < angle);
1813 let axis = *scaled_axis / angle;
1814 Versor (Quaternion::rotation_3d (angle, axis))
1815 }
1816 }
1817}
1818impl <S> From <Rotation3 <S>> for Versor <S> where
1819 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1820{
1821 fn from (rot : Rotation3 <S>) -> Self {
1822 rot.versor()
1823 }
1824}
1825impl <S : Real> std::ops::Deref for Versor <S> {
1826 type Target = Quaternion <S>;
1827 fn deref (&self) -> &Quaternion <S> {
1828 &self.0
1829 }
1830}
1831impl <S, A, B, M> AffineMap <S, A, B, M> where
1837 A : AffineSpace <S>,
1838 B : AffineSpace <S>,
1839 M : LinearMap <S, A::Vector, B::Vector>,
1840 S : Field + std::fmt::Display,
1841 B::Vector : std::fmt::Display
1842{
1843 pub fn new (linear_map : M, translation : B::Vector) -> Self {
1844 AffineMap { linear_map, translation, _phantom: PhantomData::default() }
1845 }
1846 pub fn transform (self, point : A::Point) -> B::Point {
1847 B::Point::from_vector (
1848 self.linear_map * point.to_vector() + self.translation)
1849 }
1850}
1851
1852impl <S, V, W, M> LinearIso <S, V, W, M> where
1856 M : LinearMap <S, V, W> + Copy,
1857 V : Module <S>,
1858 W : Module <S>,
1859 S : Ring
1860{
1861 pub fn is_invertible (linear_map : M) -> bool {
1863 linear_map.determinant() != S::zero()
1864 }
1865 pub fn is_invertible_approx (linear_map : M) -> bool where
1867 S : approx::RelativeEq <Epsilon=S>
1868 {
1869 let four = S::one() + S::one() + S::one() + S::one();
1870 let epsilon = S::default_epsilon() * four;
1871 let max_relative = S::default_max_relative() * four;
1872 approx::relative_ne!(linear_map.determinant(), S::zero(),
1873 max_relative=max_relative, epsilon=epsilon)
1874 }
1875 pub fn new (linear_map : M) -> Option <Self> {
1877 if Self::is_invertible (linear_map) {
1878 Some (LinearIso (linear_map, PhantomData::default()))
1879 } else {
1880 None
1881 }
1882 }
1883 pub fn new_approx (linear_map : M) -> Option <Self> where
1885 S : approx::RelativeEq <Epsilon=S>
1886 {
1887 if Self::is_invertible_approx (linear_map) {
1888 Some (LinearIso (linear_map, PhantomData::default()))
1889 } else {
1890 None
1891 }
1892 }
1893}
1894impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1895 M : LinearMap <S, V, W>,
1896 V : Module <S>,
1897 W : Module <S>,
1898 S : Ring
1899{
1900 type Target = M;
1901 fn deref (&self) -> &Self::Target {
1902 &self.0
1903 }
1904}
1905impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1906 V : Module <S>,
1907 S : Ring
1908{
1909 fn one () -> Self {
1910 LinearIso (V::LinearEndo::one(), PhantomData::default())
1911 }
1912}
1913impl <S, V, W, M> std::ops::Mul <V> for LinearIso <S, V, W, M> where
1914 M : LinearMap <S, V, W>,
1915 V : Module <S>,
1916 W : Module <S>,
1917 S : Ring
1918{
1919 type Output = W;
1920 fn mul (self, rhs : V) -> Self::Output {
1921 self.0 * rhs
1922 }
1923}
1924impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1925 V : Module <S>,
1926 S : Ring
1927{
1928 type Output = Self;
1929 fn mul (self, rhs : Self) -> Self::Output {
1930 LinearIso (self.0 * rhs.0, PhantomData::default())
1931 }
1932}
1933impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1934 V : Module <S>,
1935 S : Ring
1936{
1937 fn mul_assign (&mut self, rhs : Self) {
1938 self.0 *= rhs.0
1939 }
1940}
1941
1942impl <S, V> LinearAuto <S, V> where
1946 V : Module <S>,
1947 V::LinearEndo : MaybeSerDes,
1948 S : Ring
1949{
1950 pub fn is_orthonormal (&self) -> bool {
1956 use num::One;
1957 let determinant = self.0.0.determinant();
1958 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1959 (determinant == S::one() || determinant == -S::one())
1960 }
1961 pub fn is_orthonormal_approx (&self) -> bool where
1967 S : approx::RelativeEq <Epsilon=S>,
1968 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1969 {
1970 use num::One;
1971 let four = S::one() + S::one() + S::one() + S::one();
1972 let epsilon = S::default_epsilon() * four;
1973 let max_relative = S::default_max_relative() * four;
1974 let determinant = self.0.0.determinant();
1975 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1976 max_relative=max_relative, epsilon=epsilon) &&
1977 ( approx::relative_eq!(determinant, S::one(), max_relative=max_relative) ||
1978 approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
1979 }
1980 pub fn is_rotation (&self) -> bool {
1985 use num::One;
1986 let determinant = self.0.0.determinant();
1987 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1988 determinant == S::one()
1989 }
1990 pub fn is_rotation_approx (&self) -> bool where
1995 S : approx::RelativeEq <Epsilon=S>,
1996 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1997 {
1998 use num::One;
1999 let four = S::one() + S::one() + S::one() + S::one();
2000 let epsilon = S::default_epsilon() * four;
2001 let max_relative = S::default_max_relative() * four;
2002 let determinant = self.0.0.determinant();
2003 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
2004 max_relative=max_relative, epsilon=epsilon) &&
2005 approx::relative_eq!(determinant, S::one(), max_relative=max_relative)
2006 }
2007}
2008impl <S, V> MultiplicativeMonoid for LinearAuto <S, V> where
2009 V : Module <S>,
2010 V::LinearEndo : MaybeSerDes + PartialEq,
2011 S : Ring
2012{ }
2013impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
2014 V : Module <S>,
2015 V::LinearEndo : MaybeSerDes,
2016 S : Ring
2017{
2018 type Output = V;
2019 fn mul (self, rhs : V) -> Self::Output {
2020 self.0 * rhs
2021 }
2022}
2023impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2024 V : Module <S>,
2025 V::LinearEndo : MaybeSerDes,
2026 S : Ring
2027{
2028 type Output = Self;
2029 fn mul (self, rhs : Self) -> Self::Output {
2030 LinearAuto (self.0 * rhs.0)
2031 }
2032}
2033impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2034 V : Module <S>,
2035 V::LinearEndo : MaybeSerDes,
2036 S : Ring
2037{
2038 fn mul_assign (&mut self, rhs : Self) {
2039 self.0 *= rhs.0
2040 }
2041}
2042impl <S, V> num::One for LinearAuto <S, V> where
2043 V : Module <S>,
2044 V::LinearEndo : MaybeSerDes,
2045 S : Ring
2046{
2047 fn one() -> Self {
2048 LinearAuto (LinearIso::one())
2049 }
2050}
2051
2052impl <S, A, B, M> Affinity <S, A, B, M> where
2056 M : LinearMap <S, A::Vector, B::Vector>,
2057 A : AffineSpace <S>,
2058 B : AffineSpace <S>,
2059 S : Field + std::fmt::Display,
2060 B::Vector : std::fmt::Display
2061{
2062 pub fn new (
2063 linear_iso : LinearIso <S, A::Vector, B::Vector, M>,
2064 translation : B::Vector
2065 ) -> Self {
2066 Affinity { linear_iso, translation, _phantom: PhantomData::default() }
2067 }
2068}
2069
2070impl <S, V, W, P, Q, M> Projectivity <S, V, W, P, Q, M> where
2074 M : LinearMap <S, P, Q>,
2075 P : ProjectiveSpace <S, V>,
2076 Q : ProjectiveSpace <S, W>,
2077 V : VectorSpace <S> + std::fmt::Display,
2078 W : VectorSpace <S> + std::fmt::Display,
2079 S : Field + std::fmt::Display
2080{
2081 pub fn new (linear_iso : LinearIso <S, P, Q, M>) -> Self {
2082 Projectivity (linear_iso, PhantomData::default())
2083 }
2084 pub fn transform (self, vector : P) -> Q {
2085 **self * vector
2086 }
2087}
2088impl <S, V, W, P, Q, M> std::ops::Deref for Projectivity <S, V, W, P, Q, M> where
2089 M : LinearMap <S, P, Q>,
2090 P : ProjectiveSpace <S, V>,
2091 Q : ProjectiveSpace <S, W>,
2092 V : VectorSpace <S> + std::fmt::Display,
2093 W : VectorSpace <S> + std::fmt::Display,
2094 S : Field + std::fmt::Display
2095{
2096 type Target = LinearIso <S, P, Q, M>;
2097 fn deref (&self) -> &Self::Target {
2098 &self.0
2099 }
2100}
2101
2102macro_rules! impl_angle {
2103 ( $angle:ident, $docname:expr ) => {
2104 #[doc = $docname]
2105 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2106 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2108 pub struct $angle <S> (pub S);
2109 impl_numcast_primitive!($angle);
2110 impl <S : Real> AdditiveGroup for $angle <S> { }
2111 impl <S : Real> AdditiveMonoid for $angle <S> { }
2112 impl <S : Ring> std::ops::Neg for $angle <S> {
2113 type Output = Self;
2114 fn neg (self) -> Self::Output {
2115 $angle (-self.0)
2116 }
2117 }
2118 impl <S : Ring> std::ops::Add for $angle <S> {
2119 type Output = Self;
2120 fn add (self, other : Self) -> Self::Output {
2121 $angle (self.0 + other.0)
2122 }
2123 }
2124 impl <S : Ring> std::ops::AddAssign for $angle <S> {
2125 fn add_assign (&mut self, other : Self) {
2126 self.0 += other.0
2127 }
2128 }
2129 impl <S : Ring> std::ops::Sub for $angle <S> {
2130 type Output = Self;
2131 fn sub (self, other : Self) -> Self::Output {
2132 $angle (self.0 - other.0)
2133 }
2134 }
2135 impl <S : Ring> std::ops::SubAssign for $angle <S> {
2136 fn sub_assign (&mut self, other : Self) {
2137 self.0 -= other.0
2138 }
2139 }
2140 impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2141 type Output = Self;
2142 fn mul (self, scalar : S) -> Self::Output {
2143 $angle (scalar * self.0)
2144 }
2145 }
2146 impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2147 fn mul_assign (&mut self, scalar : S) {
2148 self.0 *= scalar
2149 }
2150 }
2151 impl <S : Ring> std::ops::Div for $angle <S> {
2152 type Output = S;
2153 fn div (self, other : Self) -> Self::Output {
2154 self.0 / other.0
2155 }
2156 }
2157 impl <S : Ring> std::ops::Div <S> for $angle <S> {
2158 type Output = Self;
2159 fn div (self, scalar : S) -> Self::Output {
2160 $angle (self.0 / scalar)
2161 }
2162 }
2163 impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2164 fn div_assign (&mut self, scalar : S) {
2165 self.0 /= scalar
2166 }
2167 }
2168 impl <S : Ring> std::ops::Rem for $angle <S> {
2169 type Output = Self;
2170 fn rem (self, other : Self) -> Self::Output {
2171 $angle (self.0 % other.0)
2172 }
2173 }
2174 impl <S : Ring> num::Zero for $angle <S> {
2175 fn zero() -> Self {
2176 $angle (S::zero())
2177 }
2178 fn is_zero (&self) -> bool {
2179 self.0.is_zero()
2180 }
2181 }
2182 }
2183}
2184
2185macro_rules! impl_angle_wrapped {
2186 ( $angle:ident, $comment:expr ) => {
2187 #[doc = $comment]
2188 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2189 #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
2190 pub struct $angle <S> (Rad <S>);
2191
2192 impl_numcast!($angle);
2193 impl <S : Real> $angle <S> {
2194 pub fn angle (&self) -> Rad <S> {
2195 self.0
2196 }
2197 }
2198 impl <S : Real> AdditiveGroup for $angle <S> { }
2199 impl <S : Real> AdditiveMonoid for $angle <S> { }
2200 impl <S : Real> std::ops::Neg for $angle <S> {
2201 type Output = Self;
2202 fn neg (self) -> Self::Output {
2203 self.map (Rad::neg)
2204 }
2205 }
2206 impl <S : Real> std::ops::Add for $angle <S> {
2207 type Output = Self;
2208 fn add (self, other : Self) -> Self::Output {
2209 self.map (|angle| angle + other.0)
2210 }
2211 }
2212 impl <S : Real> std::ops::AddAssign for $angle <S> {
2213 fn add_assign (&mut self, other : Self) {
2214 *self = *self + other
2215 }
2216 }
2217 impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2218 type Output = Self;
2219 fn add (self, angle : Rad <S>) -> Self::Output {
2220 self.map (|a| a + angle)
2221 }
2222 }
2223 impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2224 fn add_assign (&mut self, angle : Rad <S>) {
2225 *self = *self + angle
2226 }
2227 }
2228 impl <S : Real> std::ops::Sub for $angle <S> {
2229 type Output = Self;
2230 fn sub (self, other : Self) -> Self::Output {
2231 self.map (|angle| angle - other.0)
2232 }
2233 }
2234 impl <S : Real> std::ops::SubAssign for $angle <S> {
2235 fn sub_assign (&mut self, other : Self) {
2236 *self = *self - other
2237 }
2238 }
2239 impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2240 type Output = Self;
2241 fn sub (self, angle : Rad <S>) -> Self::Output {
2242 self.map (|a| a - angle)
2243 }
2244 }
2245 impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2246 fn sub_assign (&mut self, angle : Rad <S>) {
2247 *self = *self - angle
2248 }
2249 }
2250 impl <S : Real> std::ops::Mul <S> for $angle <S> {
2251 type Output = Self;
2252 fn mul (self, scalar : S) -> Self::Output {
2253 self.map (|angle| angle * scalar)
2254 }
2255 }
2256 impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2257 fn mul_assign (&mut self, scalar : S) {
2258 *self = *self * scalar
2259 }
2260 }
2261 impl <S : Real> std::ops::Div for $angle <S> {
2262 type Output = S;
2263 fn div (self, other : Self) -> Self::Output {
2264 self.0 / other.0
2265 }
2266 }
2267 impl <S : Real> std::ops::Div <S> for $angle <S> {
2268 type Output = Self;
2269 fn div (self, scalar : S) -> Self::Output {
2270 self.map (|angle| angle / scalar)
2271 }
2272 }
2273 impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2274 fn div_assign (&mut self, scalar : S) {
2275 *self = *self / scalar
2276 }
2277 }
2278 impl <S : Real> std::ops::Rem for $angle <S> {
2279 type Output = Self;
2280 fn rem (self, other : Self) -> Self::Output {
2281 self.map (|angle| angle % other.0)
2282 }
2283 }
2284 impl <S : Real> num::Zero for $angle <S> {
2285 fn zero() -> Self {
2286 $angle (Rad::zero())
2287 }
2288 fn is_zero (&self) -> bool {
2289 self.0.is_zero()
2290 }
2291 }
2292 }
2293}
2294
2295macro_rules! impl_dimension {
2296 ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2297 [$($component:ident),+],
2298 [$(($axis_method:ident, $unit_method:ident)),+], [$($projective:ident)?],
2299 $matrix:ident, $affine:ident, $euclidean:ident, $ndims:expr, $dimension:expr
2300 ) => {
2301 #[doc = $dimension]
2302 #[doc = "position"]
2303 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2304 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2305 #[display("{}", _0)]
2306 #[repr(C)]
2307 pub struct $point <S> (pub $vector <S>);
2308
2309 #[doc = $dimension]
2310 #[doc = "affine space"]
2311 #[derive(Debug)]
2312 pub struct $affine <S> (PhantomData <S>);
2313 impl <S : Field> AffineSpace <S> for $affine <S> {
2314 type Point = $point <S>;
2315 type Vector = $vector <S>;
2316 }
2317
2318 #[doc = $dimension]
2319 #[doc = "euclidean space"]
2320 #[derive(Debug)]
2321 pub struct $euclidean <S> (PhantomData <S>);
2322 impl <S : Real> EuclideanSpace <S> for $euclidean <S> { }
2323 impl <S : Real> AffineSpace <S> for $euclidean <S> {
2324 type Point = $point <S>;
2325 type Vector = $vector <S>;
2326 }
2327
2328 #[doc = $dimension]
2329 #[doc = "non-zero vector"]
2330 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2331 #[derive(Clone, Copy, Debug, PartialEq, Display)]
2332 #[display("{}", _0)]
2333 #[repr(C)]
2334 pub struct $nonzero <S> ($vector <S>);
2335
2336 #[doc = $dimension]
2337 #[doc = "unit vector"]
2338 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2339 #[derive(Clone, Copy, Debug, PartialEq, Display)]
2340 #[display("{}", _0)]
2341 #[repr(C)]
2342 pub struct $unit <S> ($vector <S>);
2343
2344 impl_numcast!($point);
2348 impl <S> $point <S> {
2349 pub const fn new ($($component : S),+) -> Self {
2350 $point ($vector::new ($($component),+))
2351 }
2352 }
2353 impl <S> Point <$vector <S>> for $point <S> where S : Ring {
2354 fn to_vector (self) -> $vector <S> {
2355 self.0
2356 }
2357 fn from_vector (vector : $vector <S>) -> Self {
2358 $point (vector)
2359 }
2360 }
2361 impl <S> From<[S; $ndims]> for $point <S> {
2362 fn from (array : [S; $ndims]) -> Self {
2363 $point (array.into())
2364 }
2365 }
2366 impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2367 type Output = Self;
2368 fn add (self, displacement : $vector <S>) -> Self::Output {
2369 $point (self.0 + displacement)
2370 }
2371 }
2372 impl <S> std::ops::Add <&$vector <S>> for $point <S> where
2373 S : AdditiveGroup + Copy
2374 {
2375 type Output = Self;
2376 fn add (self, displacement : &$vector <S>) -> Self::Output {
2377 $point (self.0 + *displacement)
2378 }
2379 }
2380 impl <S> std::ops::Add <$vector <S>> for &$point <S> where
2381 S : AdditiveGroup + Copy
2382 {
2383 type Output = $point <S>;
2384 fn add (self, displacement : $vector <S>) -> Self::Output {
2385 $point (self.0 + displacement)
2386 }
2387 }
2388 impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2389 S : AdditiveGroup + Copy
2390 {
2391 type Output = $point <S>;
2392 fn add (self, displacement : &$vector <S>) -> Self::Output {
2393 $point (self.0 + *displacement)
2394 }
2395 }
2396 impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where
2397 S : AdditiveGroup
2398 {
2399 fn add_assign (&mut self, displacement : $vector <S>) {
2400 self.0 += displacement
2401 }
2402 }
2403 impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2404 S : AdditiveGroup + Copy
2405 {
2406 fn add_assign (&mut self, displacement : &$vector <S>) {
2407 self.0 += *displacement
2408 }
2409 }
2410 impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2411 type Output = Self;
2412 fn sub (self, displacement : $vector <S>) -> Self::Output {
2413 $point (self.0 - displacement)
2414 }
2415 }
2416 impl <S> std::ops::Sub <&$vector <S>> for $point <S> where
2417 S : AdditiveGroup + Copy
2418 {
2419 type Output = Self;
2420 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2421 $point (self.0 - *displacement)
2422 }
2423 }
2424 impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2425 type Output = $vector <S>;
2426 fn sub (self, other : Self) -> Self::Output {
2427 self.0 - other.0
2428 }
2429 }
2430 impl <S> std::ops::Sub <&$point <S>> for $point <S> where
2431 S : AdditiveGroup + Copy
2432 {
2433 type Output = $vector <S>;
2434 fn sub (self, other : &Self) -> Self::Output {
2435 self.0 - other.0
2436 }
2437 }
2438 impl <S> std::ops::Sub <$vector <S>> for &$point <S> where
2439 S : AdditiveGroup + Copy
2440 {
2441 type Output = $point <S>;
2442 fn sub (self, displacement : $vector <S>) -> Self::Output {
2443 $point (self.0 - displacement)
2444 }
2445 }
2446 impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2447 S : AdditiveGroup + Copy
2448 {
2449 type Output = $point <S>;
2450 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2451 $point (self.0 - *displacement)
2452 }
2453 }
2454 impl <S> std::ops::Sub <$point <S>> for &$point <S> where
2455 S : AdditiveGroup + Copy
2456 {
2457 type Output = $vector <S>;
2458 fn sub (self, other : $point <S>) -> Self::Output {
2459 self.0 - other.0
2460 }
2461 }
2462 impl <S> std::ops::Sub <&$point <S>> for &$point <S> where
2463 S : AdditiveGroup + Copy
2464 {
2465 type Output = $vector <S>;
2466 fn sub (self, other : &$point <S>) -> Self::Output {
2467 self.0 - other.0
2468 }
2469 }
2470 impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2471 S : AdditiveGroup
2472 {
2473 fn sub_assign (&mut self, displacement : $vector <S>) {
2474 self.0 -= displacement
2475 }
2476 }
2477 impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2478 S : AdditiveGroup + Copy
2479 {
2480 fn sub_assign (&mut self, displacement : &$vector <S>) {
2481 self.0 -= *displacement
2482 }
2483 }
2484 impl <S> approx::AbsDiffEq for $point <S> where
2485 S : approx::AbsDiffEq,
2486 S::Epsilon : Copy
2487 {
2488 type Epsilon = S::Epsilon;
2489 fn default_epsilon() -> Self::Epsilon {
2490 S::default_epsilon()
2491 }
2492 #[inline]
2493 fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2494 self.0.abs_diff_eq (&other.0, epsilon)
2495 }
2496 }
2497 impl <S> approx::RelativeEq for $point <S> where
2498 S : approx::RelativeEq,
2499 S::Epsilon : Copy
2500 {
2501 fn default_max_relative() -> Self::Epsilon {
2502 S::default_max_relative()
2503 }
2504 #[inline]
2505 fn relative_eq (&self,
2506 other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2507 ) -> bool {
2508 self.0.relative_eq (&other.0, epsilon, max_relative)
2509 }
2510 }
2511 impl <S> approx::UlpsEq for $point <S> where
2512 S : approx::UlpsEq,
2513 S::Epsilon : Copy
2514 {
2515 fn default_max_ulps() -> u32 {
2516 S::default_max_ulps()
2517 }
2518 #[inline]
2519 fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2520 -> bool
2521 {
2522 self.0.ulps_eq (&other.0, epsilon, max_ulps)
2523 }
2524 }
2525 impl <S : Field> InnerProductSpace <S> for $vector <S> { }
2529 impl <S : Ring> Dot <S> for $vector <S> {
2530 fn dot (self, other : Self) -> S {
2531 self.dot (other)
2532 }
2533 }
2534 impl <S : Field> VectorSpace <S> for $vector <S> {
2535 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2536 self.map (f)
2537 }
2538 }
2539 impl <S : Ring> Module <S> for $vector <S> {
2540 type LinearEndo = $matrix <S>;
2541 }
2542 impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2543 fn determinant (self) -> S {
2544 self.determinant()
2545 }
2546 fn transpose (self) -> Self {
2547 self.transposed()
2548 }
2549 }
2550 impl <S : Ring> MultiplicativeMonoid for $matrix <S> { }
2551 impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2552 fn action (self, point : $point <S>) -> $point <S> {
2553 point + self
2554 }
2555 }
2556 impl <S : Ring> AdditiveGroup for $vector <S> { }
2557 impl <S : Ring> AdditiveMonoid for $vector <S> { }
2558 impl <S : AdditiveGroup> Group for $vector <S> {
2559 fn identity() -> Self {
2560 Self::zero()
2561 }
2562 fn operation (a : Self, b : Self) -> Self {
2563 a + b
2564 }
2565 }
2566 impl <S> Point <$vector <S>> for $vector <S> where S : Ring {
2567 fn to_vector (self) -> $vector <S> {
2568 self
2569 }
2570 fn from_vector (vector : $vector <S>) -> Self {
2571 vector
2572 }
2573 }
2574 impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2575 S : Ring + MaybeSerDes
2576 {
2577 type Output = Self;
2578 fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2579 self * rhs.0
2580 }
2581 }
2582 impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for
2583 $vector <S>
2584 where
2585 S : Ring + MaybeSerDes
2586 {
2587 type Output = Self;
2588 fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>)
2589 -> Self::Output
2590 {
2591 self * rhs.0
2592 }
2593 }
2594 impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2595 S : Ring + num::Float + MaybeSerDes
2596 {
2597 type Output = Self;
2598 fn inv (self) -> Self::Output {
2599 LinearAuto (self.0.inv())
2600 }
2601 }
2602 impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2603 S : Ring + num::Float + MaybeSerDes
2604 {
2605 type Output = Self;
2606 fn div (self, rhs : Self) -> Self::Output {
2607 LinearAuto (self.0 / rhs.0)
2608 }
2609 }
2610 impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2611 S : Ring + num::Float + MaybeSerDes
2612 {
2613 fn div_assign (&mut self, rhs : Self) {
2614 self.0 /= rhs.0
2615 }
2616 }
2617 impl <S> MultiplicativeGroup for LinearAuto <S, $vector <S>> where
2618 S : Ring + num::Float + MaybeSerDes
2619 { }
2620 $(
2622 impl <S> ProjectiveSpace <S, $vector <S>> for $projective <S> where
2623 S : Field + std::fmt::Display
2624 {
2625 fn homography <A> (
2626 affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
2627 ) -> Projectivity <
2628 S, $vector <S>, $vector <S>, Self, Self, Self::LinearEndo
2629 > where
2630 A : AffineSpace <S, Vector=$vector <S>>
2631 {
2632 Projectivity::new (
2633 LinearIso::<S, Self, Self, Self::LinearEndo>::new (
2634 (*affinity.linear_iso).into()
2635 ).unwrap()
2636 )
2637 }
2638 fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>)
2639 -> Self
2640 where
2641 A : AffineSpace <S, Vector=$vector <S>>,
2642 $vector <S> : GroupAction <A::Point>
2643 {
2644 match point_or_vector {
2645 Either::Left (point) => (point.to_vector(), S::one()).into(),
2646 Either::Right (vector) => (vector, S::zero()).into(),
2647 }
2648 }
2649 }
2650 )?
2651 impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2655 V : Module <S>,
2656 W : Module <S>,
2657 S : Ring + num::Float
2658 {
2659 type Output = LinearIso <S, W, V, $matrix <S>>;
2660 fn inv (self) -> Self::Output {
2661 let mat4 = Matrix4::from (self.0);
2663 LinearIso (mat4.inverted().into(), PhantomData::default())
2664 }
2665 }
2666 impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2667 V : Module <S, LinearEndo=$matrix <S>>,
2668 S : Ring + num::Float
2669 {
2670 type Output = Self;
2671 fn div (self, rhs : Self) -> Self::Output {
2672 use num::Inv;
2673 self * rhs.inv()
2674 }
2675 }
2676 impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2677 V : Module <S, LinearEndo=$matrix <S>>,
2678 S : Ring + num::Float
2679 {
2680 fn div_assign (&mut self, rhs : Self) {
2681 use num::Inv;
2682 *self *= rhs.inv()
2683 }
2684 }
2685 impl_numcast!($nonzero);
2689 impl <S : Ring> $nonzero <S> {
2690 pub fn new (vector : $vector <S>) -> Option <Self> {
2700 use num::Zero;
2701 if !vector.is_zero() {
2702 Some ($nonzero (vector))
2703 } else {
2704 None
2705 }
2706 }
2707 pub fn noisy (vector : $vector <S>) -> Self {
2716 use num::Zero;
2717 assert!(!vector.is_zero());
2718 $nonzero (vector)
2719 }
2720 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2733 Self::noisy (fun (self.0))
2734 }
2735 }
2736 impl <S : Ring> std::ops::Deref for $nonzero <S> {
2737 type Target = $vector <S>;
2738 fn deref (&self) -> &$vector <S> {
2739 &self.0
2740 }
2741 }
2742 impl_numcast!($unit);
2746 impl <S : Real> $unit <S> {
2747 $(
2753 #[inline]
2754 pub fn $axis_method() -> Self {
2755 $unit ($vector::$unit_method())
2756 }
2757 )+
2758 pub fn new (vector : $vector <S>) -> Option <Self> {
2762 let normalized = vector.normalize();
2763 if vector == normalized {
2764 Some ($unit (vector))
2765 } else {
2766 None
2767 }
2768 }
2769 pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2775 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2776 {
2777 if vector.is_normalized() {
2778 Some ($unit (vector))
2779 } else {
2780 None
2781 }
2782 }
2783 pub fn normalize (vector : $vector <S>) -> Self {
2804 use num::Zero;
2805 assert!(!vector.is_zero());
2806 $unit (vector.normalize())
2807 }
2808 pub fn normalize_approx (vector : $vector <S>) -> Self where
2811 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2812 {
2813 use num::Zero;
2814 assert!(!vector.is_zero());
2815 let vector = if vector.is_normalized() {
2816 vector
2817 } else {
2818 vector.normalize()
2819 };
2820 $unit (vector)
2821 }
2822 pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2831 assert_eq!(vector, vector.normalize());
2832 $unit (vector)
2833 }
2834 pub fn noisy_approx (vector : $vector <S>) -> Self where
2843 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2844 {
2845 assert!(vector.is_normalized());
2846 $unit (vector)
2847 }
2848 #[inline]
2852 pub fn unchecked (vector : $vector <S>) -> Self where
2853 S : std::fmt::Debug
2854 {
2855 debug_assert_eq!(vector, vector.normalize());
2856 $unit (vector)
2857 }
2858 #[inline]
2867 pub fn unchecked_approx (vector : $vector <S>) -> Self where
2868 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2869 {
2870 debug_assert!(vector.is_normalized());
2871 $unit (vector)
2872 }
2873 pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2875 S : rand::distr::uniform::SampleUniform
2876 {
2877 let vector = $vector {
2878 $($component: rng.random_range (-S::one()..S::one())),+
2879 };
2880 $unit (vector.normalize())
2881 }
2882 pub fn invert (mut self) -> Self {
2885 self.0 = -self.0;
2886 self
2887 }
2888 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>)
2901 -> Self
2902 where
2903 S : std::fmt::Debug
2904 {
2905 Self::noisy (fun (self.0))
2906 }
2907 pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>)
2920 -> Self
2921 where
2922 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2923 {
2924 Self::noisy_approx (fun (self.0))
2925 }
2926 }
2927 impl <S : Real> std::ops::Deref for $unit <S> {
2928 type Target = $vector <S>;
2929 fn deref (&self) -> &$vector <S> {
2930 &self.0
2931 }
2932 }
2933 impl <S : Real> std::ops::Neg for $unit <S> {
2934 type Output = Self;
2935 fn neg (self) -> Self::Output {
2936 Self (-self.0)
2937 }
2938 }
2939 }
2941}
2942
2943macro_rules! impl_numcast {
2944 ($type:ident) => {
2945 impl <S> $type <S> {
2946 #[inline]
2947 pub fn numcast <T> (self) -> Option <$type <T>> where
2948 S : num::NumCast,
2949 T : num::NumCast
2950 {
2951 self.0.numcast().map ($type)
2952 }
2953 }
2954 }
2955}
2956
2957macro_rules! impl_numcast_primitive {
2958 ($type:ident) => {
2959 impl <S> $type <S> {
2960 #[inline]
2961 pub fn numcast <T> (self) -> Option <$type <T>> where
2962 S : num::NumCast,
2963 T : num::NumCast
2964 {
2965 T::from (self.0).map ($type)
2966 }
2967 }
2968 }
2969}
2970
2971#[macro_export]
2972macro_rules! impl_numcast_fields {
2973 ($type:ident, $($field:ident),+) => {
2974 impl <S> $type <S> {
2975 #[inline]
2976 pub fn numcast <T> (self) -> Option <$type <T>> where
2977 S : num::NumCast,
2978 T : num::NumCast
2979 {
2980 Some ($type {
2981 $(
2982 $field: self.$field.numcast()?
2983 ),+
2984 })
2985 }
2986 }
2987 }
2988}
2989
2990impl_angle!(Deg, "Degrees");
2991impl_angle!(Rad, "Radians");
2992impl_angle!(Turn, "Turns");
2993impl_angle_wrapped!(AngleWrapped,
2994 "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
2995impl_angle_wrapped!(AngleWrappedSigned,
2996 "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
2997
2998impl_dimension!(Point2, Vector2, NonZero2, Unit2,
2999 [x, y],
3000 [(axis_x, unit_x), (axis_y, unit_y)], [Vector3], Matrix2, Affine2, Euclidean2,
3001 2, "2D");
3002impl_dimension!(Point3, Vector3, NonZero3, Unit3,
3003 [x, y, z],
3004 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3005 [Vector4], Matrix3, Affine3, Euclidean3, 3, "3D");
3006impl_dimension!(Point4, Vector4, NonZero4, Unit4,
3007 [x, y, z, w],
3008 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3009 [], Matrix4, Affine4, Euclidean4, 4, "4D");
3010
3011impl_numcast_primitive!(Positive);
3012impl_numcast_primitive!(NonNegative);
3013impl_numcast_primitive!(NonZero);
3014impl_numcast_primitive!(Normalized);
3015impl_numcast_primitive!(NormalSigned);
3016
3017#[inline]
3021fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>)
3022 -> Quaternion <S>
3023{
3024 Quaternion::from_vec4 (quaternion.into_vec4().normalize())
3025}
3026
3027#[cfg(test)]
3028mod tests {
3029 use super::*;
3030 use crate::num_traits;
3031 use approx;
3032 use rand;
3033 use rand_xorshift;
3034
3035 #[test]
3036 fn defaults() {
3037 use num_traits::Zero;
3038
3039 assert_eq!(Positive::<f32>::default().0, 0.0);
3040 assert_eq!(NonNegative::<f32>::default().0, 0.0);
3041 assert_eq!(Normalized::<f32>::default().0, 0.0);
3042 assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3043 assert_eq!(Deg::<f32>::default().0, 0.0);
3044 assert_eq!(Rad::<f32>::default().0, 0.0);
3045 assert_eq!(Turn::<f32>::default().0, 0.0);
3046 assert_eq!(
3047 Angles3::<f32>::default(),
3048 Angles3::new (
3049 AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero())
3050 );
3051 assert_eq!(
3052 Pose3::<f32>::default(),
3053 Pose3 { position: Point3::origin(), angles: Angles3::default() });
3054 assert_eq!(
3055 LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3056 Matrix3::identity());
3057 assert_eq!(
3058 LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3059 assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3060 assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3061 assert_eq!(
3062 Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3063 assert_eq!(
3064 AffineMap::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3065 AffineMap::new (Matrix3::identity(), Vector3::zero()));
3066 assert_eq!(
3067 Affinity::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
3068 Affinity::new (
3069 LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3070 assert_eq!(
3071 Projectivity::<
3072 f32, Vector3 <f32>, Vector3 <f32>, Vector4 <f32>, Vector4 <f32>,
3073 Matrix4 <f32>
3074 >::default().0,
3075 LinearIso::new (Matrix4::identity()).unwrap());
3076 }
3077
3078 #[test]
3079 fn rotation3_noisy_approx() {
3080 use rand::{Rng, SeedableRng};
3081 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3084 let up = Vector3::unit_z();
3085 for _ in 0..1000 {
3086 let forward = Vector3::new (
3087 rng.random_range (-1000.0f32..1000.0),
3088 rng.random_range (-1000.0f32..1000.0),
3089 0.0
3090 ).normalized();
3091 let right = forward.cross (up);
3092 let mat = Matrix3::from_col_arrays ([
3093 right.into_array(),
3094 forward.into_array(),
3095 up.into_array()
3096 ]);
3097 let _ = Rotation3::noisy_approx (mat);
3098 }
3099 }
3100
3101 #[test]
3102 fn rotation3_intrinsic_angles() {
3103 use std::f32::consts::PI;
3104 use num_traits::Zero;
3105 use rand::{Rng, SeedableRng};
3106 let rot = Rotation3::from_angles_intrinsic (
3108 Turn (0.25).into(), Rad::zero(), Rad::zero());
3109 approx::assert_relative_eq!(*rot,
3110 Matrix3::from_col_arrays ([
3111 [ 0.0, 1.0, 0.0],
3112 [-1.0, 0.0, 0.0],
3113 [ 0.0, 0.0, 1.0]
3114 ])
3115 );
3116 assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()),
3117 rot.intrinsic_angles());
3118 let rot = Rotation3::from_angles_intrinsic (
3119 Turn (0.5).into(), Rad::zero(), Rad::zero());
3120 approx::assert_relative_eq!(*rot,
3121 Matrix3::from_col_arrays ([
3122 [-1.0, 0.0, 0.0],
3123 [ 0.0, -1.0, 0.0],
3124 [ 0.0, 0.0, 1.0]
3125 ])
3126 );
3127 assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()),
3128 rot.intrinsic_angles());
3129 let rot = Rotation3::from_angles_intrinsic (
3131 Rad::zero(), Turn (0.25).into(), Rad::zero());
3132 approx::assert_relative_eq!(*rot,
3133 Matrix3::from_col_arrays ([
3134 [1.0, 0.0, 0.0],
3135 [0.0, 0.0, 1.0],
3136 [0.0, -1.0, 0.0]
3137 ])
3138 );
3139 assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()),
3140 rot.intrinsic_angles());
3141 let rot = Rotation3::from_angles_intrinsic (
3143 Rad::zero(), Rad::zero(), Turn (0.25).into());
3144 approx::assert_relative_eq!(*rot,
3145 Matrix3::from_col_arrays ([
3146 [0.0, 0.0, -1.0],
3147 [0.0, 1.0, 0.0],
3148 [1.0, 0.0, 0.0]
3149 ])
3150 );
3151 assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()),
3152 rot.intrinsic_angles());
3153 let rot = Rotation3::from_angles_intrinsic (
3155 Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3156 approx::assert_relative_eq!(*rot,
3157 Matrix3::from_col_arrays ([
3158 [0.0, 1.0, 0.0],
3159 [0.0, 0.0, 1.0],
3160 [1.0, 0.0, 0.0]
3161 ])
3162 );
3163 let angles = rot.intrinsic_angles();
3164 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3165 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3166 approx::assert_relative_eq!(0.0, angles.2.0);
3167 let rot = Rotation3::from_angles_intrinsic (
3169 Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3170 approx::assert_relative_eq!(*rot,
3171 Matrix3::from_col_arrays ([
3172 [-1.0, 0.0, 0.0],
3173 [ 0.0, 0.0, 1.0],
3174 [ 0.0, 1.0, 0.0]
3175 ])
3176 );
3177 let angles = rot.intrinsic_angles();
3178 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3179 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3180 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3181
3182 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3185 let mut random_vector = || Vector3::new (
3186 rng.random_range (-100.0f32..100.0),
3187 rng.random_range (-100.0f32..100.0),
3188 rng.random_range (-100.0f32..100.0)
3189 );
3190 for _ in 0..1000 {
3191 let rot = Rotation3::orthonormalize (
3192 random_vector(), random_vector(), random_vector()
3193 ).unwrap();
3194 let (yaw, pitch, roll) = rot.intrinsic_angles();
3195 assert!(yaw.0 < PI);
3196 assert!(yaw.0 > -PI);
3197 assert!(pitch.0 < PI);
3198 assert!(pitch.0 > -PI);
3199 assert!(roll.0 < PI);
3200 assert!(roll.0 > -PI);
3201 }
3202 }
3203
3204 #[test]
3205 fn rotation3_into_versor() {
3206 use std::f32::consts::PI;
3207 let rot = Rotation3::from_angle_x (Rad (0.01));
3208 let quat = rot.versor().0;
3209 approx::assert_relative_eq!(*rot, quat.into());
3210 let rot = Rotation3::from_angle_x (Rad (-0.01));
3211 let quat = rot.versor().0;
3212 approx::assert_relative_eq!(*rot, quat.into());
3213
3214 let rot = Rotation3::from_angle_y (Rad (0.01));
3215 let quat = rot.versor().0;
3216 approx::assert_relative_eq!(*rot, quat.into());
3217 let rot = Rotation3::from_angle_y (Rad (-0.01));
3218 let quat = rot.versor().0;
3219 approx::assert_relative_eq!(*rot, quat.into());
3220
3221 let rot = Rotation3::from_angle_z (Rad (0.01));
3222 let quat = rot.versor().0;
3223 approx::assert_relative_eq!(*rot, quat.into());
3224 let rot = Rotation3::from_angle_z (Rad (-0.01));
3225 let quat = rot.versor().0;
3226 approx::assert_relative_eq!(*rot, quat.into());
3227
3228 let rot = Rotation3::from_angle_x (Rad (PI / 2.0));
3229 let quat = rot.versor().0;
3230 approx::assert_relative_eq!(*rot, quat.into());
3231 let rot = Rotation3::from_angle_x (Rad (-PI / 2.0));
3232 let quat = rot.versor().0;
3233 approx::assert_relative_eq!(*rot, quat.into());
3234
3235 let rot = Rotation3::from_angle_y (Rad (PI / 2.0));
3236 let quat = rot.versor().0;
3237 approx::assert_relative_eq!(*rot, quat.into());
3238 let rot = Rotation3::from_angle_y (Rad (-PI / 2.0));
3239 let quat = rot.versor().0;
3240 approx::assert_relative_eq!(*rot, quat.into());
3241
3242 let rot = Rotation3::from_angle_z (Rad (PI / 2.0));
3243 let quat = rot.versor().0;
3244 approx::assert_relative_eq!(*rot, quat.into());
3245 let rot = Rotation3::from_angle_z (Rad (-PI / 2.0));
3246 let quat = rot.versor().0;
3247 approx::assert_relative_eq!(*rot, quat.into());
3248 }
3249}