Add .axis_angle to UnitComplex and UnitQuaternion + .rotation_between_axis to UnitComplex.
This commit is contained in:
parent
e7c0e95d3f
commit
1ac8bbd3d1
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ target/
|
||||
Cargo.lock
|
||||
*.orig
|
||||
*.swo
|
||||
site/
|
@ -4,6 +4,14 @@ documented here.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [0.15.0] - WIP
|
||||
### Modified
|
||||
### Added
|
||||
* Add methods `.rotation_between_axis(...)` and `.scaled_rotation_between_axis(...)` to `UnitComplex`
|
||||
to compute the rotation matrix between two 2D **unit** vectors.
|
||||
* Add methods `.axis_angle()` to `UnitComplex` and `UnitQuaternion` in order to retrieve both the
|
||||
unit rotation axis and the rotation angle simultaneously.
|
||||
|
||||
## [0.14.0]
|
||||
### Modified
|
||||
* Allow the `Isometry * Unit<Vector>` multiplication.
|
||||
|
@ -462,8 +462,7 @@ where
|
||||
let (nrows3, ncols3) = b.shape();
|
||||
|
||||
assert_eq!(
|
||||
ncols2,
|
||||
nrows3,
|
||||
ncols2, nrows3,
|
||||
"gemm: dimensions mismatch for multiplication."
|
||||
);
|
||||
assert_eq!(
|
||||
@ -564,8 +563,7 @@ where
|
||||
let (nrows3, ncols3) = b.shape();
|
||||
|
||||
assert_eq!(
|
||||
nrows2,
|
||||
nrows3,
|
||||
nrows2, nrows3,
|
||||
"gemm: dimensions mismatch for multiplication."
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -491,6 +491,18 @@ impl<N: Real> UnitQuaternion<N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The rotation axis and angle in ]0, pi] of this unit quaternion.
|
||||
///
|
||||
/// Returns `None` if the angle is zero.
|
||||
#[inline]
|
||||
pub fn axis_angle(&self) -> Option<(Unit<Vector3<N>>, N)> {
|
||||
if let Some(axis) = self.axis() {
|
||||
Some((axis, self.angle()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the exponential of a quaternion.
|
||||
///
|
||||
/// Note that this function yields a `Quaternion<N>` because it looses the unit property.
|
||||
|
@ -34,6 +34,22 @@ impl<N: Real> UnitComplex<N> {
|
||||
Vector1::new(self.angle())
|
||||
}
|
||||
|
||||
/// The rotation axis and angle in ]0, pi] of this complex number.
|
||||
///
|
||||
/// Returns `None` if the angle is zero.
|
||||
#[inline]
|
||||
pub fn axis_angle(&self) -> Option<(Unit<Vector1<N>>, N)> {
|
||||
let ang = self.angle();
|
||||
|
||||
if ang.is_zero() {
|
||||
None
|
||||
} else if ang.is_sign_negative() {
|
||||
Some((Unit::new_unchecked(Vector1::x()), -ang))
|
||||
} else {
|
||||
Some((Unit::new_unchecked(-Vector1::<N>::x()), ang))
|
||||
}
|
||||
}
|
||||
|
||||
/// The underlying complex number.
|
||||
///
|
||||
/// Same as `self.as_ref()`.
|
||||
|
@ -6,7 +6,7 @@ use num_complex::Complex;
|
||||
use rand::{Rand, Rng};
|
||||
|
||||
use alga::general::Real;
|
||||
use core::{DefaultAllocator, Vector};
|
||||
use core::{DefaultAllocator, Unit, Vector};
|
||||
use core::dimension::{U1, U2};
|
||||
use core::storage::Storage;
|
||||
use core::allocator::Allocator;
|
||||
@ -99,15 +99,48 @@ impl<N: Real> UnitComplex<N> {
|
||||
SB: Storage<N, U2, U1>,
|
||||
SC: Storage<N, U2, U1>,
|
||||
{
|
||||
if let (Some(na), Some(nb)) = (a.try_normalize(N::zero()), b.try_normalize(N::zero())) {
|
||||
let sang = na.perp(&nb);
|
||||
let cang = na.dot(&nb);
|
||||
|
||||
Self::from_angle(sang.atan2(cang) * s)
|
||||
// FIXME: code duplication with Rotation.
|
||||
if let (Some(na), Some(nb)) = (
|
||||
Unit::try_new(a.clone_owned(), N::zero()),
|
||||
Unit::try_new(b.clone_owned(), N::zero()),
|
||||
) {
|
||||
Self::scaled_rotation_between_axis(&na, &nb, s)
|
||||
} else {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
/// The unit complex needed to make `a` and `b` be collinear and point toward the same
|
||||
/// direction.
|
||||
#[inline]
|
||||
pub fn rotation_between_axis<SB, SC>(
|
||||
a: &Unit<Vector<N, U2, SB>>,
|
||||
b: &Unit<Vector<N, U2, SC>>,
|
||||
) -> Self
|
||||
where
|
||||
SB: Storage<N, U2>,
|
||||
SC: Storage<N, U2>,
|
||||
{
|
||||
Self::scaled_rotation_between_axis(a, b, N::one())
|
||||
}
|
||||
|
||||
/// The smallest rotation needed to make `a` and `b` collinear and point toward the same
|
||||
/// direction, raised to the power `s`.
|
||||
#[inline]
|
||||
pub fn scaled_rotation_between_axis<SB, SC>(
|
||||
na: &Unit<Vector<N, U2, SB>>,
|
||||
nb: &Unit<Vector<N, U2, SC>>,
|
||||
s: N,
|
||||
) -> Self
|
||||
where
|
||||
SB: Storage<N, U2>,
|
||||
SC: Storage<N, U2>,
|
||||
{
|
||||
let sang = na.perp(&nb);
|
||||
let cang = na.dot(&nb);
|
||||
|
||||
Self::from_angle(sang.atan2(cang) * s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Real> One for UnitComplex<N> {
|
||||
|
Loading…
Reference in New Issue
Block a user