1use std::marker::PhantomData;
2use derive_more::{Deref, Display, From, Neg};
3
4use crate::approx;
5use crate::num_traits as num;
6
7#[cfg(feature = "derive_serdes")]
8use serde::{Deserialize, Serialize};
9
10use crate::traits::*;
11
12pub mod coordinate;
13
14pub use vek::Vec2 as Vector2;
15pub use vek::Vec3 as Vector3;
16pub use vek::Vec4 as Vector4;
17pub use vek::Mat2 as Matrix2;
18pub use vek::Mat3 as Matrix3;
19pub use vek::Mat4 as Matrix4;
20pub use vek::Quaternion as Quaternion;
21
22pub use self::enums::{Axis2, Axis3, Axis4, Octant, Quadrant, Sign, SignedAxis1,
23 SignedAxis2, SignedAxis3, SignedAxis4};
24
25mod enums {
32 use strum::{EnumCount, EnumIter, FromRepr};
33 #[cfg(feature = "derive_serdes")]
34 use serde::{Deserialize, Serialize};
35
36 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
38 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
39 #[repr(u8)]
40 pub enum Sign {
41 Negative,
42 Zero,
43 Positive
44 }
45
46 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
48 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
49 #[repr(u8)]
50 pub enum Quadrant {
51 PosPos,
53 NegPos,
55 PosNeg,
57 NegNeg
59 }
60
61 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
63 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
64 #[repr(u8)]
65 pub enum Octant {
66 PosPosPos,
68 NegPosPos,
70 PosNegPos,
72 NegNegPos,
74 PosPosNeg,
76 NegPosNeg,
78 PosNegNeg,
80 NegNegNeg
82 }
83
84 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
86 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
87 #[repr(u8)]
88 pub enum Axis2 {
89 X=0,
90 Y
91 }
92
93 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
95 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
96 #[repr(u8)]
97 pub enum Axis3 {
98 X=0,
99 Y,
100 Z
101 }
102
103 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
105 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
106 #[repr(u8)]
107 pub enum Axis4 {
108 X=0,
109 Y,
110 Z,
111 W
112 }
113
114 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
116 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
117 #[repr(u8)]
118 pub enum SignedAxis1 {
119 NegX, PosX
120 }
121
122 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
124 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
125 #[repr(u8)]
126 pub enum SignedAxis2 {
127 NegX, PosX,
128 NegY, PosY
129 }
130
131 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
133 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
134 #[repr(u8)]
135 pub enum SignedAxis3 {
136 NegX, PosX,
137 NegY, PosY,
138 NegZ, PosZ
139 }
140
141 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
143 #[derive(Clone, Copy, Debug, Eq, PartialEq, EnumCount, EnumIter, FromRepr)]
144 #[repr(u8)]
145 pub enum SignedAxis4 {
146 NegX, PosX,
147 NegY, PosY,
148 NegZ, PosZ,
149 NegW, PosW
150 }
151}
152
153#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
159#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
160pub struct Positive <S> (S);
161
162#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
164#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
165pub struct NonNegative <S> (S);
166
167#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
169#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
170pub struct NonZero <S> (S);
171
172#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
174#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
175pub struct Normalized <S> (S);
176
177#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
179#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
180pub struct NormalSigned <S> (S);
181
182#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
188#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
189pub struct Angles3 <S> {
190 pub yaw : AngleWrapped <S>,
191 pub pitch : AngleWrapped <S>,
192 pub roll : AngleWrapped <S>
193}
194
195#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
197#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
198pub struct Pose3 <S> {
199 pub position : Point3 <S>,
200 pub angles : Angles3 <S>
201}
202
203#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
205#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
206#[display("{}", _0)]
207pub struct LinearIso <S, V, W, M> (M, PhantomData <(S, V, W)>);
208
209#[derive(Clone, Copy, Debug, Default, PartialEq, Deref, Display, From)]
211#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
212#[display("{}", _0)]
213pub struct LinearAuto <S, V> (pub LinearIso <S, V, V, V::LinearEndo>) where
214 V : Module <S>,
215 V::LinearEndo : MaybeSerDes,
216 S : Ring;
217
218#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
221#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
222#[derive(Clone, Copy, Debug, Default, PartialEq)]
223pub struct Rotation2 <S> (LinearAuto <S, Vector2 <S>>) where S : Ring + MaybeSerDes;
224
225#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
228#[cfg_attr(feature = "derive_serdes", serde(bound = "S : MaybeSerDes"))]
229#[derive(Clone, Copy, Debug, Default, PartialEq)]
230pub struct Rotation3 <S> (LinearAuto <S, Vector3 <S>>) where S : Ring + MaybeSerDes;
231
232#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
234#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
235pub struct Versor <S> (Quaternion <S>) where S : num::Zero + num::One;
236
237#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
239#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
240#[display("({}, {})", linear_map, translation)]
241pub struct AffineMap <S, A, B, M> where
242 A : AffineSpace <S>,
243 B : AffineSpace <S>,
244 S : Field,
245 M : LinearMap <S, A::Translation, B::Translation>
246{
247 pub linear_map : M,
248 pub translation : B::Translation,
249 pub _phantom : PhantomData <(A, S)>
250}
251
252#[derive(Clone, Copy, Debug, Default, Eq, 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 S : Field,
258 A : AffineSpace <S>,
259 B : AffineSpace <S>,
260 M : LinearMap <S, A::Translation, B::Translation>
261{
262 pub linear_iso : LinearIso <S, A::Translation, B::Translation, M>,
263 pub translation : B::Translation
264}
265
266#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display)]
268#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
269#[display("{}", _0)]
270pub struct Projectivity <S, P, Q, M> (
271 pub LinearIso <S, P::Translation, Q::Translation, M>
272) where
273 S : Field,
274 P : ProjectiveSpace <S>,
275 Q : ProjectiveSpace <S>;
276
277impl <S : Real> Angle <S> for Deg <S> {
285 fn full_turn() -> Self {
286 Deg (S::ten() * S::nine() * S::two() * S::two())
287 }
288 fn half_turn() -> Self {
289 Deg (S::ten() * S::nine() * S::two())
290 }
291}
292impl <S : Real> Trig for Deg <S> {
293 fn sin (self) -> Self {
294 Rad::from (self).sin().into()
295 }
296 fn sin_cos (self) -> (Self, Self) {
297 let (sin, cos) = Rad::from (self).sin_cos();
298 (sin.into(), cos.into())
299 }
300 fn cos (self) -> Self {
301 Rad::from (self).cos().into()
302 }
303 fn tan (self) -> Self {
304 Rad::from (self).tan().into()
305 }
306 fn asin (self) -> Self {
307 Rad::from (self).asin().into()
308 }
309 fn acos (self) -> Self {
310 Rad::from (self).acos().into()
311 }
312 fn atan (self) -> Self {
313 Rad::from (self).atan().into()
314 }
315 fn atan2 (self, other : Self) -> Self {
316 Rad::from (self).atan2 (Rad::from (other)).into()
317 }
318}
319impl <S : Real> From <Rad <S>> for Deg <S> {
320 fn from (radians : Rad <S>) -> Self {
321 let full_turns = radians / Rad::full_turn();
322 Deg::full_turn() * full_turns
323 }
324}
325impl <S : Real> From <Turn <S>> for Deg <S> {
326 fn from (turns : Turn <S>) -> Self {
327 Deg (turns.0 * Deg::full_turn().0)
328 }
329}
330
331impl <S : Real> Angle <S> for Rad <S> {
335 fn full_turn() -> Self {
336 Rad (S::pi() * S::two())
337 }
338}
339impl <S : Real> Trig for Rad <S> {
340 fn sin (self) -> Self {
341 Rad (self.0.sin())
342 }
343 fn sin_cos (self) -> (Self, Self) {
344 let (sin, cos) = self.0.sin_cos();
345 (Rad (sin), Rad (cos))
346 }
347 fn cos (self) -> Self {
348 Rad (self.0.cos())
349 }
350 fn tan (self) -> Self {
351 Rad (self.0.tan())
352 }
353 fn asin (self) -> Self {
354 Rad (self.0.asin())
355 }
356 fn acos (self) -> Self {
357 Rad (self.0.acos())
358 }
359 fn atan (self) -> Self {
360 Rad (self.0.atan())
361 }
362 fn atan2 (self, other : Self) -> Self {
363 Rad (self.0.atan2 (other.0))
364 }
365}
366impl <S : Real> From <Deg <S>> for Rad <S> {
367 fn from (degrees : Deg <S>) -> Self {
368 let full_turns = degrees / Deg::full_turn();
369 Rad::full_turn() * full_turns
370 }
371}
372impl <S : Real> From <Turn <S>> for Rad <S> {
373 fn from (turns : Turn <S>) -> Self {
374 Rad (turns.0 * Rad::full_turn().0)
375 }
376}
377
378impl <S : Real> Angle <S> for Turn <S> {
382 fn full_turn() -> Self {
383 Turn (S::one())
384 }
385 fn half_turn() -> Self {
386 Turn (S::half())
387 }
388}
389impl <S : Real> Trig for Turn <S> {
390 fn sin (self) -> Self {
391 Rad::from (self).sin().into()
392 }
393 fn sin_cos (self) -> (Self, Self) {
394 let (sin, cos) = Rad::from (self).sin_cos();
395 (sin.into(), cos.into())
396 }
397 fn cos (self) -> Self {
398 Rad::from (self).cos().into()
399 }
400 fn tan (self) -> Self {
401 Rad::from (self).tan().into()
402 }
403 fn asin (self) -> Self {
404 Rad::from (self).asin().into()
405 }
406 fn acos (self) -> Self {
407 Rad::from (self).acos().into()
408 }
409 fn atan (self) -> Self {
410 Rad::from (self).atan().into()
411 }
412 fn atan2 (self, other : Self) -> Self {
413 Rad::from (self).atan2 (Rad::from (other)).into()
414 }
415}
416impl <S : Real> From <Rad <S>> for Turn <S> {
417 fn from (radians : Rad <S>) -> Self {
418 Turn (radians.0 / Rad::full_turn().0)
419 }
420}
421impl <S : Real> From <Deg <S>> for Turn <S> {
422 fn from (degrees : Deg <S>) -> Self {
423 Turn (degrees.0 / Deg::full_turn().0)
424 }
425}
426
427impl <S : Real> AngleWrapped <S> {
431 pub fn wrap (angle : Rad <S>) -> Self {
432 AngleWrapped (angle.wrap_unsigned())
433 }
434
435 pub fn map <F> (self, f : F) -> Self where
436 F : FnOnce (Rad <S>) -> Rad <S>
437 {
438 AngleWrapped (f (self.0).wrap_unsigned())
439 }
440}
441
442impl <S : Real> AngleWrappedSigned <S> {
446 pub fn wrap (angle : Rad <S>) -> Self {
447 AngleWrappedSigned (angle.wrap_signed())
448 }
449
450 pub fn map <F> (self, f : F) -> Self where
451 F : FnOnce (Rad <S>) -> Rad <S>
452 {
453 AngleWrappedSigned (f (self.0).wrap_signed())
454 }
455}
456
457impl <S : Real> Angles3 <S> {
462 pub const fn new (
463 yaw : AngleWrapped <S>,
464 pitch : AngleWrapped <S>,
465 roll : AngleWrapped <S>
466 ) -> Self {
467 Angles3 { yaw, pitch, roll }
468 }
469
470 pub fn zero() -> Self {
471 use num::Zero;
472 Angles3::new (
473 AngleWrapped::zero(),
474 AngleWrapped::zero(),
475 AngleWrapped::zero())
476 }
477
478 pub fn wrap (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>) -> Self {
479 let yaw = AngleWrapped::wrap (yaw);
480 let pitch = AngleWrapped::wrap (pitch);
481 let roll = AngleWrapped::wrap (roll);
482 Angles3 { yaw, pitch, roll }
483 }
484}
485
486impl <S> From <Rotation3 <S>> for Angles3 <S> where S : Real + MaybeSerDes {
487 fn from (rotation : Rotation3 <S>) -> Self {
488 let (yaw, pitch, roll) = {
489 let (yaw, pitch, roll) = rotation.intrinsic_angles();
490 ( AngleWrapped::wrap (yaw),
491 AngleWrapped::wrap (pitch),
492 AngleWrapped::wrap (roll)
493 )
494 };
495 Angles3 { yaw, pitch, roll }
496 }
497}
498
499impl Axis2 {
503 #[inline]
504 pub const fn component (self) -> usize {
505 self as usize
506 }
507}
508
509impl Axis3 {
513 #[inline]
514 pub const fn component (self) -> usize {
515 self as usize
516 }
517}
518
519impl SignedAxis3 {
523 pub fn try_from <S : Field> (vector : &Vector3 <S>) -> Option <Self> {
524 if *vector == [ S::one(), S::zero(), S::zero()].into() {
525 Some (SignedAxis3::PosX)
526 } else if *vector == [-S::one(), S::zero(), S::zero()].into() {
527 Some (SignedAxis3::NegX)
528 } else if *vector == [ S::zero(), S::one(), S::zero()].into() {
529 Some (SignedAxis3::PosY)
530 } else if *vector == [ S::zero(), -S::one(), S::zero()].into() {
531 Some (SignedAxis3::NegY)
532 } else if *vector == [ S::zero(), S::zero(), S::one() ].into() {
533 Some (SignedAxis3::PosZ)
534 } else if *vector == [ S::zero(), S::zero(), -S::one() ].into() {
535 Some (SignedAxis3::NegZ)
536 } else {
537 None
538 }
539 }
540
541 pub fn to_vec <S : Field> (self) -> Vector3 <S> {
542 match self {
543 SignedAxis3::NegX => [-S::one(), S::zero(), S::zero()].into(),
544 SignedAxis3::PosX => [ S::one(), S::zero(), S::zero()].into(),
545 SignedAxis3::NegY => [ S::zero(), -S::one(), S::zero()].into(),
546 SignedAxis3::PosY => [ S::zero(), S::one(), S::zero()].into(),
547 SignedAxis3::NegZ => [ S::zero(), S::zero(), -S::one() ].into(),
548 SignedAxis3::PosZ => [ S::zero(), S::zero(), S::one() ].into()
549 }
550 }
551 #[inline]
552 pub fn to_unit <S> (self) -> Unit3 <S> where S : Real + std::fmt::Debug {
553 Unit3::unchecked (self.to_vec())
554 }
555}
556
557impl Quadrant {
561 pub fn from_vec_strict <S> (vector : &Vector2 <S>) -> Option <Quadrant> where
564 S : Ring + SignedExt
565 {
566 let sign_x = vector.x.sign();
567 let sign_y = vector.y.sign();
568 let quadrant = match (sign_x, sign_y) {
569 (Sign::Zero, _) |
570 ( _, Sign::Zero) => return None,
571 (Sign::Positive, Sign::Positive) => Quadrant::PosPos,
572 (Sign::Negative, Sign::Positive) => Quadrant::NegPos,
573 (Sign::Positive, Sign::Negative) => Quadrant::PosNeg,
574 (Sign::Negative, Sign::Negative) => Quadrant::NegNeg
575 };
576 Some (quadrant)
577 }
578 #[inline]
580 pub fn from_point_strict <S> (point : &Point2 <S>) -> Option <Quadrant> where
581 S : Ring + SignedExt
582 {
583 Quadrant::from_vec_strict (&point.to_vector())
584 }
585}
586impl Octant {
592 pub fn from_vec_strict <S> (vector : &Vector3 <S>) -> Option <Octant> where
595 S : Ring + SignedExt
596 {
597 let sign_x = vector.x.sign();
598 let sign_y = vector.y.sign();
599 let sign_z = vector.z.sign();
600 let octant = match (sign_x, sign_y, sign_z) {
601 (Sign::Zero, _, _) |
602 ( _, Sign::Zero, _) |
603 ( _, _, Sign::Zero) => return None,
604 (Sign::Positive, Sign::Positive, Sign::Positive) => Octant::PosPosPos,
605 (Sign::Negative, Sign::Positive, Sign::Positive) => Octant::NegPosPos,
606 (Sign::Positive, Sign::Negative, Sign::Positive) => Octant::PosNegPos,
607 (Sign::Negative, Sign::Negative, Sign::Positive) => Octant::NegNegPos,
608 (Sign::Positive, Sign::Positive, Sign::Negative) => Octant::PosPosNeg,
609 (Sign::Negative, Sign::Positive, Sign::Negative) => Octant::NegPosNeg,
610 (Sign::Positive, Sign::Negative, Sign::Negative) => Octant::PosNegNeg,
611 (Sign::Negative, Sign::Negative, Sign::Negative) => Octant::NegNegNeg
612 };
613 Some (octant)
614 }
615 #[inline]
617 pub fn from_point_strict <S> (point : &Point3 <S>) -> Option <Octant> where
618 S : Ring + SignedExt
619 {
620 Octant::from_vec_strict (&point.to_vector())
621 }
622}
623impl <S : OrderedRing> Positive <S> {
629 pub fn new (value : S) -> Option <Self> {
640 if value > S::zero() {
641 Some (Positive (value))
642 } else {
643 None
644 }
645 }
646 pub fn infinity() -> Self where S : num::float::FloatCore {
648 Positive (S::infinity())
649 }
650 pub fn noisy (value : S) -> Self {
659 assert!(value > S::zero());
660 Positive (value)
661 }
662 pub fn unchecked (value : S) -> Self {
672 debug_assert!(value > S::zero());
673 Positive (value)
674 }
675 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
696 Self::noisy (fun (self.0))
697 }
698}
699impl <S : Field> num::One for Positive <S> {
700 fn one() -> Self {
701 Positive (S::one())
702 }
703}
704impl <S : Ring> std::ops::Deref for Positive <S> {
705 type Target = S;
706 fn deref (&self) -> &S {
707 &self.0
708 }
709}
710impl <S : Ring> std::ops::Mul <Positive <S>> for Positive <S> {
711 type Output = Positive <S>;
712 fn mul (self, rhs : Positive <S>) -> Self::Output {
713 Positive (self.0 * *rhs)
714 }
715}
716impl <S : Ring> std::ops::MulAssign <Positive <S>> for Positive <S> {
717 fn mul_assign (&mut self, rhs : Positive <S>) {
718 self.0 *= *rhs
719 }
720}
721impl <S : Ring> std::ops::Mul <NonNegative <S>> for Positive <S> {
722 type Output = NonNegative <S>;
723 fn mul (self, rhs : NonNegative <S>) -> Self::Output {
724 NonNegative (self.0 * *rhs)
725 }
726}
727impl <S : Ring> std::ops::MulAssign <NonNegative <S>> for Positive <S> {
728 fn mul_assign (&mut self, rhs : NonNegative <S>) {
729 self.0 *= *rhs
730 }
731}
732impl <S : Field> std::ops::Div for Positive <S> {
733 type Output = Self;
734 fn div (self, rhs : Self) -> Self::Output {
735 Positive (self.0 / rhs.0)
736 }
737}
738impl <S : Field> std::ops::DivAssign for Positive <S> {
739 fn div_assign (&mut self, rhs : Self) {
740 self.0 /= rhs.0
741 }
742}
743impl <S : Ring> std::ops::Add for Positive <S> {
744 type Output = Self;
745 fn add (self, rhs : Self) -> Self::Output {
746 Positive (self.0 + rhs.0)
747 }
748}
749impl <S : Ring> std::ops::AddAssign for Positive <S> {
750 fn add_assign (&mut self, rhs : Self) {
751 self.0 += rhs.0
752 }
753}
754impl <S : Ring> std::ops::Add <NonNegative <S>> for Positive <S> {
755 type Output = Self;
756 fn add (self, rhs : NonNegative <S>) -> Self::Output {
757 Positive (self.0 + rhs.0)
758 }
759}
760impl <S : Ring> std::ops::AddAssign <NonNegative <S>> for Positive <S> {
761 fn add_assign (&mut self, rhs : NonNegative <S>) {
762 self.0 += rhs.0
763 }
764}
765impl <S : OrderedRing> NonNegative <S> {
771 pub fn new (value : S) -> Option <Self> {
782 if value >= S::zero() {
783 Some (NonNegative (value))
784 } else {
785 None
786 }
787 }
788 pub fn abs (value : S) -> Self {
798 NonNegative (value.abs())
799 }
800 pub fn noisy (value : S) -> Self {
809 assert!(S::zero() <= value);
810 NonNegative (value)
811 }
812 pub fn unchecked (value : S) -> Self {
822 debug_assert!(value >= S::zero());
823 NonNegative (value)
824 }
825 pub fn map_abs (self, fun : fn (S) -> S) -> Self {
835 Self::abs (fun (self.0))
836 }
837 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
855 Self::noisy (fun (self.0))
856 }
857}
858impl <S : Ring> From <Positive <S>> for NonNegative <S> {
859 fn from (positive : Positive <S>) -> Self {
860 NonNegative (*positive)
861 }
862}
863impl <S : Ring> num::Zero for NonNegative <S> {
864 fn zero() -> Self {
865 NonNegative (S::zero())
866 }
867 fn is_zero (&self) -> bool {
868 self.0.is_zero()
869 }
870}
871impl <S : Field> num::One for NonNegative <S> {
872 fn one() -> Self {
873 NonNegative (S::one())
874 }
875}
876impl <S : Ring> std::ops::Deref for NonNegative <S> {
877 type Target = S;
878 fn deref (&self) -> &S {
879 &self.0
880 }
881}
882impl <S : Ring> std::ops::Mul for NonNegative <S> {
883 type Output = Self;
884 fn mul (self, rhs : Self) -> Self::Output {
885 NonNegative (self.0 * rhs.0)
886 }
887}
888impl <S : Ring> std::ops::Mul <Positive <S>> for NonNegative <S> {
889 type Output = Self;
890 fn mul (self, rhs : Positive <S>) -> Self::Output {
891 NonNegative (self.0 * rhs.0)
892 }
893}
894impl <S : Field> std::ops::Div for NonNegative <S> {
895 type Output = Self;
896 fn div (self, rhs : Self) -> Self::Output {
897 NonNegative (self.0 / rhs.0)
898 }
899}
900impl <S : Ring> std::ops::Add for NonNegative <S> {
901 type Output = Self;
902 fn add (self, rhs : Self) -> Self::Output {
903 NonNegative (self.0 + rhs.0)
904 }
905}
906impl <S : Field> NonZero <S> {
912 #[inline]
923 pub fn new (value : S) -> Option <Self> {
924 if S::zero() != value {
925 Some (NonZero (value))
926 } else {
927 None
928 }
929 }
930 #[inline]
939 pub fn noisy (value : S) -> Self {
940 assert!(S::zero() != value);
941 NonZero (value)
942 }
943 #[inline]
963 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
964 Self::noisy (fun (self.0))
965 }
966}
967impl <S : Field> num::One for NonZero <S> {
968 fn one() -> Self {
969 NonZero (S::one())
970 }
971}
972impl <S : Field> std::ops::Deref for NonZero <S> {
973 type Target = S;
974 fn deref (&self) -> &S {
975 &self.0
976 }
977}
978impl <S : Field> std::ops::Mul for NonZero <S> {
979 type Output = Self;
980 fn mul (self, rhs : Self) -> Self::Output {
981 NonZero (self.0 * rhs.0)
982 }
983}
984impl <S : Field> Eq for NonZero <S> { }
985impl <S : OrderedField> Normalized <S> {
991 #[inline]
993 pub fn zero() -> Self {
994 Normalized (S::zero())
995 }
996 #[inline]
997 pub fn is_zero (&self) -> bool {
998 self.0.is_zero()
999 }
1000 #[inline]
1014 pub fn new (value : S) -> Option <Self> {
1015 if S::zero() <= value && value <= S::one() {
1016 Some (Normalized (value))
1017 } else {
1018 None
1019 }
1020 }
1021 #[inline]
1031 #[expect(clippy::same_name_method)]
1032 pub fn clamp (value : S) -> Self {
1033 let value = S::max (S::zero(), S::min (value, S::one()));
1034 Normalized (value)
1035 }
1036 #[inline]
1050 pub fn noisy (value : S) -> Self {
1051 assert!(value <= S::one());
1052 assert!(S::zero() <= value);
1053 Normalized (value)
1054 }
1055 #[inline]
1067 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1068 Self::clamp (fun (self.0))
1069 }
1070 #[inline]
1097 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1098 Self::noisy (fun (self.0))
1099 }
1100}
1101impl <S : Field> num::One for Normalized <S> {
1102 fn one() -> Self {
1103 Normalized (S::one())
1104 }
1105}
1106impl <S : Field> std::ops::Deref for Normalized <S> {
1107 type Target = S;
1108 fn deref (&self) -> &S {
1109 &self.0
1110 }
1111}
1112impl <S : Field> std::ops::Mul for Normalized <S> {
1113 type Output = Self;
1114 fn mul (self, rhs : Self) -> Self::Output {
1115 Normalized (self.0 * rhs.0)
1116 }
1117}
1118impl <S : Field> Eq for Normalized <S> { }
1119#[expect(clippy::derive_ord_xor_partial_ord)]
1120impl <S : OrderedField> Ord for Normalized <S> {
1121 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1122 self.partial_cmp (other).unwrap()
1124 }
1125}
1126impl <S : OrderedField> NormalSigned <S> {
1132 #[inline]
1134 pub fn zero() -> Self {
1135 NormalSigned (S::zero())
1136 }
1137 #[inline]
1138 pub fn is_zero (&self) -> bool {
1139 self.0.is_zero()
1140 }
1141 #[inline]
1155 pub fn new (value : S) -> Option <Self> {
1156 if -S::one() <= value && value <= S::one() {
1157 Some (NormalSigned (value))
1158 } else {
1159 None
1160 }
1161 }
1162 #[inline]
1172 #[expect(clippy::same_name_method)]
1173 pub fn clamp (value : S) -> Self {
1174 let value = S::max (-S::one(), S::min (value, S::one()));
1175 NormalSigned (value)
1176 }
1177 #[inline]
1191 pub fn noisy (value : S) -> Self {
1192 assert!(value <= S::one());
1193 assert!(-S::one() <= value);
1194 NormalSigned (value)
1195 }
1196 #[inline]
1208 pub fn map_clamp (self, fun : fn (S) -> S) -> Self {
1209 Self::clamp (fun (self.0))
1210 }
1211 #[inline]
1238 pub fn map_noisy (self, fun : fn (S) -> S) -> Self {
1239 Self::noisy (fun (self.0))
1240 }
1241}
1242impl <S : OrderedField> From <Normalized <S>> for NormalSigned <S> {
1243 fn from (Normalized (value) : Normalized <S>) -> Self {
1244 debug_assert!(S::zero() <= value);
1245 debug_assert!(value <= S::one());
1246 NormalSigned (value)
1247 }
1248}
1249impl <S : Field> num::One for NormalSigned <S> {
1250 fn one() -> Self {
1251 NormalSigned (S::one())
1252 }
1253}
1254impl <S : Field> std::ops::Deref for NormalSigned <S> {
1255 type Target = S;
1256 fn deref (&self) -> &S {
1257 &self.0
1258 }
1259}
1260impl <S : Field> std::ops::Mul for NormalSigned <S> {
1261 type Output = Self;
1262 fn mul (self, rhs : Self) -> Self::Output {
1263 NormalSigned (self.0 * rhs.0)
1264 }
1265}
1266impl <S : Field> Eq for NormalSigned <S> { }
1267#[expect(clippy::derive_ord_xor_partial_ord)]
1268impl <S : OrderedField> Ord for NormalSigned <S> {
1269 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
1270 self.partial_cmp (other).unwrap()
1272 }
1273}
1274impl <S : Field> std::ops::Neg for NormalSigned <S> {
1275 type Output = Self;
1276 fn neg (self) -> Self::Output {
1277 NormalSigned (-self.0)
1278 }
1279}
1280impl <S> Rotation2 <S> where S : Ring + MaybeSerDes {
1286 pub fn identity() -> Self {
1288 use num::One;
1289 Self::one()
1290 }
1291 pub fn new (mat : Matrix2 <S>) -> Option <Self> {
1296 let transform = LinearAuto (LinearIso::new (mat)?);
1297 if !transform.is_rotation() {
1298 None
1299 } else {
1300 Some (Rotation2 (transform))
1301 }
1302 }
1303 pub fn new_approx (mat : Matrix2 <S>) -> Option <Self> where
1309 S : approx::RelativeEq <Epsilon=S>
1310 {
1311 let four = S::one() + S::one() + S::one() + S::one();
1312 let thirtytwo = four * four * (S::one() + S::one());
1313 let epsilon = S::default_epsilon() * thirtytwo;
1314 let max_relative = S::default_max_relative() * four;
1315 if approx::relative_ne!(mat * mat.transposed(), Matrix2::identity(),
1316 max_relative=max_relative, epsilon=epsilon
1317 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1318 None
1319 } else {
1320 Some (Rotation2 (LinearAuto (LinearIso (mat, PhantomData))))
1321 }
1322 }
1323 pub fn from_angle (angle : Rad <S>) -> Self where S : num::real::Real {
1325 Rotation2 (LinearAuto (LinearIso (Matrix2::rotation_z (angle.0), PhantomData)))
1326 }
1327 pub fn noisy (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1331 assert_eq!(mat * mat.transposed(), Matrix2::identity());
1332 assert_eq!(mat.determinant(), S::one());
1333 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1334 }
1335 pub fn noisy_approx (mat : Matrix2 <S>) -> Self where
1340 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1341 {
1342 let four = S::one() + S::one() + S::one() + S::one();
1343 let epsilon = S::default_epsilon() * four;
1344 let max_relative = S::default_max_relative() * four;
1345 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1346 epsilon=epsilon, max_relative=max_relative);
1347 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1348 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1349 }
1350 pub fn unchecked (mat : Matrix2 <S>) -> Self where S : std::fmt::Debug {
1354 debug_assert!(mat * mat.transposed() == Matrix2::identity());
1355 debug_assert!(mat.determinant() == S::one());
1356 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1357 }
1358 pub fn unchecked_approx (mat : Matrix2 <S>) -> Self where
1363 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1364 {
1365 if cfg!(debug_assertions) {
1366 let four = S::one() + S::one() + S::one() + S::one();
1367 let epsilon = S::default_epsilon() * four;
1368 let max_relative = S::default_max_relative() * four;
1369 approx::assert_relative_eq!(mat * mat.transposed(), Matrix2::identity(),
1370 max_relative=max_relative, epsilon=epsilon);
1371 approx::assert_relative_eq!(mat.determinant(), S::one(),
1372 max_relative=max_relative);
1373 }
1374 Rotation2 (LinearAuto (LinearIso (mat, PhantomData)))
1375 }
1376 pub const fn mat (self) -> Matrix2 <S> {
1378 self.0.0.0
1379 }
1380 pub fn rotate (self, point : Point2 <S>) -> Point2 <S> {
1382 Point2::from (self * point.0)
1383 }
1384 pub fn rotate_around (self, point : Point2 <S>, center : Point2 <S>) -> Point2 <S> {
1386 self.rotate (point - center.0) + center.0
1387 }
1388}
1389impl <S> std::ops::Deref for Rotation2 <S> where S : Ring + MaybeSerDes {
1390 type Target = LinearAuto <S, Vector2 <S>>;
1391 fn deref (&self) -> &Self::Target {
1392 &self.0
1393 }
1394}
1395impl <S> num::Inv for Rotation2 <S> where S : Ring + MaybeSerDes {
1396 type Output = Self;
1397 fn inv (self) -> Self::Output {
1398 Rotation2 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1399 }
1400}
1401impl <S> std::ops::Mul <Vector2 <S>> for Rotation2 <S> where S : Ring + MaybeSerDes {
1402 type Output = Vector2 <S>;
1403 fn mul (self, rhs : Vector2 <S>) -> Self::Output {
1404 self.0 * rhs
1405 }
1406}
1407impl <S> std::ops::Mul <Rotation2 <S>> for Vector2 <S> where S : Ring + MaybeSerDes {
1408 type Output = Vector2 <S>;
1409 fn mul (self, rhs : Rotation2 <S>) -> Self::Output {
1410 self * rhs.0
1411 }
1412}
1413impl <S> std::ops::Mul for Rotation2 <S> where S : Ring + MaybeSerDes {
1414 type Output = Self;
1415 fn mul (self, rhs : Self) -> Self::Output {
1416 Rotation2 (self.0 * rhs.0)
1417 }
1418}
1419impl <S> std::ops::MulAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1420 fn mul_assign (&mut self, rhs : Self) {
1421 self.0 *= rhs.0
1422 }
1423}
1424impl <S> std::ops::Div for Rotation2 <S> where S : Ring + MaybeSerDes {
1425 type Output = Self;
1426 #[expect(clippy::suspicious_arithmetic_impl)]
1427 fn div (self, rhs : Self) -> Self::Output {
1428 use num::Inv;
1429 self * rhs.inv()
1430 }
1431}
1432impl <S> std::ops::DivAssign <Self> for Rotation2 <S> where S : Ring + MaybeSerDes {
1433 #[expect(clippy::suspicious_op_assign_impl)]
1434 fn div_assign (&mut self, rhs : Self) {
1435 use num::Inv;
1436 *self *= rhs.inv()
1437 }
1438}
1439impl <S> num::One for Rotation2 <S> where S : Ring + MaybeSerDes + num::Zero + num::One {
1440 fn one() -> Self {
1441 Rotation2 (LinearAuto (LinearIso (Matrix2::identity(), PhantomData)))
1442 }
1443}
1444
1445impl <S> Rotation3 <S> where S : Ring + MaybeSerDes {
1449 pub fn identity() -> Self {
1451 use num::One;
1452 Self::one()
1453 }
1454 pub fn new (mat : Matrix3 <S>) -> Option <Self> {
1459 if mat * mat.transposed() != Matrix3::identity() || mat.determinant() != S::one() {
1460 None
1461 } else {
1462 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1463 }
1464 }
1465 pub fn new_approx (mat : Matrix3 <S>) -> Option <Self> where
1471 S : approx::RelativeEq <Epsilon=S>
1472 {
1473 let four = S::one() + S::one() + S::one() + S::one();
1474 let thirtytwo = four * four * (S::one() + S::one());
1475 let epsilon = S::default_epsilon() * thirtytwo;
1476 let max_relative = S::default_max_relative() * four;
1477 if approx::relative_ne!(mat * mat.transposed(), Matrix3::identity(),
1478 max_relative=max_relative, epsilon=epsilon
1479 ) || approx::relative_ne!(mat.determinant(), S::one(), max_relative=max_relative) {
1480 None
1481 } else {
1482 Some (Rotation3 (LinearAuto (LinearIso (mat, PhantomData))))
1483 }
1484 }
1485 pub fn noisy (mat : Matrix3 <S>) -> Self {
1489 assert!(mat * mat.transposed() == Matrix3::identity());
1490 assert!(mat.determinant() == S::one());
1491 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1492 }
1493 pub fn noisy_approx (mat : Matrix3 <S>) -> Self where
1498 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1499 {
1500 let four = S::one() + S::one() + S::one() + S::one();
1501 let eight = four + S::one() + S::one() + S::one() + S::one();
1502 let epsilon = S::default_epsilon() * four;
1503 let max_relative = S::default_max_relative() * eight;
1504 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1505 max_relative=max_relative, epsilon=epsilon);
1506 approx::assert_relative_eq!(mat.determinant(), S::one(), max_relative=max_relative);
1507 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1508 }
1509 pub fn unchecked (mat : Matrix3 <S>) -> Self where S : std::fmt::Debug {
1513 debug_assert!(mat * mat.transposed() == Matrix3::identity());
1514 debug_assert!(mat.determinant() == S::one());
1515 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1516 }
1517 pub fn unchecked_approx (mat : Matrix3 <S>) -> Self where
1522 S : approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1523 {
1524 if cfg!(debug_assertions) {
1525 let four = S::one() + S::one() + S::one() + S::one();
1526 let epsilon = S::default_epsilon() * four;
1527 let max_relative = S::default_max_relative() * four;
1528 approx::assert_relative_eq!(mat * mat.transposed(), Matrix3::identity(),
1529 max_relative=max_relative, epsilon=epsilon);
1530 approx::assert_relative_eq!(mat.determinant(), S::one(),
1531 max_relative=max_relative);
1532 }
1533 Rotation3 (LinearAuto (LinearIso (mat, PhantomData)))
1534 }
1535 pub fn from_angle_x (angle : Rad <S>) -> Self where S : num::real::Real {
1539 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_x (angle.0), PhantomData)))
1540 }
1541 pub fn from_angle_y (angle : Rad <S>) -> Self where S : num::real::Real {
1545 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_y (angle.0), PhantomData)))
1546 }
1547 pub fn from_angle_z (angle : Rad <S>) -> Self where S : num::real::Real {
1551 Rotation3 (LinearAuto (LinearIso (Matrix3::rotation_z (angle.0), PhantomData)))
1552 }
1553 pub fn from_angles_intrinsic (yaw : Rad <S>, pitch : Rad <S>, roll : Rad <S>)
1559 -> Self where S : num::real::Real
1560 {
1561 let rotation1 = Rotation3::from_angle_z (yaw);
1562 let rotation2 = Rotation3::from_axis_angle (rotation1.cols.x, pitch) * rotation1;
1563 Rotation3::from_axis_angle (rotation2.cols.y, roll) * rotation2
1564 }
1565 pub fn from_axis_angle (axis : Vector3 <S>, angle : Rad <S>) -> Self where
1567 S : num::real::Real
1568 {
1569 Rotation3 (LinearAuto (LinearIso (
1570 Matrix3::rotation_3d (angle.0, axis), PhantomData)))
1571 }
1572 pub fn orthonormalize (v1 : Vector3 <S>, v2 : Vector3 <S>, v3 : Vector3 <S>)
1575 -> Option <Self> where S : Field + Sqrt
1576 {
1577 if Matrix3::from_col_arrays ([v1, v2, v3].map (Vector3::into_array)).determinant()
1578 == S::zero()
1579 {
1580 None
1581 } else {
1582 let project = |u : Vector3 <S>, v : Vector3 <S>| u * (u.dot (v) / u.self_dot());
1583 let u1 = v1;
1584 let u2 = v2 - project (u1, v2);
1585 let u3 = v3 - project (u1, v3) - project (u2, v3);
1586 Some (Rotation3 (LinearAuto (LinearIso (Matrix3::from_col_arrays ([
1587 u1.normalize().into_array(),
1588 u2.normalize().into_array(),
1589 u3.normalize().into_array()
1590 ]), PhantomData))))
1591 }
1592 }
1593
1594 pub fn look_at (point : Point3 <S>) -> Self where
1598 S : num::Float + num::FloatConst + approx::RelativeEq <Epsilon=S> + std::fmt::Debug
1599 {
1600 if point == Point::origin() {
1601 Self::identity()
1602 } else {
1603 use num::Zero;
1604 let forward = point.0.normalized();
1605 let right = {
1606 let projected = forward.with_z (S::zero());
1607 if !projected.is_zero() {
1608 Self::from_angle_z (-Rad (S::FRAC_PI_2())) * projected.normalized()
1609 } else {
1610 Vector3::unit_x()
1611 }
1612 };
1613 let up = right.cross (forward);
1614 let mat =
1615 Matrix3::from_col_arrays ([right, forward, up].map (Vector3::into_array));
1616 Self::noisy_approx (mat)
1617 }
1618 }
1619
1620 pub fn intrinsic_angles (&self) -> (Rad <S>, Rad <S>, Rad <S>) where S : Real {
1625 let cols = &self.cols;
1626 let yaw = Rad (S::atan2 (-cols.y.x, cols.y.y));
1627 let pitch = Rad (S::atan2 (cols.y.z, S::sqrt (S::one() - cols.y.z * cols.y.z)));
1628 let roll = Rad (S::atan2 (-cols.x.z, cols.z.z));
1629 (yaw, pitch, roll)
1630 }
1631
1632 pub fn versor (self) -> Versor <S> where
1636 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1637 {
1638 let diagonal = self.diagonal();
1639 let t = diagonal.sum();
1640 let m = MinMax::max (MinMax::max (MinMax::max (
1641 diagonal.x, diagonal.y), diagonal.z), t);
1642 let qmax = S::half() * Sqrt::sqrt (S::one() - t + S::two() * m);
1643 let qmax4_recip = (S::four() * qmax).recip();
1644 let [qx, qy, qz, qw] : [S; 4];
1645 let cols = self.cols;
1646 if m == diagonal.x {
1647 qx = qmax;
1648 qy = qmax4_recip * (cols.x.y + cols.y.x);
1649 qz = qmax4_recip * (cols.x.z + cols.z.x);
1650 qw = -qmax4_recip * (cols.z.y - cols.y.z);
1651 } else if m == diagonal.y {
1652 qx = qmax4_recip * (cols.x.y + cols.y.x);
1653 qy = qmax;
1654 qz = qmax4_recip * (cols.y.z + cols.z.y);
1655 qw = -qmax4_recip * (cols.x.z - cols.z.x);
1656 } else if m == diagonal.z {
1657 qx = qmax4_recip * (cols.x.z + cols.z.x);
1658 qy = qmax4_recip * (cols.y.z + cols.z.y);
1659 qz = qmax;
1660 qw = -qmax4_recip * (cols.y.x - cols.x.y);
1661 } else {
1662 qx = -qmax4_recip * (cols.z.y - cols.y.z);
1663 qy = -qmax4_recip * (cols.x.z - cols.z.x);
1664 qz = -qmax4_recip * (cols.y.x - cols.x.y);
1665 qw = qmax;
1666 }
1667 let quat = Quaternion::from_xyzw (qx, qy, qz, qw);
1668 Versor::unchecked_approx (quat)
1669 }
1670 pub const fn mat (self) -> Matrix3 <S> {
1672 self.0.0.0
1673 }
1674 pub fn rotate (self, point : Point3 <S>) -> Point3 <S> {
1676 Point3::from (self * point.0)
1677 }
1678 pub fn rotate_around (self, point : Point3 <S>, center : Point3 <S>) -> Point3 <S> {
1680 self.rotate (point - center.0) + center.0
1681 }
1682}
1683impl <S> std::ops::Deref for Rotation3 <S> where S : Ring + MaybeSerDes {
1684 type Target = LinearAuto <S, Vector3 <S>>;
1685 fn deref (&self) -> &Self::Target {
1686 &self.0
1687 }
1688}
1689impl <S> num::Inv for Rotation3 <S> where S : Ring + MaybeSerDes {
1690 type Output = Self;
1691 fn inv (self) -> Self::Output {
1692 Rotation3 (LinearAuto (LinearIso (self.0.0.0.transpose(), PhantomData)))
1693 }
1694}
1695impl <S> std::ops::Mul <Vector3 <S>> for Rotation3 <S> where S : Ring + MaybeSerDes {
1696 type Output = Vector3 <S>;
1697 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1698 self.0 * rhs
1699 }
1700}
1701impl <S> std::ops::Mul <Rotation3 <S>> for Vector3 <S> where S : Ring + MaybeSerDes {
1702 type Output = Vector3 <S>;
1703 fn mul (self, rhs : Rotation3 <S>) -> Self::Output {
1704 self * rhs.0
1705 }
1706}
1707impl <S> std::ops::Mul for Rotation3 <S> where S : Ring + MaybeSerDes {
1708 type Output = Self;
1709 fn mul (self, rhs : Self) -> Self::Output {
1710 Rotation3 (self.0 * rhs.0)
1711 }
1712}
1713impl <S> std::ops::MulAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
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 #[expect(clippy::suspicious_arithmetic_impl)]
1721 fn div (self, rhs : Self) -> Self::Output {
1722 use num::Inv;
1723 self * rhs.inv()
1724 }
1725}
1726impl <S> std::ops::DivAssign <Self> for Rotation3 <S> where S : Ring + MaybeSerDes {
1727 #[expect(clippy::suspicious_op_assign_impl)]
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 S : Ring + MaybeSerDes + num::Zero + num::One {
1734 fn one() -> Self {
1735 Rotation3 (LinearAuto (LinearIso (Matrix3::identity(), PhantomData)))
1736 }
1737}
1738impl <S> From <Angles3 <S>> for Rotation3 <S> where
1739 S : Real + num::real::Real + MaybeSerDes
1740{
1741 fn from (angles : Angles3 <S>) -> Self {
1742 Rotation3::from_angles_intrinsic (
1743 angles.yaw.angle(), angles.pitch.angle(), angles.roll.angle())
1744 }
1745}
1746
1747impl <S : Real> Versor <S> {
1751 pub fn normalize (quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1755 assert_ne!(quaternion, Quaternion::zero());
1756 Versor (normalize_quaternion (quaternion))
1757 }
1758 pub fn noisy (unit_quaternion : Quaternion <S>) -> Self where
1762 S : num::real::Real + std::fmt::Debug
1763 {
1764 assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1765 Versor (unit_quaternion)
1766 }
1767 pub fn noisy_approx (unit_quaternion : Quaternion <S>) -> Self where
1771 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1772 {
1773 assert!(unit_quaternion.into_vec4().is_normalized());
1774 Versor (unit_quaternion)
1775 }
1776 pub fn unchecked (unit_quaternion : Quaternion <S>) -> Self where S : std::fmt::Debug {
1780 debug_assert_eq!(unit_quaternion, normalize_quaternion (unit_quaternion));
1781 Versor (unit_quaternion)
1782 }
1783 pub fn unchecked_approx (unit_quaternion : Quaternion <S>) -> Self where
1787 S : num::real::Real + approx::RelativeEq <Epsilon=S>
1788 {
1789 debug_assert!(unit_quaternion.into_vec4().is_normalized());
1790 Versor (unit_quaternion)
1791 }
1792 pub fn from_scaled_axis (scaled_axis : Vector3 <S>) -> Self where
1795 S : std::fmt::Debug + num::Float
1796 {
1797 if scaled_axis == Vector3::zero() {
1798 let versor = Quaternion::rotation_3d (S::zero(), scaled_axis);
1799 debug_assert_eq!(versor.magnitude(), S::one());
1800 Versor (versor)
1801 } else {
1802 let angle = scaled_axis.magnitude();
1803 debug_assert!(S::zero() < angle);
1804 let axis = scaled_axis / angle;
1805 Versor (Quaternion::rotation_3d (angle, axis))
1806 }
1807 }
1808}
1809impl <S> std::ops::Mul <Vector3 <S>> for Versor <S> where S : Real + num::Float {
1810 type Output = Vector3 <S>;
1811 fn mul (self, rhs : Vector3 <S>) -> Self::Output {
1812 self.0 * rhs
1813 }
1814}
1815impl <S> From <Rotation3 <S>> for Versor <S> where
1816 S : Real + MaybeSerDes + num::real::Real + approx::RelativeEq <Epsilon=S>
1817{
1818 fn from (rot : Rotation3 <S>) -> Self {
1819 rot.versor()
1820 }
1821}
1822impl <S : Real> std::ops::Deref for Versor <S> {
1823 type Target = Quaternion <S>;
1824 fn deref (&self) -> &Quaternion <S> {
1825 &self.0
1826 }
1827}
1828impl <S, V, W, M> LinearIso <S, V, W, M> where
1834 M : LinearMap <S, V, W> + Copy,
1835 V : Module <S>,
1836 W : Module <S>,
1837 S : Ring
1838{
1839 pub fn mat (self) -> M {
1840 *self
1841 }
1842 pub fn is_invertible (linear_map : M) -> bool {
1844 linear_map.determinant() != S::zero()
1845 }
1846 pub fn is_invertible_approx (linear_map : M, epsilon : Option <S>) -> bool where
1848 S : approx::AbsDiffEq <Epsilon=S>
1849 {
1850 let epsilon = epsilon.unwrap_or_else (||{
1851 let four = S::one() + S::one() + S::one() + S::one();
1852 S::default_epsilon() * four
1853 });
1854 approx::abs_diff_ne!(linear_map.determinant(), S::zero(), epsilon=epsilon)
1855 }
1856 pub fn new (linear_map : M) -> Option <Self> {
1858 if Self::is_invertible (linear_map) {
1859 Some (LinearIso (linear_map, PhantomData))
1860 } else {
1861 None
1862 }
1863 }
1864 pub fn new_approx (linear_map : M, epsilon : Option <S>) -> Option <Self> where
1866 S : approx::RelativeEq <Epsilon=S>
1867 {
1868 if Self::is_invertible_approx (linear_map, epsilon) {
1869 Some (LinearIso (linear_map, PhantomData))
1870 } else {
1871 None
1872 }
1873 }
1874}
1875impl <S, V, W, M> std::ops::Deref for LinearIso <S, V, W, M> where
1876 M : LinearMap <S, V, W>,
1877 V : Module <S>,
1878 W : Module <S>,
1879 S : Ring
1880{
1881 type Target = M;
1882 fn deref (&self) -> &Self::Target {
1883 &self.0
1884 }
1885}
1886impl <S, V> num::One for LinearIso <S, V, V, V::LinearEndo> where
1887 V : Module <S>,
1888 S : Ring
1889{
1890 fn one () -> Self {
1891 LinearIso (V::LinearEndo::one(), PhantomData)
1892 }
1893}
1894impl <S, V, W, M> std::ops::Mul <V> 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 Output = W;
1901 fn mul (self, rhs : V) -> Self::Output {
1902 self.0 * rhs
1903 }
1904}
1905impl <S, V> std::ops::Mul for LinearIso <S, V, V, V::LinearEndo> where
1906 V : Module <S>,
1907 S : Ring
1908{
1909 type Output = Self;
1910 fn mul (self, rhs : Self) -> Self::Output {
1911 LinearIso (self.0 * rhs.0, PhantomData)
1912 }
1913}
1914impl <S, V> std::ops::MulAssign for LinearIso <S, V, V, V::LinearEndo> where
1915 V : Module <S>,
1916 S : Ring
1917{
1918 fn mul_assign (&mut self, rhs : Self) {
1919 self.0 *= rhs.0
1920 }
1921}
1922
1923impl <S, V> LinearAuto <S, V> where
1927 V : Module <S>,
1928 V::LinearEndo : MaybeSerDes,
1929 S : Ring
1930{
1931 pub fn mat (self) -> V::LinearEndo {
1932 **self
1933 }
1934 pub fn is_orthonormal (&self) -> bool {
1939 use num::One;
1940 let determinant = self.0.0.determinant();
1941 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1942 (determinant == S::one() || determinant == -S::one())
1943 }
1944 pub fn is_orthonormal_approx (&self) -> bool where
1950 S : approx::RelativeEq <Epsilon=S>,
1951 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1952 {
1953 use num::One;
1954 let four = S::one() + S::one() + S::one() + S::one();
1955 let epsilon = S::default_epsilon() * four;
1956 let max_relative = S::default_max_relative() * four;
1957 let determinant = self.0.0.determinant();
1958 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1959 max_relative=max_relative, epsilon=epsilon) &&
1960 ( approx::relative_eq!(determinant, S::one(), max_relative=max_relative) ||
1961 approx::relative_eq!(determinant, -S::one(), max_relative=max_relative) )
1962 }
1963 pub fn is_rotation (&self) -> bool {
1967 use num::One;
1968 let determinant = self.0.0.determinant();
1969 self.0.0 * self.0.0.transpose() == V::LinearEndo::one() &&
1970 determinant == S::one()
1971 }
1972 pub fn is_rotation_approx (&self) -> bool where
1977 S : approx::RelativeEq <Epsilon=S>,
1978 V::LinearEndo : approx::RelativeEq <Epsilon=S>
1979 {
1980 use num::One;
1981 let four = S::one() + S::one() + S::one() + S::one();
1982 let epsilon = S::default_epsilon() * four;
1983 let max_relative = S::default_max_relative() * four;
1984 let determinant = self.0.0.determinant();
1985 approx::relative_eq!(self.0.0 * self.0.0.transpose(), V::LinearEndo::one(),
1986 max_relative=max_relative, epsilon=epsilon) &&
1987 approx::relative_eq!(determinant, S::one(), max_relative=max_relative)
1988 }
1989}
1990impl <S, V> std::ops::Mul <V> for LinearAuto <S, V> where
1991 V : Module <S>,
1992 V::LinearEndo : MaybeSerDes,
1993 S : Ring
1994{
1995 type Output = V;
1996 fn mul (self, rhs : V) -> Self::Output {
1997 self.0 * rhs
1998 }
1999}
2000impl <S, V> std::ops::Mul for LinearAuto <S, V> where
2001 V : Module <S>,
2002 V::LinearEndo : MaybeSerDes,
2003 S : Ring
2004{
2005 type Output = Self;
2006 fn mul (self, rhs : Self) -> Self::Output {
2007 LinearAuto (self.0 * rhs.0)
2008 }
2009}
2010impl <S, V> std::ops::MulAssign <Self> for LinearAuto <S, V> where
2011 V : Module <S>,
2012 V::LinearEndo : MaybeSerDes,
2013 S : Ring
2014{
2015 fn mul_assign (&mut self, rhs : Self) {
2016 self.0 *= rhs.0
2017 }
2018}
2019impl <S, V> num::One for LinearAuto <S, V> where
2020 V : Module <S>,
2021 V::LinearEndo : MaybeSerDes,
2022 S : Ring
2023{
2024 fn one() -> Self {
2025 LinearAuto (LinearIso::one())
2026 }
2027}
2028
2029impl <S, A, B, M> AffineMap <S, A, B, M> where
2033 A : AffineSpace <S>,
2034 B : AffineSpace <S>,
2035 M : LinearMap <S, A::Translation, B::Translation>,
2036 S : Field
2037{
2038 pub const fn new (linear_map : M, translation : B::Translation) -> Self {
2039 AffineMap { linear_map, translation, _phantom: PhantomData }
2040 }
2041 pub fn map (self, point : A) -> B {
2042 B::from_vector (self.linear_map * point.to_vector() + self.translation)
2043 }
2044 pub fn transform (self, translation : A::Translation) -> B::Translation {
2045 self.linear_map * translation
2046 }
2047}
2048
2049impl <S, A, B, M> Affinity <S, A, B, M> where
2053 M : LinearMap <S, A::Translation, B::Translation>,
2054 A : AffineSpace <S>,
2055 B : AffineSpace <S>,
2056 S : Field
2057{
2058 pub const fn new (
2059 linear_iso : LinearIso <S, A::Translation, B::Translation, M>,
2060 translation : B::Translation
2061 ) -> Self {
2062 Affinity { linear_iso, translation }
2063 }
2064 pub fn mat (self) -> M {
2065 *self.linear_iso
2066 }
2067 pub fn map (self, point : A) -> B {
2068 B::from_vector (self.linear_iso * point.to_vector() + self.translation)
2069 }
2070 pub fn transform (self, translation : A::Translation) -> B::Translation {
2071 self.linear_iso * translation
2072 }
2073}
2074
2075impl <S, P, Q, M> Projectivity <S, P, Q, M> where
2079 M : LinearMap <S, P::Translation, Q::Translation>,
2080 P : ProjectiveSpace <S>,
2081 Q : ProjectiveSpace <S>,
2082 S : Field
2083{
2084 pub const fn new (linear_iso : LinearIso <S, P::Translation, Q::Translation, M>)
2085 -> Self
2086 {
2087 Projectivity (linear_iso)
2088 }
2089 pub fn mat (self) -> M {
2090 **self
2091 }
2092}
2093impl <S, P, Q, M> std::ops::Deref for Projectivity <S, P, Q, M> where
2094 M : LinearMap <S, P::Translation, Q::Translation>,
2095 P : ProjectiveSpace <S>,
2096 Q : ProjectiveSpace <S>,
2097 S : Field
2098{
2099 type Target = LinearIso <S, P::Translation, Q::Translation, M>;
2100 fn deref (&self) -> &Self::Target {
2101 &self.0
2102 }
2103}
2104impl <S, P, Q, M> std::ops::Mul <P> for Projectivity <S, P, Q, M> where
2105 M : LinearMap <S, P::Translation, Q::Translation>,
2106 P : ProjectiveSpace <S>,
2107 Q : ProjectiveSpace <S>,
2108 S : Field
2109{
2110 type Output = Q;
2111 fn mul (self, rhs : P) -> Q {
2112 Q::from_vector (self.0 * rhs.to_vector())
2113 }
2114}
2115
2116pub macro vector {
2117 ($x:expr, $y:expr) => {
2118 $crate::vector2 ($x, $y)
2119 },
2120 ($x:expr, $y:expr, $z:expr) => {
2121 $crate::vector3 ($x, $y, $z)
2122 },
2123 ($x:expr, $y:expr, $z:expr, $w:expr) => {
2124 $crate::vector4 ($x, $y, $z, $w)
2125 }
2126}
2127
2128pub macro matrix {
2129 ($v00:expr, $v01:expr; $v10:expr, $v11:expr$(;)?) => {
2130 $crate::Matrix2::new ($v00, $v01, $v10, $v11)
2131 },
2132 ( $v00:expr, $v01:expr, $v02:expr;
2133 $v10:expr, $v11:expr, $v12:expr;
2134 $v20:expr, $v21:expr, $v22:expr$(;)?
2135 ) => {
2136 $crate::Matrix3::new ($v00, $v01, $v02, $v10, $v11, $v12, $v20, $v21, $v22)
2137 },
2138 ( $v00:expr, $v01:expr, $v02:expr, $v03:expr;
2139 $v10:expr, $v11:expr, $v12:expr, $v13:expr;
2140 $v20:expr, $v21:expr, $v22:expr, $v23:expr;
2141 $v30:expr, $v31:expr, $v32:expr, $v33:expr$(;)?
2142 ) => {
2143 $crate::Matrix4::new (
2144 $v00, $v01, $v02, $v03,
2145 $v10, $v11, $v12, $v13,
2146 $v20, $v21, $v22, $v23,
2147 $v30, $v31, $v32, $v33)
2148 }
2149}
2150
2151macro_rules! impl_angle {
2152 ( $angle:ident, $docname:expr ) => {
2153 #[doc = $docname]
2154 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2155 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2157 pub struct $angle <S> (pub S);
2158 impl_numcast_primitive!($angle);
2159 impl <S : Ring> std::iter::Sum for $angle <S> {
2160 fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2161 use num::Zero;
2162 iter.fold ($angle::zero(), |acc, item| acc + item)
2163 }
2164 }
2165 impl <S : Ring> std::ops::Neg for $angle <S> {
2166 type Output = Self;
2167 fn neg (self) -> Self::Output {
2168 $angle (-self.0)
2169 }
2170 }
2171 impl <S : Ring> std::ops::Add for $angle <S> {
2172 type Output = Self;
2173 fn add (self, other : Self) -> Self::Output {
2174 $angle (self.0 + other.0)
2175 }
2176 }
2177 impl <S : Ring> std::ops::AddAssign for $angle <S> {
2178 fn add_assign (&mut self, other : Self) {
2179 self.0 += other.0
2180 }
2181 }
2182 impl <S : Ring> std::ops::Sub for $angle <S> {
2183 type Output = Self;
2184 fn sub (self, other : Self) -> Self::Output {
2185 $angle (self.0 - other.0)
2186 }
2187 }
2188 impl <S : Ring> std::ops::SubAssign for $angle <S> {
2189 fn sub_assign (&mut self, other : Self) {
2190 self.0 -= other.0
2191 }
2192 }
2193 impl <S : Ring> std::ops::Mul <S> for $angle <S> {
2194 type Output = Self;
2195 fn mul (self, scalar : S) -> Self::Output {
2196 $angle (scalar * self.0)
2197 }
2198 }
2199 impl <S : Ring> std::ops::MulAssign <S> for $angle <S> {
2200 fn mul_assign (&mut self, scalar : S) {
2201 self.0 *= scalar
2202 }
2203 }
2204 impl <S : Field> std::ops::Div for $angle <S> {
2205 type Output = S;
2206 fn div (self, other : Self) -> Self::Output {
2207 self.0 / other.0
2208 }
2209 }
2210 impl <S : Field> std::ops::Div <S> for $angle <S> {
2211 type Output = Self;
2212 fn div (self, scalar : S) -> Self::Output {
2213 $angle (self.0 / scalar)
2214 }
2215 }
2216 impl <S : Field> std::ops::DivAssign <S> for $angle <S> {
2217 fn div_assign (&mut self, scalar : S) {
2218 self.0 /= scalar
2219 }
2220 }
2221 impl <S : OrderedField> std::ops::Rem for $angle <S> {
2222 type Output = Self;
2223 fn rem (self, other : Self) -> Self::Output {
2224 $angle (self.0 % other.0)
2225 }
2226 }
2227 impl <S : Ring> num::Zero for $angle <S> {
2228 fn zero() -> Self {
2229 $angle (S::zero())
2230 }
2231 fn is_zero (&self) -> bool {
2232 self.0.is_zero()
2233 }
2234 }
2235 impl <S : Ring> From <S> for $angle <S> {
2236 fn from (s : S) -> Self {
2237 $angle (s)
2238 }
2239 }
2240 }
2241}
2242
2243macro_rules! impl_angle_wrapped {
2244 ( $angle:ident, $comment:expr ) => {
2245 #[doc = $comment]
2246 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2247 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd)]
2248 pub struct $angle <S> (Rad <S>);
2249
2250 impl_numcast!($angle);
2251 impl <S : Real> $angle <S> {
2252 pub const fn angle (&self) -> Rad <S> {
2253 self.0
2254 }
2255 }
2256 impl <S : Real> std::iter::Sum for $angle <S> {
2257 fn sum <I> (iter : I) -> Self where I : Iterator <Item = Self> {
2258 use num::Zero;
2259 iter.fold ($angle::zero(), |acc, item| acc + item)
2260 }
2261 }
2262 impl <S : Real> std::ops::Neg for $angle <S> {
2263 type Output = Self;
2264 fn neg (self) -> Self::Output {
2265 self.map (Rad::neg)
2266 }
2267 }
2268 impl <S : Real> std::ops::Add for $angle <S> {
2269 type Output = Self;
2270 fn add (self, other : Self) -> Self::Output {
2271 self.map (|angle| angle + other.0)
2272 }
2273 }
2274 impl <S : Real> std::ops::AddAssign for $angle <S> {
2275 fn add_assign (&mut self, other : Self) {
2276 *self = *self + other
2277 }
2278 }
2279 impl <S : Real> std::ops::Add <Rad <S>> for $angle <S> {
2280 type Output = Self;
2281 fn add (self, angle : Rad <S>) -> Self::Output {
2282 self.map (|a| a + angle)
2283 }
2284 }
2285 impl <S : Real> std::ops::AddAssign <Rad <S>> for $angle <S> {
2286 fn add_assign (&mut self, angle : Rad <S>) {
2287 *self = *self + angle
2288 }
2289 }
2290 impl <S : Real> std::ops::Sub for $angle <S> {
2291 type Output = Self;
2292 fn sub (self, other : Self) -> Self::Output {
2293 self.map (|angle| angle - other.0)
2294 }
2295 }
2296 impl <S : Real> std::ops::SubAssign for $angle <S> {
2297 fn sub_assign (&mut self, other : Self) {
2298 *self = *self - other
2299 }
2300 }
2301 impl <S : Real> std::ops::Sub <Rad <S>> for $angle <S> {
2302 type Output = Self;
2303 fn sub (self, angle : Rad <S>) -> Self::Output {
2304 self.map (|a| a - angle)
2305 }
2306 }
2307 impl <S : Real> std::ops::SubAssign <Rad <S>> for $angle <S> {
2308 fn sub_assign (&mut self, angle : Rad <S>) {
2309 *self = *self - angle
2310 }
2311 }
2312 impl <S : Real> std::ops::Mul <S> for $angle <S> {
2313 type Output = Self;
2314 fn mul (self, scalar : S) -> Self::Output {
2315 self.map (|angle| angle * scalar)
2316 }
2317 }
2318 impl <S : Real> std::ops::MulAssign <S> for $angle <S> {
2319 fn mul_assign (&mut self, scalar : S) {
2320 *self = *self * scalar
2321 }
2322 }
2323 impl <S : Real> std::ops::Div for $angle <S> {
2324 type Output = S;
2325 fn div (self, other : Self) -> Self::Output {
2326 self.0 / other.0
2327 }
2328 }
2329 impl <S : Real> std::ops::Div <S> for $angle <S> {
2330 type Output = Self;
2331 fn div (self, scalar : S) -> Self::Output {
2332 self.map (|angle| angle / scalar)
2333 }
2334 }
2335 impl <S : Real> std::ops::DivAssign <S> for $angle <S> {
2336 fn div_assign (&mut self, scalar : S) {
2337 *self = *self / scalar
2338 }
2339 }
2340 impl <S : Real> std::ops::Rem for $angle <S> {
2341 type Output = Self;
2342 fn rem (self, other : Self) -> Self::Output {
2343 self.map (|angle| angle % other.0)
2344 }
2345 }
2346 impl <S : Real> num::Zero for $angle <S> {
2347 fn zero() -> Self {
2348 $angle (Rad::zero())
2349 }
2350 fn is_zero (&self) -> bool {
2351 self.0.is_zero()
2352 }
2353 }
2354 }
2355}
2356
2357macro_rules! impl_dimension {
2358 ( $point:ident, $vector:ident, $nonzero:ident, $unit:ident,
2359 $point_fun:ident, $vector_fun:ident, $matrix_fun:ident,
2360 [$($component:ident),+],
2361 [$(($axis_method:ident, $unit_method:ident)),+], [$($patch:ident)?],
2362 [$($projective:ident)?],
2363 $matrix:ident, [$($submatrix:ident)?], $ndims:expr, $dimension:expr
2364 ) => {
2365 #[doc = $dimension]
2366 #[doc = "position"]
2367 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Display, From, Neg)]
2368 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2369 #[display("{}", _0)]
2370 #[repr(C)]
2371 pub struct $point <S> (pub $vector <S>);
2372
2373 #[doc = $dimension]
2374 #[doc = "non-zero vector"]
2375 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2376 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2377 #[display("{}", _0)]
2378 #[repr(C)]
2379 pub struct $nonzero <S> ($vector <S>);
2380
2381 #[doc = $dimension]
2382 #[doc = "unit vector"]
2383 #[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
2384 #[derive(Clone, Copy, Debug, Eq, PartialEq, Display)]
2385 #[display("{}", _0)]
2386 #[repr(C)]
2387 pub struct $unit <S> ($vector <S>);
2388
2389 #[doc = "Construct a"]
2393 #[doc = $dimension]
2394 #[doc = "point"]
2395 pub const fn $point_fun <S> ($($component : S),+) -> $point <S> {
2396 $point::new ($($component),+)
2397 }
2398 impl_numcast!($point);
2399 impl <S> $point <S> {
2400 pub const fn new ($($component : S),+) -> Self {
2401 $point ($vector::new ($($component),+))
2402 }
2403 $(
2404 pub const fn $component (&self) -> S where S : Copy {
2405 self.0.$component
2406 }
2407 )+
2408 pub fn distance (self, other : $point <S>) -> S where S : num::real::Real {
2409 self.0.distance (other.0)
2410 }
2411 pub fn distance_squared (self, other : $point <S>) -> S where S : Field {
2412 self.0.distance_squared (other.0)
2413 }
2414 }
2415 $(
2417 impl <S : Field> ProjectiveSpace <S> for $projective <S> {
2418 type Patch = $point <S>;
2419 }
2420 )?
2421 impl <S : Field> AffineSpace <S> for $point <S> {
2422 type Translation = $vector <S>;
2423 }
2424 impl <S : Ring> Point <$vector <S>> for $point <S> {
2425 fn to_vector (self) -> $vector <S> {
2426 self.0
2427 }
2428 fn from_vector (vector : $vector <S>) -> Self {
2429 $point (vector)
2430 }
2431 }
2432 impl <S> From <[S; $ndims]> for $point <S> {
2433 fn from (array : [S; $ndims]) -> Self {
2434 $point (array.into())
2435 }
2436 }
2437 $(
2438 impl <S> From <($patch <S>, S)> for $point <S> {
2439 fn from ((patch, scale) : ($patch <S>, S)) -> Self {
2440 $point ((patch.0, scale).into())
2441 }
2442 }
2443 )?
2444 impl <S> std::cmp::PartialOrd for $point <S> where S : PartialOrd {
2445 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
2446 self.0.as_slice().partial_cmp (&other.0.as_slice())
2447 }
2448 }
2449 impl <S> std::ops::Add <$vector <S>> for $point <S> where S : AdditiveGroup {
2450 type Output = Self;
2451 fn add (self, displacement : $vector <S>) -> Self::Output {
2452 $point (self.0 + displacement)
2453 }
2454 }
2455 impl <S> std::ops::Add <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2456 type Output = Self;
2457 fn add (self, displacement : &$vector <S>) -> Self::Output {
2458 $point (self.0 + *displacement)
2459 }
2460 }
2461 impl <S> std::ops::Add <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2462 type Output = $point <S>;
2463 fn add (self, displacement : $vector <S>) -> Self::Output {
2464 $point (self.0 + displacement)
2465 }
2466 }
2467 impl <S> std::ops::Add <&$vector <S>> for &$point <S> where
2468 S : AdditiveGroup + Copy
2469 {
2470 type Output = $point <S>;
2471 fn add (self, displacement : &$vector <S>) -> Self::Output {
2472 $point (self.0 + *displacement)
2473 }
2474 }
2475 impl <S> std::ops::AddAssign <$vector <S>> for $point <S> where S : AdditiveGroup {
2476 fn add_assign (&mut self, displacement : $vector <S>) {
2477 self.0 += displacement
2478 }
2479 }
2480 impl <S> std::ops::AddAssign <&$vector <S>> for $point <S> where
2481 S : AdditiveGroup + Copy
2482 {
2483 fn add_assign (&mut self, displacement : &$vector <S>) {
2484 self.0 += *displacement
2485 }
2486 }
2487 impl <S> std::ops::Sub <$vector <S>> for $point <S> where S : AdditiveGroup {
2488 type Output = Self;
2489 fn sub (self, displacement : $vector <S>) -> Self::Output {
2490 $point (self.0 - displacement)
2491 }
2492 }
2493 impl <S> std::ops::Sub <&$vector <S>> for $point <S> where S : AdditiveGroup + Copy {
2494 type Output = Self;
2495 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2496 $point (self.0 - *displacement)
2497 }
2498 }
2499 impl <S> std::ops::Sub <$point <S>> for $point <S> where S : AdditiveGroup {
2500 type Output = $vector <S>;
2501 fn sub (self, other : Self) -> Self::Output {
2502 self.0 - other.0
2503 }
2504 }
2505 impl <S> std::ops::Sub <&$point <S>> for $point <S> where S : AdditiveGroup + Copy {
2506 type Output = $vector <S>;
2507 fn sub (self, other : &Self) -> Self::Output {
2508 self.0 - other.0
2509 }
2510 }
2511 impl <S> std::ops::Sub <$vector <S>> for &$point <S> where S : AdditiveGroup + Copy {
2512 type Output = $point <S>;
2513 fn sub (self, displacement : $vector <S>) -> Self::Output {
2514 $point (self.0 - displacement)
2515 }
2516 }
2517 impl <S> std::ops::Sub <&$vector <S>> for &$point <S> where
2518 S : AdditiveGroup + Copy
2519 {
2520 type Output = $point <S>;
2521 fn sub (self, displacement : &$vector <S>) -> Self::Output {
2522 $point (self.0 - *displacement)
2523 }
2524 }
2525 impl <S> std::ops::Sub <$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2526 type Output = $vector <S>;
2527 fn sub (self, other : $point <S>) -> Self::Output {
2528 self.0 - other.0
2529 }
2530 }
2531 impl <S> std::ops::Sub <&$point <S>> for &$point <S> where S : AdditiveGroup + Copy {
2532 type Output = $vector <S>;
2533 fn sub (self, other : &$point <S>) -> Self::Output {
2534 self.0 - other.0
2535 }
2536 }
2537 impl <S> std::ops::SubAssign <$vector <S>> for $point <S> where
2538 S : AdditiveGroup
2539 {
2540 fn sub_assign (&mut self, displacement : $vector <S>) {
2541 self.0 -= displacement
2542 }
2543 }
2544 impl <S> std::ops::SubAssign <&$vector <S>> for $point <S> where
2545 S : AdditiveGroup + Copy
2546 {
2547 fn sub_assign (&mut self, displacement : &$vector <S>) {
2548 self.0 -= *displacement
2549 }
2550 }
2551 impl <S> approx::AbsDiffEq for $point <S> where
2552 S : approx::AbsDiffEq,
2553 S::Epsilon : Copy
2554 {
2555 type Epsilon = S::Epsilon;
2556 fn default_epsilon() -> Self::Epsilon {
2557 S::default_epsilon()
2558 }
2559 #[inline]
2560 fn abs_diff_eq (&self, other : &Self, epsilon : Self::Epsilon) -> bool {
2561 self.0.abs_diff_eq (&other.0, epsilon)
2562 }
2563 }
2564 impl <S> approx::RelativeEq for $point <S> where
2565 S : approx::RelativeEq,
2566 S::Epsilon : Copy
2567 {
2568 fn default_max_relative() -> Self::Epsilon {
2569 S::default_max_relative()
2570 }
2571 #[inline]
2572 fn relative_eq (&self,
2573 other : &Self, epsilon : Self::Epsilon, max_relative : Self::Epsilon
2574 ) -> bool {
2575 self.0.relative_eq (&other.0, epsilon, max_relative)
2576 }
2577 }
2578 impl <S> approx::UlpsEq for $point <S> where
2579 S : approx::UlpsEq,
2580 S::Epsilon : Copy
2581 {
2582 fn default_max_ulps() -> u32 {
2583 S::default_max_ulps()
2584 }
2585 #[inline]
2586 fn ulps_eq (&self, other : &Self, epsilon : Self::Epsilon, max_ulps : u32)
2587 -> bool
2588 {
2589 self.0.ulps_eq (&other.0, epsilon, max_ulps)
2590 }
2591 }
2592 #[doc = "Construct a"]
2596 #[doc = $dimension]
2597 #[doc = "vector"]
2598 pub const fn $vector_fun <S> ($($component : S),+) -> $vector <S> {
2599 $vector::new ($($component),+)
2600 }
2601 impl <S> InnerProductSpace <S> for $vector <S> where S : Field {
2602 fn outer_product (self, rhs : Self) -> $matrix <S> {
2603 let mut cols : $vector <$vector <S>> = [$vector::zero(); $ndims].into();
2604 for col in 0..$ndims {
2605 for row in 0..$ndims {
2606 cols[col][row] = self[row] * rhs[col];
2607 }
2608 }
2609 $matrix { cols }
2610 }
2611 }
2612 impl <S : Ring> Dot <S> for $vector <S> {
2613 fn dot (self, other : Self) -> S {
2614 self.dot (other)
2615 }
2616 }
2617 impl <S : Field> VectorSpace <S> for $vector <S> {
2618 fn map <F> (self, f : F) -> Self where F : FnMut (S) -> S {
2619 self.map (f)
2620 }
2621 }
2622 impl <S> Module <S> for $vector <S> where S : Ring + num::MulAdd {
2623 type LinearEndo = $matrix <S>;
2624 }
2625 impl <S> GroupAction <$point <S>> for $vector <S> where S : AdditiveGroup {
2626 fn action (self, point : $point <S>) -> $point <S> {
2627 point + self
2628 }
2629 }
2630 impl <S : AdditiveGroup> Group for $vector <S> {
2631 fn identity() -> Self {
2632 Self::zero()
2633 }
2634 fn operation (a : Self, b : Self) -> Self {
2635 a + b
2636 }
2637 }
2638 impl <S> std::ops::Mul <LinearAuto <S, Self>> for $vector <S> where
2639 S : Ring + MaybeSerDes
2640 {
2641 type Output = Self;
2642 fn mul (self, rhs : LinearAuto <S, Self>) -> Self::Output {
2643 self * rhs.0
2644 }
2645 }
2646 impl <S> std::ops::Mul <LinearIso <S, Self, Self, $matrix <S>>> for $vector <S> where
2647 S : Ring + MaybeSerDes
2648 {
2649 type Output = Self;
2650 fn mul (self, rhs : LinearIso <S, Self, Self, $matrix <S>>) -> Self::Output {
2651 self * rhs.0
2652 }
2653 }
2654 impl <S> num::Inv for LinearAuto <S, $vector <S>> where
2655 S : Ring + num::real::Real + MaybeSerDes
2656 {
2657 type Output = Self;
2658 fn inv (self) -> Self::Output {
2659 LinearAuto (self.0.inv())
2660 }
2661 }
2662 impl <S> std::ops::Div for LinearAuto <S, $vector <S>> where
2663 S : Ring + num::Float + MaybeSerDes
2664 {
2665 type Output = Self;
2666 fn div (self, rhs : Self) -> Self::Output {
2667 LinearAuto (self.0 / rhs.0)
2668 }
2669 }
2670 impl <S> std::ops::DivAssign <Self> for LinearAuto <S, $vector <S>> where
2671 S : Ring + num::Float + MaybeSerDes
2672 {
2673 fn div_assign (&mut self, rhs : Self) {
2674 self.0 /= rhs.0
2675 }
2676 }
2677 #[doc = "Construct a"]
2681 #[doc = $dimension]
2682 #[doc = "matrix"]
2683 pub const fn $matrix_fun <S> ($($component : $vector <S>),+) -> $matrix <S> {
2684 $matrix {
2685 cols: $vector_fun ($($component),+)
2686 }
2687 }
2688 impl <S, V, W> num::Inv for LinearIso <S, V, W, $matrix <S>> where
2689 V : Module <S>,
2690 W : Module <S>,
2691 S : Ring + num::real::Real
2692 {
2693 type Output = LinearIso <S, W, V, $matrix <S>>;
2694 fn inv (self) -> Self::Output {
2695 let mat4 = Matrix4::from (self.0);
2697 LinearIso (mat4.inverted().into(), PhantomData::default())
2698 }
2699 }
2700 impl <S, V> std::ops::Div for LinearIso <S, V, V, $matrix <S>> where
2701 V : Module <S, LinearEndo=$matrix <S>>,
2702 S : Ring + num::real::Real
2703 {
2704 type Output = Self;
2705 #[expect(clippy::suspicious_arithmetic_impl)]
2706 fn div (self, rhs : Self) -> Self::Output {
2707 use num::Inv;
2708 self * rhs.inv()
2709 }
2710 }
2711 impl <S, V> std::ops::DivAssign for LinearIso <S, V, V, $matrix <S>> where
2712 V : Module <S, LinearEndo=$matrix <S>>,
2713 S : Ring + num::real::Real
2714 {
2715 #[expect(clippy::suspicious_op_assign_impl)]
2716 fn div_assign (&mut self, rhs : Self) {
2717 use num::Inv;
2718 *self *= rhs.inv()
2719 }
2720 }
2721 $(
2722 impl <S : Copy> Matrix <S> for $matrix <S> {
2723 type Rows = $vector <$vector <S>>;
2724 type Submatrix = $submatrix <S>;
2725 fn rows (self) -> $vector <$vector <S>> {
2726 self.into_row_arrays().map ($vector::from).into()
2727 }
2728 fn submatrix (self, i : usize, j : usize) -> $submatrix <S> {
2729 let a : [S; ($ndims-1) * ($ndims-1)] = std::array::from_fn (|index|{
2730 let i = (i + 1 + index / ($ndims-1)) % $ndims;
2731 let j = (j + 1 + index % ($ndims-1)) % $ndims;
2732 self.cols[i][j]
2733 });
2734 $submatrix::from_col_array (a)
2735 }
2736 fn fill_zeros (submatrix : $submatrix <S>) -> Self where S : num::Zero{
2738 let cols = $vector::from (
2739 std::array::from_fn (|i| if i < $ndims-1 {
2740 $vector::from (submatrix.cols[i])
2741 } else {
2742 $vector::zero()
2743 })
2744 );
2745 $matrix { cols }
2746 }
2747 }
2748 )?
2749 impl <S : Ring> LinearMap <S, $vector <S>, $vector <S>> for $matrix <S> {
2750 fn determinant (self) -> S {
2751 self.determinant()
2752 }
2753 fn transpose (self) -> Self {
2754 self.transposed()
2755 }
2756 }
2757 impl_numcast!($nonzero);
2761 impl <S : Ring> $nonzero <S> {
2762 pub fn new (vector : $vector <S>) -> Option <Self> {
2772 use num::Zero;
2773 if !vector.is_zero() {
2774 Some ($nonzero (vector))
2775 } else {
2776 None
2777 }
2778 }
2779 pub fn noisy (vector : $vector <S>) -> Self {
2788 use num::Zero;
2789 assert!(!vector.is_zero());
2790 $nonzero (vector)
2791 }
2792 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self {
2804 Self::noisy (fun (self.0))
2805 }
2806 }
2807 impl <S : Ring> std::ops::Deref for $nonzero <S> {
2808 type Target = $vector <S>;
2809 fn deref (&self) -> &$vector <S> {
2810 &self.0
2811 }
2812 }
2813 impl_numcast!($unit);
2817 impl <S : Real> $unit <S> {
2818 $(
2824 #[inline]
2825 pub fn $axis_method() -> Self {
2826 $unit ($vector::$unit_method())
2827 }
2828 )+
2829 pub fn new (vector : $vector <S>) -> Option <Self> {
2833 let normalized = vector.normalize();
2834 if vector == normalized {
2835 Some ($unit (vector))
2836 } else {
2837 None
2838 }
2839 }
2840 pub fn new_approx (vector : $vector <S>) -> Option <Self> where
2846 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2847 {
2848 if vector.is_normalized() {
2849 Some ($unit (vector))
2850 } else {
2851 None
2852 }
2853 }
2854 pub fn normalize (vector : $vector <S>) -> Self {
2875 use num::Zero;
2876 assert!(!vector.is_zero());
2877 $unit (vector.normalize())
2878 }
2879 pub fn normalize_approx (vector : $vector <S>) -> Self where
2882 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2883 {
2884 use num::Zero;
2885 assert!(!vector.is_zero());
2886 let vector = if vector.is_normalized() {
2887 vector
2888 } else {
2889 vector.normalize()
2890 };
2891 $unit (vector)
2892 }
2893 pub fn noisy (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2902 assert_eq!(vector, vector.normalize());
2903 $unit (vector)
2904 }
2905 pub fn noisy_approx (vector : $vector <S>) -> Self where
2914 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2915 {
2916 assert!(vector.is_normalized());
2917 $unit (vector)
2918 }
2919 #[inline]
2923 pub fn unchecked (vector : $vector <S>) -> Self where S : std::fmt::Debug {
2924 debug_assert_eq!(vector, vector.normalize());
2925 $unit (vector)
2926 }
2927 #[inline]
2936 pub fn unchecked_approx (vector : $vector <S>) -> Self where
2937 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2938 {
2939 debug_assert!(vector.is_normalized());
2940 $unit (vector)
2941 }
2942 pub fn random_unit <R : rand::Rng> (rng : &mut R) -> Self where
2944 S : rand::distr::uniform::SampleUniform
2945 {
2946 let vector = $vector {
2947 $($component: rng.random_range (-S::one()..S::one())),+
2948 };
2949 $unit (vector.normalize())
2950 }
2951 pub fn invert (mut self) -> Self {
2954 self.0 = -self.0;
2955 self
2956 }
2957 pub fn map_noisy (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2969 S : std::fmt::Debug
2970 {
2971 Self::noisy (fun (self.0))
2972 }
2973 pub fn map_noisy_approx (self, fun : fn ($vector <S>) -> $vector <S>) -> Self where
2985 S : num::real::Real + approx::RelativeEq <Epsilon=S>
2986 {
2987 Self::noisy_approx (fun (self.0))
2988 }
2989 }
2990 impl <S : Real> std::ops::Deref for $unit <S> {
2991 type Target = $vector <S>;
2992 fn deref (&self) -> &$vector <S> {
2993 &self.0
2994 }
2995 }
2996 impl <S : Real> std::ops::Neg for $unit <S> {
2997 type Output = Self;
2998 fn neg (self) -> Self::Output {
2999 Self (-self.0)
3000 }
3001 }
3002 }
3004}
3005
3006macro_rules! impl_numcast {
3007 ($type:ident) => {
3008 impl <S> $type <S> {
3009 #[inline]
3010 pub fn numcast <T> (self) -> Option <$type <T>> where
3011 S : num::NumCast,
3012 T : num::NumCast
3013 {
3014 self.0.numcast().map ($type)
3015 }
3016 }
3017 }
3018}
3019
3020macro_rules! impl_numcast_primitive {
3021 ($type:ident) => {
3022 impl <S> $type <S> {
3023 #[inline]
3024 pub fn numcast <T> (self) -> Option <$type <T>> where
3025 S : num::NumCast,
3026 T : num::NumCast
3027 {
3028 T::from (self.0).map ($type)
3029 }
3030 }
3031 }
3032}
3033
3034#[doc(hidden)]
3035#[macro_export]
3036macro_rules! impl_numcast_fields {
3037 ($type:ident, $($field:ident),+) => {
3038 impl <S> $type <S> {
3039 #[inline]
3040 pub fn numcast <T> (self) -> Option <$type <T>> where
3041 S : num::NumCast,
3042 T : num::NumCast
3043 {
3044 Some ($type {
3045 $($field: self.$field.numcast()?),+
3046 })
3047 }
3048 }
3049 }
3050}
3051
3052impl_angle!(Deg, "Degrees");
3053impl_angle!(Rad, "Radians");
3054impl_angle!(Turn, "Turns");
3055impl_angle_wrapped!(AngleWrapped, "Unsigned wrapped angle restricted to $[0, 2\\pi)$");
3056impl_angle_wrapped!(AngleWrappedSigned,
3057 "Signed wrapped angle restricted to $(-\\pi, \\pi]$");
3058
3059impl_dimension!(Point2, Vector2, NonZero2, Unit2, point2, vector2, matrix2, [x, y],
3060 [(axis_x, unit_x), (axis_y, unit_y)],
3061 [], [Point3], Matrix2, [], 2, "2D");
3062impl_dimension!(Point3, Vector3, NonZero3, Unit3, point3, vector3, matrix3, [x, y, z],
3063 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z)],
3064 [Point2], [Point4], Matrix3, [Matrix2], 3, "3D");
3065impl_dimension!(Point4, Vector4, NonZero4, Unit4, point4, vector4, matrix4, [x, y, z, w],
3066 [(axis_x, unit_x), (axis_y, unit_y), (axis_z, unit_z), (axis_w, unit_w)],
3067 [Point3], [], Matrix4, [Matrix3], 4, "4D");
3068
3069impl_numcast_primitive!(Positive);
3070impl_numcast_primitive!(NonNegative);
3071impl_numcast_primitive!(NonZero);
3072impl_numcast_primitive!(Normalized);
3073impl_numcast_primitive!(NormalSigned);
3074impl_numcast_fields!(Angles3, yaw, pitch, roll);
3075
3076#[inline]
3080fn normalize_quaternion <S : Real> (quaternion : Quaternion <S>) -> Quaternion <S> {
3081 Quaternion::from_vec4 (quaternion.into_vec4().normalize())
3082}
3083
3084#[cfg(test)]
3085mod tests {
3086 use super::*;
3087 use crate::num_traits;
3088 use approx;
3089 use rand;
3090 use rand_xorshift;
3091
3092 #[test]
3093 fn defaults() {
3094 use num_traits::Zero;
3095
3096 assert_eq!(Positive::<f32>::default().0, 0.0);
3097 assert_eq!(NonNegative::<f32>::default().0, 0.0);
3098 assert_eq!(Normalized::<f32>::default().0, 0.0);
3099 assert_eq!(NormalSigned::<f32>::default().0, 0.0);
3100 assert_eq!(Deg::<f32>::default().0, 0.0);
3101 assert_eq!(Rad::<f32>::default().0, 0.0);
3102 assert_eq!(Turn::<f32>::default().0, 0.0);
3103 assert_eq!(
3104 Angles3::<f32>::default(),
3105 Angles3::new (AngleWrapped::zero(), AngleWrapped::zero(), AngleWrapped::zero()));
3106 assert_eq!(
3107 Pose3::<f32>::default(),
3108 Pose3 { position: Point3::origin(), angles: Angles3::default() });
3109 assert_eq!(
3110 LinearIso::<f32, Vector3 <f32>, Vector3 <f32>, Matrix3 <f32>>::default().0,
3111 Matrix3::identity());
3112 assert_eq!(LinearAuto::<f32, Vector3 <f32>>::default().0.0, Matrix3::identity());
3113 assert_eq!(Rotation2::<f32>::default().0.0.0, Matrix2::identity());
3114 assert_eq!(Rotation3::<f32>::default().0.0.0, Matrix3::identity());
3115 assert_eq!(Versor::<f32>::default().0, Quaternion::from_xyzw (0.0, 0.0, 0.0, 1.0));
3116 assert_eq!(
3117 AffineMap::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3118 AffineMap::new (Matrix3::identity(), Vector3::zero()));
3119 assert_eq!(
3120 Affinity::<f32, Point3 <f32>, Point3 <f32>, Matrix3 <f32>>::default(),
3121 Affinity::new (LinearIso::new (Matrix3::identity()).unwrap(), Vector3::zero()));
3122 assert_eq!(
3123 Projectivity::<f32, Point4 <f32>, Point4 <f32>, Matrix4 <f32>>::default().0,
3124 LinearIso::new (Matrix4::identity()).unwrap());
3125 }
3126
3127 #[test]
3128 fn vector_sum() {
3129 let s = [
3130 [0.0, 1.0],
3131 [1.0, 1.0],
3132 [0.5, 0.5]
3133 ].map (Vector2::<f32>::from);
3134 let _sum = s.iter().copied().sum::<Vector2 <f32>>();
3135 }
3136
3137 #[test]
3138 fn vector_outer_product() {
3139 let v1 = vector3 (1.0, 2.0, 3.0);
3140 let v2 = vector3 (2.0, 3.0, 4.0);
3141 assert_eq!(v1.outer_product (v2).into_row_arrays(), [
3142 [2.0, 3.0, 4.0],
3143 [4.0, 6.0, 8.0],
3144 [6.0, 9.0, 12.0]
3145 ]);
3146 }
3147
3148 #[test]
3149 fn rotation3_noisy_approx() {
3150 use rand::{Rng, SeedableRng};
3151 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3154 let up = Vector3::unit_z();
3155 for _ in 0..1000 {
3156 let forward = vector3 (
3157 rng.random_range (-1000.0f32..1000.0),
3158 rng.random_range (-1000.0f32..1000.0),
3159 0.0
3160 ).normalized();
3161 let right = forward.cross (up);
3162 let mat = Matrix3::from_col_arrays ([
3163 right.into_array(),
3164 forward.into_array(),
3165 up.into_array()
3166 ]);
3167 let _ = Rotation3::noisy_approx (mat);
3168 }
3169 }
3170
3171 #[test]
3172 fn rotation3_intrinsic_angles() {
3173 use std::f32::consts::PI;
3174 use num_traits::Zero;
3175 use rand::{Rng, SeedableRng};
3176 let rot = Rotation3::from_angles_intrinsic (
3178 Turn (0.25).into(), Rad::zero(), Rad::zero());
3179 approx::assert_relative_eq!(rot.mat(),
3180 Matrix3::from_col_arrays ([
3181 [ 0.0, 1.0, 0.0],
3182 [-1.0, 0.0, 0.0],
3183 [ 0.0, 0.0, 1.0]
3184 ])
3185 );
3186 assert_eq!((Turn (0.25).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3187 let rot = Rotation3::from_angles_intrinsic (
3188 Turn (0.5).into(), Rad::zero(), Rad::zero());
3189 approx::assert_relative_eq!(rot.mat(),
3190 Matrix3::from_col_arrays ([
3191 [-1.0, 0.0, 0.0],
3192 [ 0.0, -1.0, 0.0],
3193 [ 0.0, 0.0, 1.0]
3194 ])
3195 );
3196 assert_eq!((Turn (0.5).into(), Rad::zero(), Rad::zero()), rot.intrinsic_angles());
3197 let rot = Rotation3::from_angles_intrinsic (
3199 Rad::zero(), Turn (0.25).into(), Rad::zero());
3200 approx::assert_relative_eq!(rot.mat(),
3201 Matrix3::from_col_arrays ([
3202 [1.0, 0.0, 0.0],
3203 [0.0, 0.0, 1.0],
3204 [0.0, -1.0, 0.0]
3205 ])
3206 );
3207 assert_eq!((Rad::zero(), Turn (0.25).into(), Rad::zero()), rot.intrinsic_angles());
3208 let rot = Rotation3::from_angles_intrinsic (
3210 Rad::zero(), Rad::zero(), Turn (0.25).into());
3211 approx::assert_relative_eq!(rot.mat(),
3212 Matrix3::from_col_arrays ([
3213 [0.0, 0.0, -1.0],
3214 [0.0, 1.0, 0.0],
3215 [1.0, 0.0, 0.0]
3216 ])
3217 );
3218 assert_eq!((Rad::zero(), Rad::zero(), Turn (0.25).into()), rot.intrinsic_angles());
3219 let rot = Rotation3::from_angles_intrinsic (
3221 Turn (0.25).into(), Turn (0.25).into(), Rad::zero());
3222 approx::assert_relative_eq!(rot.mat(),
3223 Matrix3::from_col_arrays ([
3224 [0.0, 1.0, 0.0],
3225 [0.0, 0.0, 1.0],
3226 [1.0, 0.0, 0.0]
3227 ])
3228 );
3229 let angles = rot.intrinsic_angles();
3230 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3231 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3232 approx::assert_relative_eq!(0.0, angles.2.0);
3233 let rot = Rotation3::from_angles_intrinsic (
3235 Turn (0.25).into(), Turn (0.25).into(), Turn (0.25).into());
3236 approx::assert_relative_eq!(rot.mat(),
3237 Matrix3::from_col_arrays ([
3238 [-1.0, 0.0, 0.0],
3239 [ 0.0, 0.0, 1.0],
3240 [ 0.0, 1.0, 0.0]
3241 ])
3242 );
3243 let angles = rot.intrinsic_angles();
3244 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.0.0);
3245 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.1.0);
3246 approx::assert_relative_eq!(Rad::from (Turn (0.25)).0, angles.2.0);
3247
3248 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64 (0);
3251 let mut random_vector = || vector3 (
3252 rng.random_range (-100.0f32..100.0),
3253 rng.random_range (-100.0f32..100.0),
3254 rng.random_range (-100.0f32..100.0));
3255 for _ in 0..1000 {
3256 let rot = Rotation3::orthonormalize (
3257 random_vector(), random_vector(), random_vector()
3258 ).unwrap();
3259 let (yaw, pitch, roll) = rot.intrinsic_angles();
3260 assert!(yaw.0 < PI);
3261 assert!(yaw.0 > -PI);
3262 assert!(pitch.0 < PI);
3263 assert!(pitch.0 > -PI);
3264 assert!(roll.0 < PI);
3265 assert!(roll.0 > -PI);
3266 }
3267 }
3268
3269 #[test]
3270 fn rotation3_into_versor() {
3271 use std::f32::consts::PI;
3272 let rot = Rotation3::from_angle_x (Rad (0.01));
3273 let quat = rot.versor().0;
3274 approx::assert_relative_eq!(rot.mat(), quat.into());
3275 let rot = Rotation3::from_angle_x (Rad (-0.01));
3276 let quat = rot.versor().0;
3277 approx::assert_relative_eq!(rot.mat(), quat.into());
3278
3279 let rot = Rotation3::from_angle_y (Rad (0.01));
3280 let quat = rot.versor().0;
3281 approx::assert_relative_eq!(rot.mat(), quat.into());
3282 let rot = Rotation3::from_angle_y (Rad (-0.01));
3283 let quat = rot.versor().0;
3284 approx::assert_relative_eq!(rot.mat(), quat.into());
3285
3286 let rot = Rotation3::from_angle_z (Rad (0.01));
3287 let quat = rot.versor().0;
3288 approx::assert_relative_eq!(rot.mat(), quat.into());
3289 let rot = Rotation3::from_angle_z (Rad (-0.01));
3290 let quat = rot.versor().0;
3291 approx::assert_relative_eq!(rot.mat(), quat.into());
3292
3293 let rot = Rotation3::from_angle_x (Rad (PI / 2.0));
3294 let quat = rot.versor().0;
3295 approx::assert_relative_eq!(rot.mat(), quat.into());
3296 let rot = Rotation3::from_angle_x (Rad (-PI / 2.0));
3297 let quat = rot.versor().0;
3298 approx::assert_relative_eq!(rot.mat(), quat.into());
3299
3300 let rot = Rotation3::from_angle_y (Rad (PI / 2.0));
3301 let quat = rot.versor().0;
3302 approx::assert_relative_eq!(rot.mat(), quat.into());
3303 let rot = Rotation3::from_angle_y (Rad (-PI / 2.0));
3304 let quat = rot.versor().0;
3305 approx::assert_relative_eq!(rot.mat(), quat.into());
3306
3307 let rot = Rotation3::from_angle_z (Rad (PI / 2.0));
3308 let quat = rot.versor().0;
3309 approx::assert_relative_eq!(rot.mat(), quat.into());
3310 let rot = Rotation3::from_angle_z (Rad (-PI / 2.0));
3311 let quat = rot.versor().0;
3312 approx::assert_relative_eq!(rot.mat(), quat.into());
3313 }
3314}