This commit is contained in:
Terence 2021-01-28 18:46:14 -05:00
parent 6be0365203
commit 388b77108e
11 changed files with 77 additions and 71 deletions

View File

@ -1,11 +1,11 @@
use std::fmt;
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use crate::{ use crate::{
Quaternion, SimdRealField, VectorN, U8, Vector3, Point3, Isometry3, Unit, Matrix4, Isometry3, Matrix4, Normed, Point3, Quaternion, Scalar, SimdRealField, Translation3, Unit,
Translation3, UnitQuaternion, Scalar, Normed UnitQuaternion, Vector3, VectorN, U8,
}; };
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
#[cfg(feature = "serde-serialize")] #[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use simba::scalar::{ClosedNeg, RealField}; use simba::scalar::{ClosedNeg, RealField};
@ -432,7 +432,9 @@ where
#[inline] #[inline]
#[must_use = "Did you mean to use inverse_mut()?"] #[must_use = "Did you mean to use inverse_mut()?"]
pub fn inverse(&self) -> Self { pub fn inverse(&self) -> Self {
let real = Unit::new_unchecked(self.as_ref().real).inverse().into_inner(); let real = Unit::new_unchecked(self.as_ref().real)
.inverse()
.into_inner();
let dual = -real * self.as_ref().dual * real; let dual = -real * self.as_ref().dual * real;
UnitDualQuaternion::new_unchecked(DualQuaternion { real, dual }) UnitDualQuaternion::new_unchecked(DualQuaternion { real, dual })
} }
@ -634,9 +636,11 @@ where
moment * sin + direction * (pitch * half * cos), moment * sin + direction * (pitch * half * cos),
); );
Some(self * UnitDualQuaternion::new_unchecked( Some(
DualQuaternion::from_real_and_dual(real, dual) self * UnitDualQuaternion::new_unchecked(DualQuaternion::from_real_and_dual(
)) real, dual,
)),
)
} }
/// Return the rotation part of this unit dual quaternion. /// Return the rotation part of this unit dual quaternion.
@ -844,8 +848,7 @@ where
/// assert_relative_eq!(dq.to_homogeneous(), expected, epsilon = 1.0e-6); /// assert_relative_eq!(dq.to_homogeneous(), expected, epsilon = 1.0e-6);
/// ``` /// ```
#[inline] #[inline]
pub fn to_homogeneous(&self) -> Matrix4<N> pub fn to_homogeneous(&self) -> Matrix4<N> {
{
self.to_isometry().to_homogeneous() self.to_isometry().to_homogeneous()
} }
} }

View File

