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, Eq, PartialEq, PartialOrd)]
161pub struct Positive <S> (S);
162
163#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
165#[derive(Clone, Copy, Debug, Default, Eq, 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, Eq, 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, Eq, PartialEq)]
199pub struct Pose3 <S> {
200 pub position : Point3 <S>,
201 pub angles : Angles3 <S>
202}
203
204#[derive(Clone, Copy, Debug, Default, Eq, 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 S : Ring + MaybeSerDes;
225
226#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
229#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
230#[derive(Clone, Copy, Debug, Default, PartialEq)]
231pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where S : Ring + MaybeSerDes;
232
233#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
235#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
236pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
237
238#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
240#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
241#[display("({}, {})", linear_map, translation)]
242pub struct AffineMap <S, A, B, M> where
243 B : AffineSpace <S>,
244 S : Field + std::fmt::Display,
245 B::Vector : std::fmt::Display
246{
247 pub linear_map : M,
248 pub translation : B::Vector,
249 pub _phantom : PhantomData <A>
250}
251
252#[derive(Clone, Copy, Debug, Default, PartialEq, Display)]
254#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
255#[display("({}, {})", linear_iso, translation)]
256pub struct Affinity <S, A, B, M> where
257 A : AffineSpace <S>,
258 B : AffineSpace <S>,
259 S : Field + std::fmt::Display,
260 B::Vector : std::fmt::Display
261{
262 pub linear_iso : LinearIso <S, A::Vector, B::Vector, M>,
263 pub translation : B::Vector,
264 pub _phantom : PhantomData <A>
265}
266
267#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
269#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
270#[display("{}", _0)]
271pub struct Projectivity <S, V, W, P, Q, M> (
272 pub LinearIso <S, P, Q, M>,
273 pub PhantomData <(V, W)>
274);
275
276impl <S : Real> Angle <S> for Deg <S> {
284 fn full_turn() -> Self {
285 Deg (S::ten() * S::nine() * S::two() * S::two())
286 }
287 fn half_turn() -> Self {
288 Deg (S::ten() * S::nine() * S::two())
289 }
290}
291impl <S : Real> Trig for Deg <S> {
292 fn sin (self) -> Self {
293 Rad::from (self).sin().into()
294 }
295 fn sin_cos (self) -> (Self, Self) {
296 let (sin, cos) = Rad::from (self).sin_cos();
297 (sin.into(), cos.into())
298 }
299 fn cos (self) -> Self {
300 Rad::from (self).cos().into()
301 }
302 fn tan (self) -> Self {
303 Rad::from (self).tan().into()
304 }
305 fn asin (self) -> Self {
306 Rad::from (self).asin().into()
307 }
308 fn acos (self) -> Self {
309 Rad::from (self).acos().into()
310 }
311 fn atan (self) -> Self {
312 Rad::from (self).atan().into()
313 }
314 fn atan2 (self, other : Self) -> Self {
315 Rad::from (self).atan2 (Rad::from (other)).into()
316 }
317}
318impl <S : Real> From <Rad <S>> for Deg <S> {
319 fn from (radians : Rad <S>) -> Self {
320 let full_turns = radians / Rad::full_turn();
321 Deg::full_turn() * full_turns
322 }
323}
324impl <S : Real> From <Turn <S>> for Deg <S> {
325 fn from (turns : Turn <S>) -> Self {
326 Deg (turns.0 * Deg::full_turn().0)
327 }
328}
329
330impl <S : Real> Angle <S> for Rad <S> {
334 fn full_turn() -> Self {
335 Rad (S::pi() * S::two())
336 }
337}
338impl <S : Real> Trig for Rad <S> {
339 fn sin (self) -> Self {
340 Rad (self.0.sin())
341 }
342 fn sin_cos (self) -> (Self, Self) {
343 let (sin, cos) = self.0.sin_cos();
344 (Rad (sin), Rad (cos))
345 }
346 fn cos (self) -> Self {
347 Rad (self.0.cos())
348 }
349 fn tan (self) -> Self {
350 Rad (self.0.tan())
351 }
352 fn asin (self) -> Self {
353 Rad (self.0.asin())
354 }
355 fn acos (self) -> Self {
356 Rad (self.0.acos())
357 }
358 fn atan (self) -> Self {
359 Rad (self.0.atan())
360 }
361 fn atan2 (self, other : Self) -> Self {
362 Rad (self.0.atan2 (other.0))
363 }
364}
365impl <S : Real> From <Deg <S>> for Rad <S> {
366 fn from (degrees : Deg <S>) -> Self {
367 let full_turns = degrees / Deg::full_turn();
368 Rad::full_turn() * full_turns
369 }
370}
371impl <S : Real> From <Turn <S>> for Rad <S> {
372 fn from (turns : Turn <S>) -> Self {
373 Rad (turns.0 * Rad::full_turn().0)
374 }
375}
376
377impl <S : Real> Angle <S> for Turn <S> {
381 fn full_turn() -> Self {
382 Turn (S::one())
383 }
384 fn half_turn() -> Self {
385 Turn (S::half())
386 }
387}
388impl <S : Real> Trig for Turn <S> {
389 fn sin (self) -> Self {
390 Rad::from (self).sin().into()
391 }
392 fn sin_cos (self) -> (Self, Self) {
393 let (sin, cos) = Rad::from (self).sin_cos();
394 (sin.into(), cos.into())
395 }
396 fn cos (self) -> Self {
397 Rad::from (self).cos().into()
398 }
399 fn tan (self) -> Self {
400 Rad::from (self).tan().into()
401 }
402 fn asin (self) -> Self {
403 Rad::from (self).asin().into()
404 }
405 fn acos (self) -> Self {
406 Rad::from (self).acos().into()
407 }
408 fn atan (self) -> Self {
409 Rad::from (self).atan().into()
410 }
411 fn atan2 (self, other : Self) -> Self {
412 Rad::from (self).atan2 (Rad::from (other)).into()
413 }
414}
415impl <S : Real> From <Rad <S>> for Turn <S> {
416 fn from (radians : Rad <S>) -> Self {
417 Turn (radians.0 / Rad::full_turn().0)
418 }
419}
420impl <S : Real> From <Deg <S>> for Turn <S> {
421 fn from (degrees : Deg <S>) -> Self {
422 Turn (degrees.0 / Deg::full_turn().0)
423 }
424}
425
426impl <S : Real> AngleWrapped <S> {
430 pub fn wrap (angle : Rad <S>) -> Self {
431 AngleWrapped (angle.wrap_unsigned())
432 }
433
434 pub fn map <F> (self, f : F) -> Self where
435 F : FnOnce (Rad <S>) -> Rad <S>
436 {
437 AngleWrapped (f (self.0).wrap_unsigned())
438 }
439}
440
441impl <S : Real> AngleWrappedSigned <S> {
445 pub fn wrap (angle : Rad <S>) -> Self {
446 AngleWrappedSigned (angle.wrap_signed())
447 }
448
449 pub fn map <F> (self, f : F) -> Self where
450 F : FnOnce (Rad <S>) -> Rad <S>
451 {
452 AngleWrappedSigned (f (self.0).wrap_signed())
453 }
454}
455
456impl <S : Real> Angles3 <S> {
461 pub const fn new (
462 yaw : AngleWrapped <S>,
463 pitch : AngleWrapped <S>,
464 roll : AngleWrapped <S>
465 ) -> Self {
466 Angles3 { yaw, pitch, roll }
467 }
468
469 pub fn zero() -> Self {
470 use num::Zero;
471 Angles3::new (
472 AngleWrapped::zero(),
473 AngleWrapped::zero(),
474 AngleWrapped::zero())
475 }
476
477 pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
478 let yaw = AngleWrapped::wrap (yaw);
479 let pitch = AngleWrapped::wrap (pitch);
480 let roll = AngleWrapped::wrap (roll);
481 Angles3 { yaw, pitch, roll }
482 }
483}
484
485impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
486 fn from (rotation : Rotation3 <S>) -> Self {
487 let (yaw, pitch, roll) = {
488 let (yaw, pitch, roll) = rotation.intrinsic_angles();
489 ( AngleWrapped::wrap (yaw),
490 AngleWrapped::wrap (pitch),
491 AngleWrapped::wrap (roll)
492 )
493 };
494 Angles3 { yaw, pitch, roll }
495 }
496}
497
498impl Axis2 {
502 #[inline]
503 pub const fn component (self) -> usize {
504 self as usize
505 }
506}
507
508impl Axis3 {
512 #[inline]
513 pub const fn component (self) -> usize {
514 self as usize
515 }
516}
517
518impl SignedAxis3 {
522 pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
523 if *vector == [ S::one(), S::zero(), S::zero()].into() {
524 Some (SignedAxis3::PosX)
525 } else if *vector == [-S::one(), S::zero(), S::zero()].into() {
526 Some (SignedAxis3::NegX)
527 } else if *vector == [ S::zero(), S::one(), S::zero()].into() {
528 Some (SignedAxis3::PosY)
529 } else if *vector == [ S::zero(), -S::one(), S::zero()].into() {
530 Some (SignedAxis3::NegY)
531 } else if *vector == [ S::zero(), S::zero(), S::one() ].into() {
532 Some (SignedAxis3::PosZ)
533 } else if *vector == [ S::zero(), S::zero(), -S::one() ].into() {
534 Some (SignedAxis3::NegZ)
535 } else {
536 None
537 }
538 }
539
540 pub fn to_vec <S : Field> (self) -> Vector3 <S> {
541 match self {
542 SignedAxis3::NegX => [-S::one(), S::zero(), S::zero()].into(),
543 SignedAxis3::PosX => [ S::one(), S::zero(), S::zero()].into(),
544 SignedAxis3::NegY => [ S::zero(), -S::one(), S::zero()].into(),
545 SignedAxis3::PosY => [ S::zero(), S::one(), S::zero()].into(),
546 SignedAxis3::NegZ => [ S::zero(), S::zero(), -S::one() ].into(),
547 SignedAxis3::PosZ => [ S::zero(), S::zero(), S::one() ].into()
548 }
549 }
550 #[inline]
551 pub fn to_unit <S> (self) -> Unit3 <S> where S : Real + std::fmt::Debug {
552 Unit3::unchecked (self.to_vec())
553 }
554}
555
556impl Quadrant {
560 pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
563 S : Ring + SignedExt
564 {
565 let sign_x = vector.x.sign();
566 let sign_y = vector.y.sign();
567 let quadrant = match (sign_x, sign_y) {
568 (Sign::Zero, _) |
569 ( _, Sign::Zero) => return None,
570 (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
571 (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
572 (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
573 (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
574 };
575 Some (quadrant)
576 }
577 #[inline]
579 pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
580 S : Ring + SignedExt
581 {
582 Quadrant::from_vec_strict (&point.to_vector())
583 }
584}
585impl Octant {
591 pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
594 S : Ring + SignedExt
595 {
596 let sign_x = vector.x.sign();
597 let sign_y = vector.y.sign();
598 let sign_z = vector.z.sign();
599 let octant = match (sign_x, sign_y, sign_z) {
600 (Sign::Zero, _, _) |
601 ( _, Sign::Zero, _) |
602 ( _, _, Sign::Zero) => return None,
603 (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
604 (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
605 (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
606 (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
607 (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
608 (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
609 (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
610 (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
611 };
612 Some (octant)
613 }
614 #[inline]
616 pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
617 S : Ring + SignedExt
618 {
619 Octant::from_vec_strict (&point.to_vector())
620 }
621}
622impl <S : Ring> Positive <S> {
628 pub fn new (value : S) -> Option <Self> {
639 if value > S::zero() {
640 Some (Positive (value))
641 } else {
642 None
643 }
644 }
645 pub fn infinity() -> Self where S : num::float::FloatCore {
647 Positive (S::infinity())
648 }
649 pub fn noisy (value : S) -> Self {
658 assert!(value > S::zero());
659 Positive (value)
660 }
661 pub fn unchecked (value : S) -> Self {
670 debug_assert!(value > S::zero());
671 Positive (value)
672 }
673 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
694 Self::noisy (fun (self.0))
695 }
696}
697impl <S : Field> num::One for Positive <S> {
698 fn one() -> Self {
699 Positive (S::one())
700 }
701}
702impl <S : Ring> std::ops::Deref for Positive <S> {
703 type Target = S;
704 fn deref (&self) -> &S {
705 &self.0
706 }
707}
708impl <S : Ring> std::ops::Mul for Positive <S> {
709 type Output = Self;
710 fn mul (self, rhs : Self) -> Self::Output {
711 Positive (self.0 * rhs.0)
712 }
713}
714impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
715 type Output = NonNegative <S>;
716 fn mul (self, rhs : NonNegative <S>) -> Self::Output {
717 NonNegative (self.0 * *rhs)
718 }
719}
720impl <S : Field> std::ops::Div for Positive <S> {
721 type Output = Self;
722 fn div (self, rhs : Self) -> Self::Output {
723 Positive (self.0 / rhs.0)
724 }
725}
726impl <S : Ring> std::ops::Add for Positive <S> {
727 type Output = Self;
728 fn add (self, rhs : Self) -> Self::Output {
729 Positive (self.0 + rhs.0)
730 }
731}
732impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
733 type Output = Self;
734 fn add (self, rhs : NonNegative <S>) -> Self::Output {
735 Positive (self.0 + rhs.0)
736 }
737}
738impl <S : Ring> NonNegative <S> {
744 pub fn new (value : S) -> Option <Self> {
755 if value >= S::zero() {
756 Some (NonNegative (value))
757 } else {
758 None
759 }
760 }
761 pub fn abs (value : S) -> Self {
771 NonNegative (value.abs())
772 }
773 pub fn noisy (value : S) -> Self {
782 assert!(S::zero() <= value);
783 NonNegative (value)
784 }
785 pub fn unchecked (value : S) -> Self {
795 debug_assert!(value >= S::zero());
796 NonNegative (value)
797 }
798 pub fn map_abs (self, fun : fn (S) -> S) -> Self {
808 Self::abs (fun (self.0))
809 }
810 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
828 Self::noisy (fun (self.0))
829 }
830}
831impl <S : Ring> From <Positive <S>> for NonNegative <S> {
832 fn from (positive : Positive <S>) -> Self {
833 NonNegative (*positive)
834 }
835}
836impl <S : Ring> num::Zero for NonNegative <S> {
837 fn zero() -> Self {
838 NonNegative (S::zero())
839 }
840 fn is_zero (&self) -> bool {
841 self.0.is_zero()
842 }
843}
844impl <S : Field> num::One for NonNegative <S> {
845 fn one() -> Self {
846 NonNegative (S::one())
847 }
848}
849impl <S : Ring> std::ops::Deref for NonNegative <S> {
850 type Target = S;
851 fn deref (&self) -> &S {
852 &self.0
853 }
854}
855impl <S : Ring> std::ops::Mul for NonNegative <S> {
856 type Output = Self;
857 fn mul (self, rhs : Self) -> Self::Output {
858 NonNegative (self.0 * rhs.0)
859 }
860}
861impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
862 type Output = Self;
863 fn mul (self, rhs : Positive <S>) -> Self::Output {
864 NonNegative (self.0 * rhs.0)
865 }
866}
867impl <S : Field> std::ops::Div for NonNegative <S> {
868 type Output = Self;
869 fn div (self, rhs : Self) -> Self::Output {
870 NonNegative (self.0 / rhs.0)
871 }
872}
873impl <S : Ring> std::ops::Add for NonNegative <S> {
874 type Output = Self;
875 fn add (self, rhs : Self) -> Self::Output {
876 NonNegative (self.0 + rhs.0)
877 }
878}
879impl <S : Field> NonZero <S> {
885 #[inline]
896 pub fn new (value : S) -> Option <Self> {
897 if S::zero() != value {
898 Some (NonZero (value))
899 } else {
900 None
901 }
902 }
903 #[inline]
912 pub fn noisy (value : S) -> Self {
913 assert!(S::zero() != value);
914 NonZero (value)
915 }
916 #[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 #[expect(clippy::same_name_method)]
1005 pub fn clamp (value : S) -> Self {
1006 let value = S::max (S::zero(), S::min (value, S::one()));
1007 Normalized (value)
1008 }
1009 #[inline]
1023 pub fn noisy (value : S) -> Self {
1024 assert!(value <= S::one());
1025 assert!(S::zero() <= value);
1026 Normalized (value)
1027 }
1028 #[inline]
1040 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1041 Self::clamp (fun (self.0))
1042 }
1043 #[inline]
1070 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1071 Self::noisy (fun (self.0))
1072 }
1073}
1074impl <S : Field> num::One for Normalized <S> {
1075 fn one() -> Self {
1076 Normalized (S::one())
1077 }
1078}
1079impl <S : Field> std::ops::Deref for Normalized <S> {
1080 type Target = S;
1081 fn deref (&self) -> &S {
1082 &self.0
1083 }
1084}
1085impl <S : Field> std::ops::Mul for Normalized <S> {
1086 type Output = Self;
1087 fn mul (self, rhs : Self) -> Self::Output {
1088 Normalized (self.0 * rhs.0)
1089 }
1090}
1091impl <S : Field> Eq for Normalized <S> { }
1092#[expect(clippy::derive_ord_xor_partial_ord)]
1093impl <S : Field> Ord for Normalized <S> {
1094 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1095 self.partial_cmp (other).unwrap()
1097 }
1098}
1099impl <S : Field> NormalSigned <S> {
1105 #[inline]
1107 pub fn zero() -> Self {
1108 NormalSigned (S::zero())
1109 }
1110 #[inline]
1111 pub fn is_zero (&self) -> bool {
1112 self.0.is_zero()
1113 }
1114 #[inline]
1128 pub fn new (value : S) -> Option <Self> {
1129 if -S::one() <= value && value <= S::one() {
1130 Some (NormalSigned (value))
1131 } else {
1132 None
1133 }
1134 }
1135 #[inline]
1145 #[expect(clippy::same_name_method)]
1146 pub fn clamp (value : S) -> Self {
1147 let value = S::max (-S::one(), S::min (value, S::one()));
1148 NormalSigned (value)
1149 }
1150 #[inline]
1164 pub fn noisy (value : S) -> Self {
1165 assert!(value <= S::one());
1166 assert!(-S::one() <= value);
1167 NormalSigned (value)
1168 }
1169 #[inline]
1181 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1182 Self::clamp (fun (self.0))
1183 }
1184 #[inline]
1211 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1212 Self::noisy (fun (self.0))
1213 }
1214}
1215impl <S : Field> From <Normalized <S>> for NormalSigned <S> {
1216 fn from (Normalized (value) : Normalized <S>) -> Self {
1217 debug_assert!(S::zero() <= value);
1218 debug_assert!(value <= S::one());
1219 NormalSigned (value)
1220 }
1221}
1222impl <S : Field> num::One for NormalSigned <S> {
1223 fn one() -> Self {
1224 NormalSigned (S::one())
1225 }
1226}
1227impl <S : Field> std::ops::Deref for NormalSigned <S> {
1228 type Target = S;
1229 fn deref (&self) -> &S {
1230 &self.0
1231 }
1232}
1233impl <S : Field> std::ops::Mul for NormalSigned <S> {
1234 type Output = Self;
1235 fn mul (self, rhs : Self) -> Self::Output {
1236 NormalSigned (self.0 * rhs.0)
1237 }
1238}
1239impl <S : Field> Eq for NormalSigned <S> { }
1240#[expect(clippy::derive_ord_xor_partial_ord)]
1241impl <S : Field> Ord for NormalSigned <S> {
1242 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1243 self.partial_cmp (other).unwrap()
1245 }
1246}
1247impl <S : Field> std::ops::Neg for NormalSigned <S> {
1248 type Output = Self;
1249 fn neg (self) -> Self::Output {
1250 NormalSigned (-self.0)
1251 }
1252}
1253impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1259 pub fn identity() -> Self {
1261 use num::One;
1262 Self::one()
1263 }
1264 pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1269 let transform = LinearAuto (LinearIso::new (mat)?);
1270 if !transform.is_rotation() {
1271 None
1272 } else {
1273 Some (Rotation2 (transform))
1274 }
1275 }
1276 pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1282 S : approx::RelativeEq <Epsilon=S>
1283 {
1284 let four = S::one() + S::one() + S::one() + S::one();
1285 let epsilon = S::default_epsilon() * four;
1286 let max_relative = S::default_max_relative() * four;
1287 if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1288 max_relative=max_relative, epsilon=epsilon
1289 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1290 None
1291 } else {
1292 Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData))))
1293 }
1294 }
1295 pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1297 Rotation2 (LinearAuto (LinearIso (Matrix2::rotation_z (angle.0), PhantomData)))
1298 }
1299 pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1303 assert_eq!(mat * mat.transposed(), Matrix2::identity());
1304 assert_eq!(mat.determinant(), S::one());
1305 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1306 }
1307 pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1312 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1313 {
1314 let four = S::one() + S::one() + S::one() + S::one();
1315 let epsilon = S::default_epsilon() * four;
1316 let max_relative = S::default_max_relative() * four;
1317 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1318 epsilon=epsilon, max_relative=max_relative);
1319 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1320 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1321 }
1322 pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1326 debug_assert!(mat * mat.transposed() == Matrix2::identity());
1327 debug_assert!(mat.determinant() == S::one());
1328 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1329 }
1330 pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1335 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1336 {
1337 if cfg!(debug_assertions) {
1338 let four = S::one() + S::one() + S::one() + S::one();
1339 let epsilon = S::default_epsilon() * four;
1340 let max_relative = S::default_max_relative() * four;
1341 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1342 max_relative=max_relative, epsilon=epsilon);
1343 approx::assert_relative_eq!(mat.determinant(), S::one(),
1344 max_relative=max_relative);
1345 }
1346 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1347 }
1348 pub fn rotate (self, point : Point2 <S>) -> Point2 <S> {
1350 Point2::from (self * point.0)
1351 }
1352}
1353impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1354 type Target = Matrix2 <S>;
1355 fn deref (&self) -> &Self::Target {
1356 &self.0
1357 }
1358}
1359impl <S> MultiplicativeGroup for Rotation2 <S> where S : Ring + MaybeSerDes { }
1360impl <S> MultiplicativeMonoid for Rotation2 <S> where S : Ring + MaybeSerDes { }
1361impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1362 type Output = Self;
1363 fn inv (self) -> Self::Output {
1364 Rotation2 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1365 }
1366}
1367impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1368 type Output = Vector2 <S>;
1369 fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1370 self.0 * rhs
1371 }
1372}
1373impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where S : Ring + MaybeSerDes {
1374 type Output = Vector2 <S>;
1375 fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1376 self * rhs.0
1377 }
1378}
1379impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1380 type Output = Self;
1381 fn mul (self, rhs : Self) -> Self::Output {
1382 Rotation2 (self.0 * rhs.0)
1383 }
1384}
1385impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1386 fn mul_assign (&mut self, rhs : Self) {
1387 self.0 *= rhs.0
1388 }
1389}
1390impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1391 type Output = Self;
1392 #[expect(clippy::suspicious_arithmetic_impl)]
1393 fn div (self, rhs : Self) -> Self::Output {
1394 use num::Inv;
1395 self * rhs.inv()
1396 }
1397}
1398impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1399 #[expect(clippy::suspicious_op_assign_impl)]
1400 fn div_assign (&mut self, rhs : Self) {
1401 use num::Inv;
1402 *self *= rhs.inv()
1403 }
1404}
1405impl <S> num::One for Rotation2 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
1406 fn one() -> Self {
1407 Rotation2 (LinearAuto (LinearIso (Matrix2::identity(), PhantomData)))
1408 }
1409}
1410
1411impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1415 pub fn identity() -> Self {
1417 use num::One;
1418 Self::one()
1419 }
1420 pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1424 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_x (angle.0), PhantomData)))
1425 }
1426 pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1430 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_y (angle.0), PhantomData)))
1431 }
1432 pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1436 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_z (angle.0), PhantomData)))
1437 }
1438 pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1444 -> Self where S : num::real::Real
1445 {
1446 let rotation1 = Rotation3::from_angle_z (yaw);
1447 let rotation2 = Rotation3::from_axis_angle (rotation1.cols.x, pitch) * rotation1;
1448 Rotation3::from_axis_angle (rotation2.cols.y, roll) * rotation2
1449 }
1450 pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1452 S : num::real::Real
1453 {
1454 Rotation3 (LinearAuto (LinearIso (
1455 Matrix3::rotation_3d (angle.0, axis), PhantomData)))
1456 }
1457 pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1460 -> Option <Self> where S : Field + Sqrt
1461 {
1462 if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array)).determinant()
1463 == S::zero()
1464 {
1465 None
1466 } else {
1467 let project = |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1468 let u1 = v1;
1469 let u2 = v2 - project (u1, v2);
1470 let u3 = v3 - project (u1, v3) - project (u2, v3);
1471 Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1472 u1.normalize().into_array(),
1473 u2.normalize().into_array(),
1474 u3.normalize().into_array()
1475 ]), PhantomData))))
1476 }
1477 }
1478
1479 pub fn look_at (point : Point3 <S>) -> Self where
1483 S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1484 {
1485 if point == Point::origin() {
1486 Self::identity()
1487 } else {
1488 use num::Zero;
1489 let forward = point.0.normalized();
1490 let right = {
1491 let projected = forward.with_z (S::zero());
1492 if !projected.is_zero() {
1493 Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1494 } else {
1495 Vector3::unit_x()
1496 }
1497 };
1498 let up = right.cross (forward);
1499 let mat =
1500 Matrix3::from_col_arrays ([right, forward, up].map (Vector3::into_array));
1501 Self::noisy_approx (mat)
1502 }
1503 }
1504
1505 pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1510 if mat * mat.transposed() != Matrix3::identity() || mat.determinant() != S::one() {
1511 None
1512 } else {
1513 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1514 }
1515 }
1516 pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1522 S : approx::RelativeEq <Epsilon=S>
1523 {
1524 let four = S::one() + S::one() + S::one() + S::one();
1525 let epsilon = S::default_epsilon() * four;
1526 let max_relative = S::default_max_relative() * four;
1527 if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1528 max_relative=max_relative, epsilon=epsilon
1529 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1530 None
1531 } else {
1532 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1533 }
1534 }
1535 pub fn noisy (mat : Matrix3 <S>) -> Self {
1539 assert!(mat * mat.transposed() == Matrix3::identity());
1540 assert!(mat.determinant() == S::one());
1541 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1542 }
1543 pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1548 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1549 {
1550 let four = S::one() + S::one() + S::one() + S::one();
1551 let eight = four + S::one() + S::one() + S::one() + S::one();
1552 let epsilon = S::default_epsilon() * four;
1553 let max_relative = S::default_max_relative() * eight;
1554 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1555 max_relative=max_relative, epsilon=epsilon);
1556 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1557 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1558 }
1559 pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1563 debug_assert!(mat * mat.transposed() == Matrix3::identity());
1564 debug_assert!(mat.determinant() == S::one());
1565 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1566 }
1567 pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1572 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1573 {
1574 if cfg!(debug_assertions) {
1575 let four = S::one() + S::one() + S::one() + S::one();
1576 let epsilon = S::default_epsilon() * four;
1577 let max_relative = S::default_max_relative() * four;
1578 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1579 max_relative=max_relative, epsilon=epsilon);
1580 approx::assert_relative_eq!(mat.determinant(), S::one(),
1581 max_relative=max_relative);
1582 }
1583 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1584 }
1585 pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1590 let cols = &self.cols;
1591 let yaw = Rad (S::atan2 (-cols.y.x, cols.y.y));
1592 let pitch = Rad (S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z)));
1593 let roll = Rad (S::atan2 (-cols.x.z, cols.z.z));
1594 (yaw, pitch, roll)
1595 }
1596
1597 pub fn versor (self) -> Versor <S> where
1601 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1602 {
1603 let diagonal = self.diagonal();
1604 let t = diagonal.sum();
1605 let m = MinMax::max (MinMax::max (MinMax::max (
1606 diagonal.x, diagonal.y), diagonal.z), t);
1607 let qmax = S::half() * Sqrt::sqrt (S::one() - t + S::two() * m);
1608 let qmax4_recip = (S::four() * qmax).recip();
1609 let [qx, qy, qz, qw] : [S; 4];
1610 let cols = self.cols;
1611 if m == diagonal.x {
1612 qx = qmax;
1613 qy = qmax4_recip * (cols.x.y + cols.y.x);
1614 qz = qmax4_recip * (cols.x.z + cols.z.x);
1615 qw = -qmax4_recip * (cols.z.y - cols.y.z);
1616 } else if m == diagonal.y {
1617 qx = qmax4_recip * (cols.x.y + cols.y.x);
1618 qy = qmax;
1619 qz = qmax4_recip * (cols.y.z + cols.z.y);
1620 qw = -qmax4_recip * (cols.x.z - cols.z.x);
1621 } else if m == diagonal.z {
1622 qx = qmax4_recip * (cols.x.z + cols.z.x);
1623 qy = qmax4_recip * (cols.y.z + cols.z.y);
1624 qz = qmax;
1625 qw = -qmax4_recip * (cols.y.x - cols.x.y);
1626 } else {
1627 qx = -qmax4_recip * (cols.z.y - cols.y.z);
1628 qy = -qmax4_recip * (cols.x.z - cols.z.x);
1629 qz = -qmax4_recip * (cols.y.x - cols.x.y);
1630 qw = qmax;
1631 }
1632 let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1633 Versor::unchecked_approx (quat)
1634 }
1635 pub fn rotate (self, point : Point3 <S>) -> Point3 <S> {
1637 Point3::from (self * point.0)
1638 }
1639}
1640impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1641 type Target = Matrix3 <S>;
1642 fn deref (&self) -> &Self::Target {
1643 &self.0
1644 }
1645}
1646impl <S> MultiplicativeGroup for Rotation3 <S> where S : Ring + MaybeSerDes { }
1647impl <S> MultiplicativeMonoid for Rotation3 <S> where S : Ring + MaybeSerDes { }
1648impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1649 type Output = Self;
1650 fn inv (self) -> Self::Output {
1651 Rotation3 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1652 }
1653}
1654impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
1655 type Output = Vector3 <S>;
1656 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1657 self.0 * rhs
1658 }
1659}
1660impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where S : Ring + MaybeSerDes {
1661 type Output = Vector3 <S>;
1662 fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1663 self * rhs.0
1664 }
1665}
1666impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1667 type Output = Self;
1668 fn mul (self, rhs : Self) -> Self::Output {
1669 Rotation3 (self.0 * rhs.0)
1670 }
1671}
1672impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
1673 fn mul_assign (&mut self, rhs : Self) {
1674 self.0 *= rhs.0
1675 }
1676}
1677impl <S> std::ops::Div for Rotation3 <S> where S : Ring + MaybeSerDes {
1678 type Output = Self;
1679 #[expect(clippy::suspicious_arithmetic_impl)]
1680 fn div (self, rhs : Self) -> Self::Output {
1681 use num::Inv;
1682 self * rhs.inv()
1683 }
1684}
1685impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
1686 #[expect(clippy::suspicious_op_assign_impl)]
1687 fn div_assign (&mut self, rhs : Self) {
1688 use num::Inv;
1689 *self *= rhs.inv()
1690 }
1691}
1692impl <S> num::One for Rotation3 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
1693 fn one() -> Self {
1694 Rotation3 (LinearAuto (LinearIso (Matrix3::identity(), PhantomData)))
1695 }
1696}
1697impl <S> From <Angles3 <S>> for Rotation3 <S> where
1698 S : Real + MaybeSerDes + num::real::Real
1699{
1700 fn from (angles : Angles3 <S>) -> Self {
1701 Rotation3::from_angles_intrinsic (
1702 angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1703 }
1704}
1705
1706
1707impl <S : Real> Versor <S> {
1711 pub fn normalize (quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1715 assert_ne!(quaternion, Quaternion::zero());
1716 Versor (normalize_quaternion (quaternion))
1717 }
1718 pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1722 assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1723 Versor (unit_quaternion)
1724 }
1725 pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1729 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1730 {
1731 assert!(unit_quaternion.into_vec4().is_normalized());
1732 Versor (unit_quaternion)
1733 }
1734 pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1738 debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1739 Versor (unit_quaternion)
1740 }
1741 pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1745 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1746 {
1747 debug_assert!(unit_quaternion.into_vec4().is_normalized());
1748 Versor (unit_quaternion)
1749 }
1750 pub fn from_scaled_axis (scaled_axis : &Vector3 <S>) -> Self where
1753 S : std::fmt::Debug + num::Float
1754 {
1755 if *scaled_axis == Vector3::zero() {
1756 let versor = Quaternion::rotation_3d (S::zero(), *scaled_axis);
1757 debug_assert_eq!(versor.magnitude(), S::one());
1758 Versor (versor)
1759 } else {
1760 let angle = scaled_axis.magnitude();
1761 debug_assert!(S::zero() < angle);
1762 let axis = *scaled_axis / angle;
1763 Versor (Quaternion::rotation_3d (angle, axis))
1764 }
1765 }
1766}
1767impl <S> From <Rotation3 <S>> for Versor <S> where
1768 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1769{
1770 fn from (rot : Rotation3 <S>) -> Self {
1771 rot.versor()
1772 }
1773}
1774impl <S : Real> std::ops::Deref for Versor <S> {
1775 type Target = Quaternion <S>;
1776 fn deref (&self) -> &Quaternion <S> {
1777 &self.0
1778 }
1779}
1780impl <S, A, B, M> AffineMap <S, A, B, M> where
1786 A : AffineSpace <S>,
1787 B : AffineSpace <S>,
1788 M : LinearMap <S, A::Vector, B::Vector>,
1789 S : Field + std::fmt::Display,
1790 B::Vector : std::fmt::Display
1791{
1792 pub const fn new (linear_map : M, translation : B::Vector) -> Self {
1793 AffineMap { linear_map, translation, _phantom: PhantomData }
1794 }
1795 pub fn transform (self, point : A::Point) -> B::Point {
1796 B::Point::from_vector (self.linear_map * point.to_vector() + self.translation)
1797 }
1798}
1799
1800impl <S, V, W, M> LinearIso <S, V, W, M> where
1804 M : LinearMap <S, V, W> + Copy,
1805 V : Module <S>,
1806 W : Module <S>,
1807 S : Ring
1808{
1809 pub fn is_invertible (linear_map : M) -> bool {
1811 linear_map.determinant() != S::zero()
1812 }
1813 pub fn is_invertible_approx (linear_map : M) -> bool where
1815 S : approx::RelativeEq <Epsilon=S>
1816 {
1817 let four = S::one() + S::one() + S::one() + S::one();
1818 let epsilon = S::default_epsilon() * four;
1819 let max_relative = S::default_max_relative() * four;
1820 approx::relative_ne!(linear_map.determinant(), S::zero(),
1821 max_relative=max_relative, epsilon=epsilon)
1822 }
1823 pub fn new (linear_map : M) -> Option <Self> {
1825 if Self::is_invertible (linear_map) {
1826 Some (LinearIso (linear_map, PhantomData))
1827 } else {
1828 None
1829 }
1830 }
1831 pub fn new_approx (linear_map : M) -> Option <Self> where
1833 S : approx::RelativeEq <Epsilon=S>
1834 {
1835 if Self::is_invertible_approx (linear_map) {
1836 Some (LinearIso (linear_map, PhantomData))
1837 } else {
1838 None
1839 }
1840 }
1841}
1842impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1843 M : LinearMap <S, V, W>,
1844 V : Module <S>,
1845 W : Module <S>,
1846 S : Ring
1847{
1848 type Target = M;
1849 fn deref (&self) -> &Self::Target {
1850 &self.0
1851 }
1852}
1853impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1854 V : Module <S>,
1855 S : Ring
1856{
1857 fn one () -> Self {
1858 LinearIso (V::LinearEndo::one(), PhantomData)
1859 }
1860}
1861impl <S, V, W, M> std::ops::Mul <V> for LinearIso <S, V, W, M> where
1862 M : LinearMap <S, V, W>,
1863 V : Module <S>,
1864 W : Module <S>,
1865 S : Ring
1866{
1867 type Output = W;
1868 fn mul (self, rhs : V) -> Self::Output {
1869 self.0 * rhs
1870 }
1871}
1872impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1873 V : Module <S>,
1874 S : Ring
1875{
1876 type Output = Self;
1877 fn mul (self, rhs : Self) -> Self::Output {
1878 LinearIso (self.0 * rhs.0, PhantomData)
1879 }
1880}
1881impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1882 V : Module <S>,
1883 S : Ring
1884{
1885 fn mul_assign (&mut self, rhs : Self) {
1886 self.0 *= rhs.0
1887 }
1888}
1889
1890impl <S, V> LinearAuto <S, V> where
1894 V : Module <S>,
1895 V::LinearEndo : MaybeSerDes,
1896 S : Ring
1897{
1898 pub fn is_orthonormal (&self) -> bool {
1903 use num::One;
1904 let determinant = self.0.0.determinant();
1905 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1906 (determinant == S::one() || determinant == -S::one())
1907 }
1908 pub fn is_orthonormal_approx (&self) -> bool where
1914 S : approx::RelativeEq <Epsilon=S>,
1915 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1916 {
1917 use num::One;
1918 let four = S::one() + S::one() + S::one() + S::one();
1919 let epsilon = S::default_epsilon() * four;
1920 let max_relative = S::default_max_relative() * four;
1921 let determinant = self.0.0.determinant();
1922 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1923 max_relative=max_relative, epsilon=epsilon) &&
1924 ( approx::relative_eq!(determinant, S::one(), max_relative=max_relative) ||
1925 approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
1926 }
1927 pub fn is_rotation (&self) -> bool {
1931 use num::One;
1932 let determinant = self.0.0.determinant();
1933 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1934 determinant == S::one()
1935 }
1936 pub fn is_rotation_approx (&self) -> bool where
1941 S : approx::RelativeEq <Epsilon=S>,
1942 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1943 {
1944 use num::One;
1945 let four = S::one() + S::one() + S::one() + S::one();
1946 let epsilon = S::default_epsilon() * four;
1947 let max_relative = S::default_max_relative() * four;
1948 let determinant = self.0.0.determinant();
1949 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1950 max_relative=max_relative, epsilon=epsilon) &&
1951 approx::relative_eq!(determinant, S::one(), max_relative=max_relative)
1952 }
1953}
1954impl <S, V> MultiplicativeMonoid for LinearAuto <S, V> where
1955 V : Module <S>,
1956 V::LinearEndo : MaybeSerDes + PartialEq,
1957 S : Ring
1958{ }
1959impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
1960 V : Module <S>,
1961 V::LinearEndo : MaybeSerDes,
1962 S : Ring
1963{
1964 type Output = V;
1965 fn mul (self, rhs : V) -> Self::Output {
1966 self.0 * rhs
1967 }
1968}
1969impl <S, V> std::ops::Mul for LinearAuto <S, V> where
1970 V : Module <S>,
1971 V::LinearEndo : MaybeSerDes,
1972 S : Ring
1973{
1974 type Output = Self;
1975 fn mul (self, rhs : Self) -> Self::Output {
1976 LinearAuto (self.0 * rhs.0)
1977 }
1978}
1979impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
1980 V : Module <S>,
1981 V::LinearEndo : MaybeSerDes,
1982 S : Ring
1983{
1984 fn mul_assign (&mut self, rhs : Self) {
1985 self.0 *= rhs.0
1986 }
1987}
1988impl <S, V> num::One for LinearAuto <S, V> where
1989 V : Module <S>,
1990 V::LinearEndo : MaybeSerDes,
1991 S : Ring
1992{
1993 fn one() -> Self {
1994 LinearAuto (LinearIso::one())
1995 }
1996}
1997
1998impl <S, A, B, M> Affinity <S, A, B, M> where
2002 M : LinearMap <S, A::Vector, B::Vector>,
2003 A : AffineSpace <S>,
2004 B : AffineSpace <S>,
2005 S : Field + std::fmt::Display,
2006 B::Vector : std::fmt::Display
2007{
2008 pub const fn new (
2009 linear_iso : LinearIso <S, A::Vector, B::Vector, M>, translation : B::Vector
2010 ) -> Self {
2011 Affinity { linear_iso, translation, _phantom: PhantomData }
2012 }
2013}
2014
2015impl <S, V, W, P, Q, M> Projectivity <S, V, W, P, Q, M> where
2019 M : LinearMap <S, P, Q>,
2020 P : ProjectiveSpace <S, V>,
2021 Q : ProjectiveSpace <S, W>,
2022 V : VectorSpace <S> + std::fmt::Display,
2023 W : VectorSpace <S> + std::fmt::Display,
2024 S : Field + std::fmt::Display
2025{
2026 pub const fn new (linear_iso : LinearIso <S, P, Q, M>) -> Self {
2027 Projectivity (linear_iso, PhantomData)
2028 }
2029 pub fn transform (self, vector : P) -> Q {
2030 **self * vector
2031 }
2032}
2033impl <S, V, W, P, Q, M> std::ops::Deref for Projectivity <S, V, W, P, Q, M> where
2034 M : LinearMap <S, P, Q>,
2035 P : ProjectiveSpace <S, V>,
2036 Q : ProjectiveSpace <S, W>,
2037 V : VectorSpace <S> + std::fmt::Display,
2038 W : VectorSpace <S> + std::fmt::Display,
2039 S : Field + std::fmt::Display
2040{
2041 type Target = LinearIso <S, P, Q, M>;
2042 fn deref (&self) -> &Self::Target {
2043 &self.0
2044 }
2045}
2046
2047macro_rules! impl_angle {
2048 ( $angle:ident, $docname:expr ) => {
2049 #[doc = $docname]
2050 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2051 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2053 pub struct $angle <S> (pub S);
2054 impl_numcast_primitive!($angle);
2055 impl <S : Real> AdditiveGroup for $angle <S> { }
2056 impl <S : Real> AdditiveMonoid for $angle <S> { }
2057 impl <S : Ring> std::ops::Neg for $angle <S> {
2058 type Output = Self;
2059 fn neg (self) -> Self::Output {
2060 $angle (-self.0)
2061 }
2062 }
2063 impl <S : Ring> std::ops::Add for $angle <S> {
2064 type Output = Self;
2065 fn add (self, other : Self) -> Self::Output {
2066 $angle (self.0 + other.0)
2067 }
2068 }
2069 impl <S : Ring> std::ops::AddAssign for $angle <S> {
2070 fn add_assign (&mut self, other : Self) {
2071 self.0 += other.0
2072 }
2073 }
2074 impl <S : Ring> std::ops::Sub for $angle <S> {
2075 type Output = Self;
2076 fn sub (self, other : Self) -> Self::Output {
2077 $angle (self.0 - other.0)
2078 }
2079 }
2080 impl <S : Ring> std::ops::SubAssign for $angle <S> {
2081 fn sub_assign (&mut self, other : Self) {
2082 self.0 -= other.0
2083 }
2084 }
2085 impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2086 type Output = Self;
2087 fn mul (self, scalar : S) -> Self::Output {
2088 $angle (scalar * self.0)
2089 }
2090 }
2091 impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2092 fn mul_assign (&mut self, scalar : S) {
2093 self.0 *= scalar
2094 }
2095 }
2096 impl <S : Ring> std::ops::Div for $angle <S> {
2097 type Output = S;
2098 fn div (self, other : Self) -> Self::Output {
2099 self.0 / other.0
2100 }
2101 }
2102 impl <S : Ring> std::ops::Div <S> for $angle <S> {
2103 type Output = Self;
2104 fn div (self, scalar : S) -> Self::Output {
2105 $angle (self.0 / scalar)
2106 }
2107 }
2108 impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2109 fn div_assign (&mut self, scalar : S) {
2110 self.0 /= scalar
2111 }
2112 }
2113 impl <S : Ring> std::ops::Rem for $angle <S> {
2114 type Output = Self;
2115 fn rem (self, other : Self) -> Self::Output {
2116 $angle (self.0 % other.0)
2117 }
2118 }
2119 impl <S : Ring> num::Zero for $angle <S> {
2120 fn zero() -> Self {
2121 $angle (S::zero())
2122 }
2123 fn is_zero (&self) -> bool {
2124 self.0.is_zero()
2125 }
2126 }
2127 }
2128}
2129
2130macro_rules! impl_angle_wrapped {
2131 ( $angle:ident, $comment:expr ) => {
2132 #[doc = $comment]
2133 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2134 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2135 pub struct $angle <S> (Rad <S>);
2136
2137 impl_numcast!($angle);
2138 impl <S : Real> $angle <S> {
2139 pub const fn angle (&self) -> Rad <S> {
2140 self.0
2141 }
2142 }
2143 impl <S : Real> AdditiveGroup for $angle <S> { }
2144 impl <S : Real> AdditiveMonoid for $angle <S> { }
2145 impl <S : Real> std::ops::Neg for $angle <S> {
2146 type Output = Self;
2147 fn neg (self) -> Self::Output {
2148 self.map (Rad::neg)
2149 }
2150 }
2151 impl <S : Real> std::ops::Add for $angle <S> {
2152 type Output = Self;
2153 fn add (self, other : Self) -> Self::Output {
2154 self.map (|angle| angle + other.0)
2155 }
2156 }
2157 impl <S : Real> std::ops::AddAssign for $angle <S> {
2158 fn add_assign (&mut self, other : Self) {
2159 *self = *self + other
2160 }
2161 }
2162 impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2163 type Output = Self;
2164 fn add (self, angle : Rad <S>) -> Self::Output {
2165 self.map (|a| a + angle)
2166 }
2167 }
2168 impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2169 fn add_assign (&mut self, angle : Rad <S>) {
2170 *self = *self + angle
2171 }
2172 }
2173 impl <S : Real> std::ops::Sub for $angle <S> {
2174 type Output = Self;
2175 fn sub (self, other : Self) -> Self::Output {
2176 self.map (|angle| angle - other.0)
2177 }
2178 }
2179 impl <S : Real> std::ops::SubAssign for $angle <S> {
2180 fn sub_assign (&mut self, other : Self) {
2181 *self = *self - other
2182 }
2183 }
2184 impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2185 type Output = Self;
2186 fn sub (self, angle : Rad <S>) -> Self::Output {
2187 self.map (|a| a - angle)
2188 }
2189 }
2190 impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2191 fn sub_assign (&mut self, angle : Rad <S>) {
2192 *self = *self - angle
2193 }
2194 }
2195 impl <S : Real> std::ops::Mul <S> for $angle <S> {
2196 type Output = Self;
2197 fn mul (self, scalar : S) -> Self::Output {
2198 self.map (|angle| angle * scalar)
2199 }
2200 }
2201 impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2202 fn mul_assign (&mut self, scalar : S) {
2203 *self = *self * scalar
2204 }
2205 }
2206 impl <S : Real> std::ops::Div for $angle <S> {
2207 type Output = S;
2208 fn div (self, other : Self) -> Self::Output {
2209 self.0 / other.0
2210 }
2211 }
2212 impl <S : Real> std::ops::Div <S> for $angle <S> {
2213 type Output = Self;
2214 fn div (self, scalar : S) -> Self::Output {
2215 self.map (|angle| angle / scalar)
2216 }
2217 }
2218 impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2219 fn div_assign (&mut self, scalar : S) {
2220 *self = *self / scalar
2221 }
2222 }
2223 impl <S : Real> std::ops::Rem for $angle <S> {
2224 type Output = Self;
2225 fn rem (self, other : Self) -> Self::Output {
2226 self.map (|angle| angle % other.0)
2227 }
2228 }
2229 impl <S : Real> num::Zero for $angle <S> {
2230 fn zero() -> Self {
2231 $angle (Rad::zero())
2232 }
2233 fn is_zero (&self) -> bool {
2234 self.0.is_zero()
2235 }
2236 }
2237 }
2238}
2239
2240macro_rules! impl_dimension {
2241 ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2242 $point_fun:ident, $vector_fun:ident,
2243 [$($component:ident),+],
2244 [$(($axis_method:ident, $unit_method:ident)),+], [$($projective:ident)?],
2245 $matrix:ident, $affine:ident, $euclidean:ident, $ndims:expr, $dimension:expr
2246 ) => {
2247 #[doc = $dimension]
2248 #[doc = "position"]
2249 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2250 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2251 #[display("{}", _0)]
2252 #[repr(C)]
2253 pub struct $point <S> (pub $vector <S>);
2254
2255 #[doc = $dimension]
2256 #[doc = "affine space"]
2257 #[derive(Debug)]
2258 pub struct $affine <S> (PhantomData <S>);
2259 impl <S : Field> AffineSpace <S> for $affine <S> {
2260 type Point = $point <S>;
2261 type Vector = $vector <S>;
2262 }
2263
2264 #[doc = $dimension]
2265 #[doc = "euclidean space"]
2266 #[derive(Debug)]
2267 pub struct $euclidean <S> (PhantomData <S>);
2268 impl <S : Real> EuclideanSpace <S> for $euclidean <S> { }
2269 impl <S : Real> AffineSpace <S> for $euclidean <S> {
2270 type Point = $point <S>;
2271 type Vector = $vector <S>;
2272 }
2273
2274 #[doc = $dimension]
2275 #[doc = "non-zero vector"]
2276 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2277 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2278 #[display("{}", _0)]
2279 #[repr(C)]
2280 pub struct $nonzero <S> ($vector <S>);
2281
2282 #[doc = $dimension]
2283 #[doc = "unit vector"]
2284 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2285 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2286 #[display("{}", _0)]
2287 #[repr(C)]
2288 pub struct $unit <S> ($vector <S>);
2289
2290 #[doc = "Construct a"]
2294 #[doc = $dimension]
2295 #[doc = "point"]
2296 pub const fn $point_fun <S> ($($component : S),+) -> $point <S> {
2297 $point::new ($($component),+)
2298 }
2299 impl_numcast!($point);
2300 impl <S> $point <S> {
2301 pub const fn new ($($component : S),+) -> Self {
2302 $point ($vector::new ($($component),+))
2303 }
2304 }
2305 impl <S> Point <$vector <S>> for $point <S> where S : Ring {
2306 fn to_vector (self) -> $vector <S> {
2307 self.0
2308 }
2309 fn from_vector (vector : $vector <S>) -> Self {
2310 $point (vector)
2311 }
2312 }
2313 impl <S> From<[S; $ndims]> for $point <S> {
2314 fn from (array : [S; $ndims]) -> Self {
2315 $point (array.into())
2316 }
2317 }
2318 impl <S> std::cmp::PartialOrd for $point <S> where S : PartialOrd {
2319 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
2320 self.0.as_slice().partial_cmp (&other.0.as_slice())
2321 }
2322 }
2323 impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2324 type Output = Self;
2325 fn add (self, displacement : $vector <S>) -> Self::Output {
2326 $point (self.0 + displacement)
2327 }
2328 }
2329 impl <S> std::ops::Add <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2330 type Output = Self;
2331 fn add (self, displacement : &$vector <S>) -> Self::Output {
2332 $point (self.0 + *displacement)
2333 }
2334 }
2335 impl <S> std::ops::Add <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2336 type Output = $point <S>;
2337 fn add (self, displacement : $vector <S>) -> Self::Output {
2338 $point (self.0 + displacement)
2339 }
2340 }
2341 impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2342 S : AdditiveGroup + Copy
2343 {
2344 type Output = $point <S>;
2345 fn add (self, displacement : &$vector <S>) -> Self::Output {
2346 $point (self.0 + *displacement)
2347 }
2348 }
2349 impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where S : AdditiveGroup {
2350 fn add_assign (&mut self, displacement : $vector <S>) {
2351 self.0 += displacement
2352 }
2353 }
2354 impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2355 S : AdditiveGroup + Copy
2356 {
2357 fn add_assign (&mut self, displacement : &$vector <S>) {
2358 self.0 += *displacement
2359 }
2360 }
2361 impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2362 type Output = Self;
2363 fn sub (self, displacement : $vector <S>) -> Self::Output {
2364 $point (self.0 - displacement)
2365 }
2366 }
2367 impl <S> std::ops::Sub <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2368 type Output = Self;
2369 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2370 $point (self.0 - *displacement)
2371 }
2372 }
2373 impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2374 type Output = $vector <S>;
2375 fn sub (self, other : Self) -> Self::Output {
2376 self.0 - other.0
2377 }
2378 }
2379 impl <S> std::ops::Sub <&$point <S>> for $point <S> where S : AdditiveGroup + Copy {
2380 type Output = $vector <S>;
2381 fn sub (self, other : &Self) -> Self::Output {
2382 self.0 - other.0
2383 }
2384 }
2385 impl <S> std::ops::Sub <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2386 type Output = $point <S>;
2387 fn sub (self, displacement : $vector <S>) -> Self::Output {
2388 $point (self.0 - displacement)
2389 }
2390 }
2391 impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2392 S : AdditiveGroup + Copy
2393 {
2394 type Output = $point <S>;
2395 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2396 $point (self.0 - *displacement)
2397 }
2398 }
2399 impl <S> std::ops::Sub <$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2400 type Output = $vector <S>;
2401 fn sub (self, other : $point <S>) -> Self::Output {
2402 self.0 - other.0
2403 }
2404 }
2405 impl <S> std::ops::Sub <&$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2406 type Output = $vector <S>;
2407 fn sub (self, other : &$point <S>) -> Self::Output {
2408 self.0 - other.0
2409 }
2410 }
2411 impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2412 S : AdditiveGroup
2413 {
2414 fn sub_assign (&mut self, displacement : $vector <S>) {
2415 self.0 -= displacement
2416 }
2417 }
2418 impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2419 S : AdditiveGroup + Copy
2420 {
2421 fn sub_assign (&mut self, displacement : &$vector <S>) {
2422 self.0 -= *displacement
2423 }
2424 }
2425 impl <S> approx::AbsDiffEq for $point <S> where
2426 S : approx::AbsDiffEq,
2427 S::Epsilon : Copy
2428 {
2429 type Epsilon = S::Epsilon;
2430 fn default_epsilon() -> Self::Epsilon {
2431 S::default_epsilon()
2432 }
2433 #[inline]
2434 fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2435 self.0.abs_diff_eq (&other.0, epsilon)
2436 }
2437 }
2438 impl <S> approx::RelativeEq for $point <S> where
2439 S : approx::RelativeEq,
2440 S::Epsilon : Copy
2441 {
2442 fn default_max_relative() -> Self::Epsilon {
2443 S::default_max_relative()
2444 }
2445 #[inline]
2446 fn relative_eq (&self,
2447 other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2448 ) -> bool {
2449 self.0.relative_eq (&other.0, epsilon, max_relative)
2450 }
2451 }
2452 impl <S> approx::UlpsEq for $point <S> where
2453 S : approx::UlpsEq,
2454 S::Epsilon : Copy
2455 {
2456 fn default_max_ulps() -> u32 {
2457 S::default_max_ulps()
2458 }
2459 #[inline]
2460 fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2461 -> bool
2462 {
2463 self.0.ulps_eq (&other.0, epsilon, max_ulps)
2464 }
2465 }
2466 #[doc = "Construct a"]
2470 #[doc = $dimension]
2471 #[doc = "vector"]
2472 pub const fn $vector_fun <S> ($($component : S),+) -> $vector <S> {
2473 $vector::new ($($component),+)
2474 }
2475 impl <S : Field> InnerProductSpace <S> for $vector <S> { }
2476 impl <S : Ring> Dot <S> for $vector <S> {
2477 fn dot (self, other : Self) -> S {
2478 self.dot (other)
2479 }
2480 }
2481 impl <S : Field> VectorSpace <S> for $vector <S> {
2482 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2483 self.map (f)
2484 }
2485 }
2486 impl <S : Ring> Module <S> for $vector <S> {
2487 type LinearEndo = $matrix <S>;
2488 }
2489 impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2490 fn determinant (self) -> S {
2491 self.determinant()
2492 }
2493 fn transpose (self) -> Self {
2494 self.transposed()
2495 }
2496 }
2497 impl <S : Ring> MultiplicativeMonoid for $matrix <S> { }
2498 impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2499 fn action (self, point : $point <S>) -> $point <S> {
2500 point + self
2501 }
2502 }
2503 impl <S : Ring> AdditiveGroup for $vector <S> { }
2504 impl <S : Ring> AdditiveMonoid for $vector <S> { }
2505 impl <S : AdditiveGroup> Group for $vector <S> {
2506 fn identity() -> Self {
2507 Self::zero()
2508 }
2509 fn operation (a : Self, b : Self) -> Self {
2510 a + b
2511 }
2512 }
2513 impl <S> Point <$vector <S>> for $vector <S> where S : Ring {
2514 fn to_vector (self) -> $vector <S> {
2515 self
2516 }
2517 fn from_vector (vector : $vector <S>) -> Self {
2518 vector
2519 }
2520 }
2521 impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2522 S : Ring + MaybeSerDes
2523 {
2524 type Output = Self;
2525 fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2526 self * rhs.0
2527 }
2528 }
2529 impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for $vector <S> where
2530 S : Ring + MaybeSerDes
2531 {
2532 type Output = Self;
2533 fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>) -> Self::Output {
2534 self * rhs.0
2535 }
2536 }
2537 impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2538 S : Ring + num::Float + MaybeSerDes
2539 {
2540 type Output = Self;
2541 fn inv (self) -> Self::Output {
2542 LinearAuto (self.0.inv())
2543 }
2544 }
2545 impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2546 S : Ring + num::Float + MaybeSerDes
2547 {
2548 type Output = Self;
2549 fn div (self, rhs : Self) -> Self::Output {
2550 LinearAuto (self.0 / rhs.0)
2551 }
2552 }
2553 impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2554 S : Ring + num::Float + MaybeSerDes
2555 {
2556 fn div_assign (&mut self, rhs : Self) {
2557 self.0 /= rhs.0
2558 }
2559 }
2560 impl <S> MultiplicativeGroup for LinearAuto <S, $vector <S>> where
2561 S : Ring + num::Float + MaybeSerDes
2562 { }
2563 $(
2565 impl <S> ProjectiveSpace <S, $vector <S>> for $projective <S> where
2566 S : Field + std::fmt::Display
2567 {
2568 fn homography <A> (
2569 affinity : Affinity <S, A, A, <A::Vector as Module <S>>::LinearEndo>
2570 ) -> Projectivity <S, $vector <S>, $vector <S>, Self, Self, Self::LinearEndo>
2571 where A : AffineSpace <S, Vector=$vector <S>>
2572 {
2573 Projectivity::new (
2574 LinearIso::<S, Self, Self, Self::LinearEndo>::new (
2575 (*affinity.linear_iso).into()
2576 ).unwrap())
2577 }
2578 fn homogeneous <A> (point_or_vector : Either <A::Point, A::Vector>) -> Self where
2579 A : AffineSpace <S, Vector=$vector <S>>,
2580 $vector <S> : GroupAction <A::Point>
2581 {
2582 match point_or_vector {
2583 Either::Left (point) => (point.to_vector(), S::one()).into(),
2584 Either::Right (vector) => (vector, S::zero()).into(),
2585 }
2586 }
2587 }
2588 )?
2589 impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2593 V : Module <S>,
2594 W : Module <S>,
2595 S : Ring + num::Float
2596 {
2597 type Output = LinearIso <S, W, V, $matrix <S>>;
2598 fn inv (self) -> Self::Output {
2599 let mat4 = Matrix4::from (self.0);
2601 LinearIso (mat4.inverted().into(), PhantomData::default())
2602 }
2603 }
2604 impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2605 V : Module <S, LinearEndo=$matrix <S>>,
2606 S : Ring + num::Float
2607 {
2608 type Output = Self;
2609 #[expect(clippy::suspicious_arithmetic_impl)]
2610 fn div (self, rhs : Self) -> Self::Output {
2611 use num::Inv;
2612 self * rhs.inv()
2613 }
2614 }
2615 impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2616 V : Module <S, LinearEndo=$matrix <S>>,
2617 S : Ring + num::Float
2618 {
2619 #[expect(clippy::suspicious_op_assign_impl)]
2620 fn div_assign (&mut self, rhs : Self) {
2621 use num::Inv;
2622 *self *= rhs.inv()
2623 }
2624 }
2625 impl_numcast!($nonzero);
2629 impl <S : Ring> $nonzero <S> {
2630 pub fn new (vector : $vector <S>) -> Option <Self> {
2640 use num::Zero;
2641 if !vector.is_zero() {
2642 Some ($nonzero (vector))
2643 } else {
2644 None
2645 }
2646 }
2647 pub fn noisy (vector : $vector <S>) -> Self {
2656 use num::Zero;
2657 assert!(!vector.is_zero());
2658 $nonzero (vector)
2659 }
2660 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2672 Self::noisy (fun (self.0))
2673 }
2674 }
2675 impl <S : Ring> std::ops::Deref for $nonzero <S> {
2676 type Target = $vector <S>;
2677 fn deref (&self) -> &$vector <S> {
2678 &self.0
2679 }
2680 }
2681 impl_numcast!($unit);
2685 impl <S : Real> $unit <S> {
2686 $(
2692 #[inline]
2693 pub fn $axis_method() -> Self {
2694 $unit ($vector::$unit_method())
2695 }
2696 )+
2697 pub fn new (vector : $vector <S>) -> Option <Self> {
2701 let normalized = vector.normalize();
2702 if vector == normalized {
2703 Some ($unit (vector))
2704 } else {
2705 None
2706 }
2707 }
2708 pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2714 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2715 {
2716 if vector.is_normalized() {
2717 Some ($unit (vector))
2718 } else {
2719 None
2720 }
2721 }
2722 pub fn normalize (vector : $vector <S>) -> Self {
2743 use num::Zero;
2744 assert!(!vector.is_zero());
2745 $unit (vector.normalize())
2746 }
2747 pub fn normalize_approx (vector : $vector <S>) -> Self where
2750 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2751 {
2752 use num::Zero;
2753 assert!(!vector.is_zero());
2754 let vector = if vector.is_normalized() {
2755 vector
2756 } else {
2757 vector.normalize()
2758 };
2759 $unit (vector)
2760 }
2761 pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2770 assert_eq!(vector, vector.normalize());
2771 $unit (vector)
2772 }
2773 pub fn noisy_approx (vector : $vector <S>) -> Self where
2782 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2783 {
2784 assert!(vector.is_normalized());
2785 $unit (vector)
2786 }
2787 #[inline]
2791 pub fn unchecked (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2792 debug_assert_eq!(vector, vector.normalize());
2793 $unit (vector)
2794 }
2795 #[inline]
2804 pub fn unchecked_approx (vector : $vector <S>) -> Self where
2805 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2806 {
2807 debug_assert!(vector.is_normalized());
2808 $unit (vector)
2809 }
2810 pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2812 S : rand::distr::uniform::SampleUniform
2813 {
2814 let vector = $vector {
2815 $($component: rng.random_range (-S::one()..S::one())),+
2816 };
2817 $unit (vector.normalize())
2818 }
2819 pub fn invert (mut self) -> Self {
2822 self.0 = -self.0;
2823 self
2824 }
2825 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2837 S : std::fmt::Debug
2838 {
2839 Self::noisy (fun (self.0))
2840 }
2841 pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2853 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2854 {
2855 Self::noisy_approx (fun (self.0))
2856 }
2857 }
2858 impl <S : Real> std::ops::Deref for $unit <S> {
2859 type Target = $vector <S>;
2860 fn deref (&self) -> &$vector <S> {
2861 &self.0
2862 }
2863 }
2864 impl <S : Real> std::ops::Neg for $unit <S> {
2865 type Output = Self;
2866 fn neg (self) -> Self::Output {
2867 Self (-self.0)
2868 }
2869 }
2870 }
2872}
2873
2874macro_rules! impl_numcast {
2875 ($type:ident) => {
2876 impl <S> $type <S> {
2877 #[inline]
2878 pub fn numcast <T> (self) -> Option <$type <T>> where
2879 S : num::NumCast,
2880 T : num::NumCast
2881 {
2882 self.0.numcast().map ($type)
2883 }
2884 }
2885 }
2886}
2887
2888macro_rules! impl_numcast_primitive {
2889 ($type:ident) => {
2890 impl <S> $type <S> {
2891 #[inline]
2892 pub fn numcast <T> (self) -> Option <$type <T>> where
2893 S : num::NumCast,
2894 T : num::NumCast
2895 {
2896 T::from (self.0).map ($type)
2897 }
2898 }
2899 }
2900}
2901
2902#[doc(hidden)]
2903#[macro_export]
2904macro_rules! impl_numcast_fields {
2905 ($type:ident, $($field:ident),+) => {
2906 impl <S> $type <S> {
2907 #[inline]
2908 pub fn numcast <T> (self) -> Option <$type <T>> where
2909 S : num::NumCast,
2910 T : num::NumCast
2911 {
2912 Some ($type {
2913 $($field: self.$field.numcast()?),+
2914 })
2915 }
2916 }
2917 }
2918}
2919
2920impl_angle!(Deg, "Degrees");
2921impl_angle!(Rad, "Radians");
2922impl_angle!(Turn, "Turns");
2923impl_angle_wrapped!(AngleWrapped,
2924 "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
2925impl_angle_wrapped!(AngleWrappedSigned,
2926 "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
2927
2928impl_dimension!(Point2, Vector2, NonZero2, Unit2,
2929 point2, vector2,
2930 [x, y],
2931 [(axis_x, unit_x), (axis_y, unit_y)], [Vector3], Matrix2, Affine2, Euclidean2,
2932 2, "2D");
2933impl_dimension!(Point3, Vector3, NonZero3, Unit3,
2934 point3, vector3,
2935 [x, y, z],
2936 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
2937 [Vector4], Matrix3, Affine3, Euclidean3, 3, "3D");
2938impl_dimension!(Point4, Vector4, NonZero4, Unit4,
2939 point4, vector4,
2940 [x, y, z, w],
2941 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
2942 [], Matrix4, Affine4, Euclidean4, 4, "4D");
2943
2944impl_numcast_primitive!(Positive);
2945impl_numcast_primitive!(NonNegative);
2946impl_numcast_primitive!(NonZero);
2947impl_numcast_primitive!(Normalized);
2948impl_numcast_primitive!(NormalSigned);
2949impl_numcast_fields!(Angles3, yaw, pitch, roll);
2950
2951#[inline]
2955fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>) -> Quaternion <S> {
2956 Quaternion::from_vec4 (quaternion.into_vec4().normalize())
2957}
2958
2959#[cfg(test)]
2960mod tests {
2961 use super::*;
2962 use crate::num_traits;
2963 use approx;
2964 use rand;
2965 use rand_xorshift;
2966
2967 #[test]
2968 fn defaults() {
2969 use num_traits::Zero;
2970
2971 assert_eq!(Positive::<f32>::default().0, 0.0);
2972 assert_eq!(NonNegative::<f32>::default().0, 0.0);
2973 assert_eq!(Normalized::<f32>::default().0, 0.0);
2974 assert_eq!(NormalSigned::<f32>::default().0, 0.0);
2975 assert_eq!(Deg::<f32>::default().0, 0.0);
2976 assert_eq!(Rad::<f32>::default().0, 0.0);
2977 assert_eq!(Turn::<f32>::default().0, 0.0);
2978 assert_eq!(
2979 Angles3::<f32>::default(),
2980 Angles3::new (AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero()));
2981 assert_eq!(
2982 Pose3::<f32>::default(),
2983 Pose3 { position: Point3::origin(), angles: Angles3::default() });
2984 assert_eq!(
2985 LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
2986 Matrix3::identity());
2987 assert_eq!(LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
2988 assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
2989 assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
2990 assert_eq!(Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
2991 assert_eq!(
2992 AffineMap::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
2993 AffineMap::new (Matrix3::identity(), Vector3::zero()));
2994 assert_eq!(
2995 Affinity::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default(),
2996 Affinity::new (LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
2997 assert_eq!(
2998 Projectivity::<
2999 f32, Vector3 <f32>, Vector3 <f32>, Vector4 <f32>, Vector4 <f32>, Matrix4 <f32>
3000 >::default().0,
3001 LinearIso::new (Matrix4::identity()).unwrap());
3002 }
3003
3004 #[test]
3005 fn rotation3_noisy_approx() {
3006 use rand::{Rng, SeedableRng};
3007 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3010 let up = Vector3::unit_z();
3011 for _ in 0..1000 {
3012 let forward = vector3 (
3013 rng.random_range (-1000.0f32..1000.0),
3014 rng.random_range (-1000.0f32..1000.0),
3015 0.0
3016 ).normalized();
3017 let right = forward.cross (up);
3018 let mat = Matrix3::from_col_arrays ([
3019 right.into_array(),
3020 forward.into_array(),
3021 up.into_array()
3022 ]);
3023 let _ = Rotation3::noisy_approx (mat);
3024 }
3025 }
3026
3027 #[test]
3028 fn rotation3_intrinsic_angles() {
3029 use std::f32::consts::PI;
3030 use num_traits::Zero;
3031 use rand::{Rng, SeedableRng};
3032 let rot = Rotation3::from_angles_intrinsic (
3034 Turn (0.25).into(), Rad::zero(), Rad::zero());
3035 approx::assert_relative_eq!(*rot,
3036 Matrix3::from_col_arrays ([
3037 [ 0.0, 1.0, 0.0],
3038 [-1.0, 0.0, 0.0],
3039 [ 0.0, 0.0, 1.0]
3040 ])
3041 );
3042 assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3043 let rot = Rotation3::from_angles_intrinsic (
3044 Turn (0.5).into(), Rad::zero(), Rad::zero());
3045 approx::assert_relative_eq!(*rot,
3046 Matrix3::from_col_arrays ([
3047 [-1.0, 0.0, 0.0],
3048 [ 0.0, -1.0, 0.0],
3049 [ 0.0, 0.0, 1.0]
3050 ])
3051 );
3052 assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3053 let rot = Rotation3::from_angles_intrinsic (
3055 Rad::zero(), Turn (0.25).into(), Rad::zero());
3056 approx::assert_relative_eq!(*rot,
3057 Matrix3::from_col_arrays ([
3058 [1.0, 0.0, 0.0],
3059 [0.0, 0.0, 1.0],
3060 [0.0, -1.0, 0.0]
3061 ])
3062 );
3063 assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()), rot.intrinsic_angles());
3064 let rot = Rotation3::from_angles_intrinsic (
3066 Rad::zero(), Rad::zero(), Turn (0.25).into());
3067 approx::assert_relative_eq!(*rot,
3068 Matrix3::from_col_arrays ([
3069 [0.0, 0.0, -1.0],
3070 [0.0, 1.0, 0.0],
3071 [1.0, 0.0, 0.0]
3072 ])
3073 );
3074 assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()), rot.intrinsic_angles());
3075 let rot = Rotation3::from_angles_intrinsic (
3077 Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3078 approx::assert_relative_eq!(*rot,
3079 Matrix3::from_col_arrays ([
3080 [0.0, 1.0, 0.0],
3081 [0.0, 0.0, 1.0],
3082 [1.0, 0.0, 0.0]
3083 ])
3084 );
3085 let angles = rot.intrinsic_angles();
3086 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3087 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3088 approx::assert_relative_eq!(0.0, angles.2.0);
3089 let rot = Rotation3::from_angles_intrinsic (
3091 Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3092 approx::assert_relative_eq!(*rot,
3093 Matrix3::from_col_arrays ([
3094 [-1.0, 0.0, 0.0],
3095 [ 0.0, 0.0, 1.0],
3096 [ 0.0, 1.0, 0.0]
3097 ])
3098 );
3099 let angles = rot.intrinsic_angles();
3100 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3101 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3102 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3103
3104 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3107 let mut random_vector = || vector3 (
3108 rng.random_range (-100.0f32..100.0),
3109 rng.random_range (-100.0f32..100.0),
3110 rng.random_range (-100.0f32..100.0));
3111 for _ in 0..1000 {
3112 let rot = Rotation3::orthonormalize (
3113 random_vector(), random_vector(), random_vector()
3114 ).unwrap();
3115 let (yaw, pitch, roll) = rot.intrinsic_angles();
3116 assert!(yaw.0 < PI);
3117 assert!(yaw.0 > -PI);
3118 assert!(pitch.0 < PI);
3119 assert!(pitch.0 > -PI);
3120 assert!(roll.0 < PI);
3121 assert!(roll.0 > -PI);
3122 }
3123 }
3124
3125 #[test]
3126 fn rotation3_into_versor() {
3127 use std::f32::consts::PI;
3128 let rot = Rotation3::from_angle_x (Rad (0.01));
3129 let quat = rot.versor().0;
3130 approx::assert_relative_eq!(*rot, quat.into());
3131 let rot = Rotation3::from_angle_x (Rad (-0.01));
3132 let quat = rot.versor().0;
3133 approx::assert_relative_eq!(*rot, quat.into());
3134
3135 let rot = Rotation3::from_angle_y (Rad (0.01));
3136 let quat = rot.versor().0;
3137 approx::assert_relative_eq!(*rot, quat.into());
3138 let rot = Rotation3::from_angle_y (Rad (-0.01));
3139 let quat = rot.versor().0;
3140 approx::assert_relative_eq!(*rot, quat.into());
3141
3142 let rot = Rotation3::from_angle_z (Rad (0.01));
3143 let quat = rot.versor().0;
3144 approx::assert_relative_eq!(*rot, quat.into());
3145 let rot = Rotation3::from_angle_z (Rad (-0.01));
3146 let quat = rot.versor().0;
3147 approx::assert_relative_eq!(*rot, quat.into());
3148
3149 let rot = Rotation3::from_angle_x (Rad (PI / 2.0));
3150 let quat = rot.versor().0;
3151 approx::assert_relative_eq!(*rot, quat.into());
3152 let rot = Rotation3::from_angle_x (Rad (-PI / 2.0));
3153 let quat = rot.versor().0;
3154 approx::assert_relative_eq!(*rot, quat.into());
3155
3156 let rot = Rotation3::from_angle_y (Rad (PI / 2.0));
3157 let quat = rot.versor().0;
3158 approx::assert_relative_eq!(*rot, quat.into());
3159 let rot = Rotation3::from_angle_y (Rad (-PI / 2.0));
3160 let quat = rot.versor().0;
3161 approx::assert_relative_eq!(*rot, quat.into());
3162
3163 let rot = Rotation3::from_angle_z (Rad (PI / 2.0));
3164 let quat = rot.versor().0;
3165 approx::assert_relative_eq!(*rot, quat.into());
3166 let rot = Rotation3::from_angle_z (Rad (-PI / 2.0));
3167 let quat = rot.versor().0;
3168 approx::assert_relative_eq!(*rot, quat.into());
3169 }
3170}