Quaternionic division + refactoring (#563)
This commit is contained in:
parent
f916dae6ed
commit
1e614db227
|
@ -225,7 +225,7 @@ impl<T: Neg> Neg for Unit<T> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg(self) -> Self::Output {
|
fn neg(self) -> Self::Output {
|
||||||
Unit::new_unchecked(-self.value)
|
Self::Output::new_unchecked(-self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -528,7 +528,7 @@ impl<N: Real> Quaternion<N> {
|
||||||
/// Check if the quaternion is pure.
|
/// Check if the quaternion is pure.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_pure(&self) -> bool {
|
pub fn is_pure(&self) -> bool {
|
||||||
self.w == N::zero()
|
self.w.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert quaternion to pure quaternion.
|
/// Convert quaternion to pure quaternion.
|
||||||
|
@ -537,6 +537,33 @@ impl<N: Real> Quaternion<N> {
|
||||||
Self::from_imag(self.imag())
|
Self::from_imag(self.imag())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Left quaternionic division.
|
||||||
|
///
|
||||||
|
/// Calculates B<sup>-1</sup> * A where A = self, B = other.
|
||||||
|
#[inline]
|
||||||
|
pub fn left_div(&self, other: &Self) -> Option<Self> {
|
||||||
|
other.try_inverse().map(|inv| inv * self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Right quaternionic division.
|
||||||
|
///
|
||||||
|
/// Calculates A * B<sup>-1</sup> where A = self, B = other.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # #[macro_use] extern crate approx;
|
||||||
|
/// # use nalgebra::Quaternion;
|
||||||
|
/// let a = Quaternion::new(0.0, 1.0, 2.0, 3.0);
|
||||||
|
/// let b = Quaternion::new(0.0, 5.0, 2.0, 1.0);
|
||||||
|
/// let result = a.right_div(&b).unwrap();
|
||||||
|
/// let expected = Quaternion::new(0.4, 0.13333333333333336, -0.4666666666666667, 0.26666666666666666);
|
||||||
|
/// assert_relative_eq!(expected, result, epsilon = 1.0e-7);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn right_div(&self, other: &Self) -> Option<Self> {
|
||||||
|
other.try_inverse().map(|inv| self * inv)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the quaternionic cosinus.
|
/// Calculates the quaternionic cosinus.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -626,11 +653,7 @@ impl<N: Real> Quaternion<N> {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tan(&self) -> Self {
|
pub fn tan(&self) -> Self {
|
||||||
let s = self.sin();
|
self.sin().right_div(&self.cos()).unwrap()
|
||||||
let c = self.cos();
|
|
||||||
|
|
||||||
let ci = c.try_inverse().unwrap();
|
|
||||||
s * ci
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the quaternionic arctangent.
|
/// Calculates the quaternionic arctangent.
|
||||||
|
@ -648,7 +671,7 @@ impl<N: Real> Quaternion<N> {
|
||||||
let u = Self::from_imag(self.imag().normalize());
|
let u = Self::from_imag(self.imag().normalize());
|
||||||
let num = u + self;
|
let num = u + self;
|
||||||
let den = u - self;
|
let den = u - self;
|
||||||
let fr = num * den.try_inverse().unwrap();
|
let fr = num.right_div(&den).unwrap();
|
||||||
let ln = fr.ln();
|
let ln = fr.ln();
|
||||||
(u.half()) * ln
|
(u.half()) * ln
|
||||||
}
|
}
|
||||||
|
@ -732,11 +755,7 @@ impl<N: Real> Quaternion<N> {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tanh(&self) -> Self {
|
pub fn tanh(&self) -> Self {
|
||||||
let s = self.sinh();
|
self.sinh().right_div(&self.cosh()).unwrap()
|
||||||
let c = self.cosh();
|
|
||||||
|
|
||||||
let ci = c.try_inverse().unwrap();
|
|
||||||
s * ci
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the hyperbolic quaternionic arctangent.
|
/// Calculates the hyperbolic quaternionic arctangent.
|
||||||
|
@ -1096,11 +1115,7 @@ impl<N: Real> UnitQuaternion<N> {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn axis_angle(&self) -> Option<(Unit<Vector3<N>>, N)> {
|
pub fn axis_angle(&self) -> Option<(Unit<Vector3<N>>, N)> {
|
||||||
if let Some(axis) = self.axis() {
|
self.axis().map(|axis| (axis, self.angle()))
|
||||||
Some((axis, self.angle()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the exponential of a quaternion.
|
/// Compute the exponential of a quaternion.
|
||||||
|
|
|
@ -71,6 +71,12 @@ impl<N: Real> Quaternion<N> {
|
||||||
Self::new(scalar, vector[0], vector[1], vector[2])
|
Self::new(scalar, vector[0], vector[1], vector[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a real quaternion.
|
||||||
|
#[inline]
|
||||||
|
pub fn from_real(r: N) -> Self {
|
||||||
|
Self::from_parts(r, Vector3::zero())
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new quaternion from its polar decomposition.
|
/// Creates a new quaternion from its polar decomposition.
|
||||||
///
|
///
|
||||||
/// Note that `axis` is assumed to be a unit vector.
|
/// Note that `axis` is assumed to be a unit vector.
|
||||||
|
@ -95,7 +101,7 @@ impl<N: Real> Quaternion<N> {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn identity() -> Self {
|
pub fn identity() -> Self {
|
||||||
Self::from_parts(N::one(), Vector3::zero())
|
Self::from_real(N::one())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -552,7 +552,7 @@ impl<N: Real> Neg for Quaternion<N> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg(self) -> Self::Output {
|
fn neg(self) -> Self::Output {
|
||||||
Quaternion::from(-self.coords)
|
Self::Output::from(-self.coords)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +561,7 @@ impl<'a, N: Real> Neg for &'a Quaternion<N> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg(self) -> Self::Output {
|
fn neg(self) -> Self::Output {
|
||||||
Quaternion::from(-&self.coords)
|
Self::Output::from(-&self.coords)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<N: Real, D: Dim, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
0 => true,
|
0 => true,
|
||||||
1 => {
|
1 => {
|
||||||
let determinant = self.get_unchecked((0, 0)).clone();
|
let determinant = self.get_unchecked((0, 0)).clone();
|
||||||
if determinant == N::zero() {
|
if determinant.is_zero() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
*self.get_unchecked_mut((0, 0)) = N::one() / determinant;
|
*self.get_unchecked_mut((0, 0)) = N::one() / determinant;
|
||||||
|
@ -51,7 +51,7 @@ impl<N: Real, D: Dim, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
|
|
||||||
let determinant = m11 * m22 - m21 * m12;
|
let determinant = m11 * m22 - m21 * m12;
|
||||||
|
|
||||||
if determinant == N::zero() {
|
if determinant.is_zero() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
*self.get_unchecked_mut((0, 0)) = m22 / determinant;
|
*self.get_unchecked_mut((0, 0)) = m22 / determinant;
|
||||||
|
@ -83,7 +83,7 @@ impl<N: Real, D: Dim, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
let determinant =
|
let determinant =
|
||||||
m11 * minor_m12_m23 - m12 * minor_m11_m23 + m13 * minor_m11_m22;
|
m11 * minor_m12_m23 - m12 * minor_m11_m23 + m13 * minor_m11_m22;
|
||||||
|
|
||||||
if determinant == N::zero() {
|
if determinant.is_zero() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
*self.get_unchecked_mut((0, 0)) = minor_m12_m23 / determinant;
|
*self.get_unchecked_mut((0, 0)) = minor_m12_m23 / determinant;
|
||||||
|
|
Loading…
Reference in New Issue