@ -7,13 +7,12 @@ use alga::general::{
}; };
use alga::linear::{ use alga::linear::{
AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace, AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace,
ProjectiveTransformation, Similarity, Transformation, ProjectiveTransformation, Similarity, Transformation, VectorSpace,
VectorSpace,
}; };
use crate::base::Vector3; use crate::base::Vector3;
use crate::geometry::{ use crate::geometry::{
Point3, Quaternion, UnitQuaternion, DualQuaternion, UnitDualQuaternion, Translation3 DualQuaternion, Point3, Quaternion, Translation3, UnitDualQuaternion, UnitQuaternion,
}; };
impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for DualQuaternion<N> { impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for DualQuaternion<N> {
@ -103,12 +102,12 @@ impl<N: RealField + simba::scalar::RealField> FiniteDimVectorSpace for DualQuate
if i < 4 { if i < 4 {
DualQuaternion::from_real_and_dual( DualQuaternion::from_real_and_dual(
Quaternion::canonical_basis_element(i), Quaternion::canonical_basis_element(i),
Quaternion::zero() Quaternion::zero(),
) )
} else { } else {
DualQuaternion::from_real_and_dual( DualQuaternion::from_real_and_dual(
Quaternion::zero(), Quaternion::zero(),
Quaternion::canonical_basis_element(i - 4) Quaternion::canonical_basis_element(i - 4),
) )
} }
} }
@ -157,7 +156,10 @@ impl<N: RealField + simba::scalar::RealField> NormedSpace for DualQuaternion<N>
fn try_normalize(&self, min_norm: N) -> Option<Self> { fn try_normalize(&self, min_norm: N) -> Option<Self> {
let real_norm = self.real.norm(); let real_norm = self.real.norm();
if real_norm > min_norm { if real_norm > min_norm {
Some(Self::from_real_and_dual(self.real / real_norm, self.dual / real_norm)) Some(Self::from_real_and_dual(
self.real / real_norm,
self.dual / real_norm,
))
} else { } else {
None None
} }
@ -188,7 +190,9 @@ impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for UnitD
} }
} }
impl<N: RealField + simba::scalar::RealField> AbstractMagma<Multiplicative> for UnitDualQuaternion<N> { impl<N: RealField + simba::scalar::RealField> AbstractMagma<Multiplicative>
for UnitDualQuaternion<N>
{
#[inline] #[inline]
fn operate(&self, rhs: &Self) -> Self { fn operate(&self, rhs: &Self) -> Self {
self * rhs self * rhs
@ -253,7 +257,12 @@ impl<N: RealField + simba::scalar::RealField> AffineTransformation<Point3<N>>
#[inline] #[inline]
fn decompose(&self) -> (Self::Translation, Self::Rotation, Id, Self::Rotation) { fn decompose(&self) -> (Self::Translation, Self::Rotation, Id, Self::Rotation) {
(self.translation(), self.rotation(), Id::new(), UnitQuaternion::identity()) (
self.translation(),
self.rotation(),
Id::new(),
UnitQuaternion::identity(),
)
} }
#[inline] #[inline]
@ -313,4 +322,3 @@ macro_rules! marker_impl(
); );
marker_impl!(Isometry, DirectIsometry); marker_impl!(Isometry, DirectIsometry);

View File

@ -1,10 +1,10 @@
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
use crate::{ use crate::{
DualQuaternion, Quaternion, UnitDualQuaternion, SimdRealField, Isometry3, DualQuaternion, Isometry3, Quaternion, SimdRealField, Translation3, UnitDualQuaternion,
Translation3, UnitQuaternion UnitQuaternion,
}; };
use num::{One, Zero}; use num::{One, Zero};
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
impl<N: SimdRealField> DualQuaternion<N> { impl<N: SimdRealField> DualQuaternion<N> {
/// Creates a dual quaternion from its rotation and translation components. /// Creates a dual quaternion from its rotation and translation components.
@ -50,9 +50,8 @@ impl<N: SimdRealField> DualQuaternion<N> {
impl<N: SimdRealField> DualQuaternion<N> impl<N: SimdRealField> DualQuaternion<N>
where where
N::Element: SimdRealField N::Element: SimdRealField,
{ {
/// Creates a dual quaternion from only its real part, with no translation /// Creates a dual quaternion from only its real part, with no translation
/// component. /// component.
/// ///
@ -67,7 +66,10 @@ where
/// ``` /// ```
#[inline] #[inline]
pub fn from_real(real: Quaternion<N>) -> Self { pub fn from_real(real: Quaternion<N>) -> Self {
Self { real, dual: Quaternion::zero() } Self {
real,
dual: Quaternion::zero(),
}
} }
} }
@ -87,10 +89,7 @@ where
{ {
#[inline] #[inline]
fn zero() -> Self { fn zero() -> Self {
DualQuaternion::from_real_and_dual( DualQuaternion::from_real_and_dual(Quaternion::zero(), Quaternion::zero())
Quaternion::zero(),
Quaternion::zero()
)
} }
#[inline] #[inline]
@ -107,10 +106,7 @@ where
{ {
#[inline] #[inline]
fn arbitrary<G: Gen>(rng: &mut G) -> Self { fn arbitrary<G: Gen>(rng: &mut G) -> Self {
Self::from_real_and_dual( Self::from_real_and_dual(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
Arbitrary::arbitrary(rng),
Arbitrary::arbitrary(rng)
)
} }
} }
@ -151,10 +147,7 @@ where
/// assert_relative_eq!(dq * point, Point3::new(1.0, 0.0, 2.0), epsilon = 1.0e-6); /// assert_relative_eq!(dq * point, Point3::new(1.0, 0.0, 2.0), epsilon = 1.0e-6);
/// ``` /// ```
#[inline] #[inline]
pub fn from_parts( pub fn from_parts(translation: Translation3<N>, rotation: UnitQuaternion<N>) -> Self {
translation: Translation3<N>,
rotation: UnitQuaternion<N>
) -> Self {
let half: N = crate::convert(0.5f64); let half: N = crate::convert(0.5f64);
UnitDualQuaternion::new_unchecked(DualQuaternion { UnitDualQuaternion::new_unchecked(DualQuaternion {
real: rotation.clone().into_inner(), real: rotation.clone().into_inner(),

View File

@ -4,8 +4,8 @@ use simba::simd::SimdRealField;
use crate::base::dimension::U3; use crate::base::dimension::U3;
use crate::base::{Matrix4, Vector4}; use crate::base::{Matrix4, Vector4};
use crate::geometry::{ use crate::geometry::{
Isometry3, DualQuaternion, Similarity3, SuperTCategoryOf, DualQuaternion, Isometry3, Similarity3, SuperTCategoryOf, TAffine, Transform, Translation3,
TAffine, Transform, Translation3, UnitQuaternion, UnitDualQuaternion UnitDualQuaternion, UnitQuaternion,
}; };
/* /*
@ -35,14 +35,15 @@ where
#[inline] #[inline]
fn is_in_subset(dq: &DualQuaternion<N2>) -> bool { fn is_in_subset(dq: &DualQuaternion<N2>) -> bool {
crate::is_convertible::<_, Vector4<N1>>(&dq.real.coords) && crate::is_convertible::<_, Vector4<N1>>(&dq.real.coords)
crate::is_convertible::<_, Vector4<N1>>(&dq.dual.coords) && crate::is_convertible::<_, Vector4<N1>>(&dq.dual.coords)
} }
#[inline] #[inline]
fn from_superset_unchecked(dq: &DualQuaternion<N2>) -> Self { fn from_superset_unchecked(dq: &DualQuaternion<N2>) -> Self {
DualQuaternion::from_real_and_dual( DualQuaternion::from_real_and_dual(
dq.real.to_subset_unchecked(), dq.dual.to_subset_unchecked() dq.real.to_subset_unchecked(),
dq.dual.to_subset_unchecked(),
) )
} }
} }
@ -71,7 +72,7 @@ where
impl<N1, N2> SubsetOf<Isometry3<N2>> for UnitDualQuaternion<N1> impl<N1, N2> SubsetOf<Isometry3<N2>> for UnitDualQuaternion<N1>
where where
N1: RealField, N1: RealField,
N2: RealField + SupersetOf<N1> N2: RealField + SupersetOf<N1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Isometry3<N2> { fn to_superset(&self) -> Isometry3<N2> {
@ -82,8 +83,8 @@ where
#[inline] #[inline]
fn is_in_subset(iso: &Isometry3<N2>) -> bool { fn is_in_subset(iso: &Isometry3<N2>) -> bool {
crate::is_convertible::<_, UnitQuaternion<N1>>(&iso.rotation) && crate::is_convertible::<_, UnitQuaternion<N1>>(&iso.rotation)
crate::is_convertible::<_, Translation3<N1>>(&iso.translation) && crate::is_convertible::<_, Translation3<N1>>(&iso.translation)
} }
#[inline] #[inline]
@ -96,7 +97,7 @@ where
impl<N1, N2> SubsetOf<Similarity3<N2>> for UnitDualQuaternion<N1> impl<N1, N2> SubsetOf<Similarity3<N2>> for UnitDualQuaternion<N1>
where where
N1: RealField, N1: RealField,
N2: RealField + SupersetOf<N1> N2: RealField + SupersetOf<N1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Similarity3<N2> { fn to_superset(&self) -> Similarity3<N2> {
@ -136,7 +137,9 @@ where
} }
} }
impl<N1: RealField, N2: RealField + SupersetOf<N1>> SubsetOf<Matrix4<N2>> for UnitDualQuaternion<N1> { impl<N1: RealField, N2: RealField + SupersetOf<N1>> SubsetOf<Matrix4<N2>>
for UnitDualQuaternion<N1>
{
#[inline] #[inline]
fn to_superset(&self) -> Matrix4<N2> { fn to_superset(&self) -> Matrix4<N2> {
self.to_homogeneous().to_superset() self.to_homogeneous().to_superset()
@ -183,4 +186,3 @@ where
Self::from_isometry(&iso) Self::from_isometry(&iso)
} }
} }

View File

@ -22,15 +22,15 @@
* - https://cs.gmu.edu/~jmlien/teaching/cs451/uploads/Main/dual-quaternion.pdf * - https://cs.gmu.edu/~jmlien/teaching/cs451/uploads/Main/dual-quaternion.pdf
*/ */
use crate::{
DualQuaternion, SimdRealField, Point3, Point, Vector3, Isometry3, Quaternion,
UnitDualQuaternion, UnitQuaternion, U1, U3, U4, Unit, Allocator,
DefaultAllocator, Vector, Translation3
};
use crate::base::storage::Storage; use crate::base::storage::Storage;
use crate::{
Allocator, DefaultAllocator, DualQuaternion, Isometry3, Point, Point3, Quaternion,
SimdRealField, Translation3, Unit, UnitDualQuaternion, UnitQuaternion, Vector, Vector3, U1, U3,
U4,
};
use std::mem; use std::mem;
use std::ops::{ use std::ops::{
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
}; };
impl<N: SimdRealField> AsRef<[N; 8]> for DualQuaternion<N> { impl<N: SimdRealField> AsRef<[N; 8]> for DualQuaternion<N> {

View File

@ -7,7 +7,7 @@ use crate::base::{DefaultAllocator, MatrixN, Scalar};
use crate::geometry::{ use crate::geometry::{
AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform, AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform,
Translation, UnitDualQuaternion, UnitQuaternion Translation, UnitDualQuaternion, UnitQuaternion,
}; };
/* /*
@ -62,8 +62,8 @@ where
#[inline] #[inline]
fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool { fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool {
crate::is_convertible::<_, UnitQuaternion<N1>>(&dq.rotation()) && crate::is_convertible::<_, UnitQuaternion<N1>>(&dq.rotation())
crate::is_convertible::<_, Translation<N1, _>>(&dq.translation()) && crate::is_convertible::<_, Translation<N1, _>>(&dq.translation())
} }
#[inline] #[inline]

View File

@ -10,7 +10,7 @@ use crate::base::dimension::U3;
use crate::base::{Matrix3, Matrix4, Scalar, Vector4}; use crate::base::{Matrix3, Matrix4, Scalar, Vector4};
use crate::geometry::{ use crate::geometry::{
AbstractRotation, Isometry, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, AbstractRotation, Isometry, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf,
TAffine, Transform, Translation, UnitQuaternion, UnitDualQuaternion TAffine, Transform, Translation, UnitDualQuaternion, UnitQuaternion,
}; };
/* /*
@ -125,7 +125,7 @@ where
impl<N1, N2> SubsetOf<UnitDualQuaternion<N2>> for UnitQuaternion<N1> impl<N1, N2> SubsetOf<UnitDualQuaternion<N2>> for UnitQuaternion<N1>
where where
N1: RealField, N1: RealField,
N2: RealField + SupersetOf<N1> N2: RealField + SupersetOf<N1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> UnitDualQuaternion<N2> { fn to_superset(&self) -> UnitDualQuaternion<N2> {

View File

@ -12,7 +12,7 @@ use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN, Scalar};
use crate::geometry::{ use crate::geometry::{
AbstractRotation, Isometry, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, AbstractRotation, Isometry, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf,
TAffine, Transform, Translation, UnitComplex, UnitQuaternion, UnitDualQuaternion, TAffine, Transform, Translation, UnitComplex, UnitDualQuaternion, UnitQuaternion,
}; };
/* /*
@ -90,8 +90,8 @@ where
#[inline] #[inline]
fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool { fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool {
crate::is_convertible::<_, UnitQuaternion<N1>>(&dq.rotation()) && crate::is_convertible::<_, UnitQuaternion<N1>>(&dq.rotation())
dq.translation().vector.is_zero() && dq.translation().vector.is_zero()
} }
#[inline] #[inline]

View File

@ -9,7 +9,7 @@ use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN};
use crate::geometry::{ use crate::geometry::{
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
Translation3, UnitDualQuaternion, UnitQuaternion Translation3, UnitDualQuaternion, UnitQuaternion,
}; };
/* /*
@ -84,8 +84,8 @@ where
#[inline] #[inline]
fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool { fn is_in_subset(dq: &UnitDualQuaternion<N2>) -> bool {
crate::is_convertible::<_, Translation<N1, _>>(&dq.translation()) && crate::is_convertible::<_, Translation<N1, _>>(&dq.translation())
dq.rotation() == UnitQuaternion::identity() && dq.rotation() == UnitQuaternion::identity()
} }
#[inline] #[inline]

View File

@ -1,9 +1,7 @@
#![cfg(feature = "arbitrary")] #![cfg(feature = "arbitrary")]
#![allow(non_snake_case)] #![allow(non_snake_case)]
use na::{ use na::{Isometry3, Point3, Translation3, UnitDualQuaternion, UnitQuaternion, Vector3};
Isometry3, Point3, Translation3, UnitQuaternion, UnitDualQuaternion, Vector3,
};
quickcheck!( quickcheck!(
fn isometry_equivalence(iso: Isometry3<f64>, p: Point3<f64>, v: Vector3<f64>) -> bool { fn isometry_equivalence(iso: Isometry3<f64>, p: Point3<f64>, v: Vector3<f64>) -> bool {
@ -25,7 +23,9 @@ quickcheck!(
} }
fn multiply_equals_alga_transform( fn multiply_equals_alga_transform(
dq: UnitDualQuaternion<f64>, v: Vector3<f64>, p: Point3<f64> dq: UnitDualQuaternion<f64>,
v: Vector3<f64>,
p: Point3<f64>,
) -> bool { ) -> bool {
dq * v == dq.transform_vector(&v) dq * v == dq.transform_vector(&v)
&& dq * p == dq.transform_point(&p) && dq * p == dq.transform_point(&p)

View File

@ -1,3 +1,4 @@
mod dual_quaternion;
mod isometry; mod isometry;
mod point; mod point;
mod projection; mod projection;
@ -5,4 +6,3 @@ mod quaternion;
mod rotation; mod rotation;
mod similarity; mod similarity;
mod unit_complex; mod unit_complex;
mod dual_quaternion;