Add the `RotationTo` trait to compute the delta rotation between two elements.
Use `::angle_between` or `.angle_to` to compute the rotation angle between two vectors/rotation matrices/unit quaternions. Use `::rotation_between` or `.rotation_to` to compute the rotation matrix/unit quaternion to transform a vector/rotation matrix/uniq quaternion to another. Fix #130.
This commit is contained in:
parent
11bbf0ff11
commit
ea86890647
17
src/lib.rs
17
src/lib.rs
|
@ -133,7 +133,7 @@ pub use traits::{
|
||||||
POrdering,
|
POrdering,
|
||||||
PntAsVec,
|
PntAsVec,
|
||||||
Repeat,
|
Repeat,
|
||||||
Rotate, Rotation, RotationMatrix, RotationWithTranslation,
|
Rotate, Rotation, RotationMatrix, RotationWithTranslation, RotationTo,
|
||||||
Row,
|
Row,
|
||||||
Shape,
|
Shape,
|
||||||
SquareMat,
|
SquareMat,
|
||||||
|
@ -569,6 +569,21 @@ pub fn append_rotation_wrt_center<LV: Neg<Output = LV> + Copy,
|
||||||
RotationWithTranslation::append_rotation_wrt_center(m, amount)
|
RotationWithTranslation::append_rotation_wrt_center(m, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RotationTo
|
||||||
|
*/
|
||||||
|
/// Computes the angle of the rotation needed to transfom `a` to `b`.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn angle_between<V: RotationTo>(a: &V, b: &V) -> V::AngleType {
|
||||||
|
a.angle_to(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the rotation needed to transform `a` to `b`.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn rotation_between<V: RotationTo>(a: &V, b: &V) -> V::DeltaRotationType {
|
||||||
|
a.rotation_to(b)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RotationMatrix<LV, AV, R>
|
* RotationMatrix<LV, AV, R>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,7 +12,7 @@ use structs::{Vec3, Pnt3, Rot3, Mat3};
|
||||||
use traits::operations::{ApproxEq, Inv, POrd, POrdering, Axpy};
|
use traits::operations::{ApproxEq, Inv, POrd, POrdering, Axpy};
|
||||||
use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape, BaseFloat, BaseNum,
|
use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape, BaseFloat, BaseNum,
|
||||||
Bounded, Repeat};
|
Bounded, Repeat};
|
||||||
use traits::geometry::{Norm, Rotation, Rotate, Transform};
|
use traits::geometry::{Norm, Rotation, Rotate, RotationTo, Transform};
|
||||||
|
|
||||||
#[cfg(feature="arbitrary")]
|
#[cfg(feature="arbitrary")]
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
@ -456,6 +456,24 @@ impl<N: BaseNum + Neg<Output = N>> Rotate<Pnt3<N>> for UnitQuat<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: BaseFloat + ApproxEq<N>> RotationTo for UnitQuat<N> {
|
||||||
|
type AngleType = N;
|
||||||
|
type DeltaRotationType = UnitQuat<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn angle_to(&self, other: &Self) -> N {
|
||||||
|
let delta = self.rotation_to(other);
|
||||||
|
let _2 = ::one::<N>() + ::one();
|
||||||
|
|
||||||
|
_2 * delta.q.vector().norm().atan2(delta.q.w)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_to(&self, other: &Self) -> UnitQuat<N> {
|
||||||
|
*other / *self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: BaseNum + Neg<Output = N>> Transform<Vec3<N>> for UnitQuat<N> {
|
impl<N: BaseNum + Neg<Output = N>> Transform<Vec3<N>> for UnitQuat<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn transform(&self, v: &Vec3<N>) -> Vec3<N> {
|
fn transform(&self, v: &Vec3<N>) -> Vec3<N> {
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
use std::ops::{Mul, Neg, Index};
|
use std::ops::{Mul, Neg, Index};
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
use num::{Zero, One};
|
use num::{Zero, One};
|
||||||
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, Transform, ToHomogeneous,
|
use traits::geometry::{Rotate, Rotation, AbsoluteRotate, RotationMatrix, RotationTo, Transform,
|
||||||
Norm, Cross};
|
ToHomogeneous, Norm, Cross};
|
||||||
use traits::structure::{Cast, Dim, Row, Col, BaseFloat, BaseNum, Eye, Diag};
|
use traits::structure::{Cast, Dim, Row, Col, BaseFloat, BaseNum, Eye, Diag};
|
||||||
use traits::operations::{Absolute, Inv, Transpose, ApproxEq};
|
use traits::operations::{Absolute, Inv, Transpose, ApproxEq};
|
||||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
||||||
|
@ -71,6 +71,21 @@ impl<N: BaseFloat + Clone> Rotation<Vec1<N>> for Rot2<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: BaseFloat> RotationTo for Rot2<N> {
|
||||||
|
type AngleType = N;
|
||||||
|
type DeltaRotationType = Rot2<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn angle_to(&self, other: &Self) -> N {
|
||||||
|
self.rotation_to(other).rotation().norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_to(&self, other: &Self) -> Rot2<N> {
|
||||||
|
*other * ::inv(self).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: Rand + BaseFloat> Rand for Rot2<N> {
|
impl<N: Rand + BaseFloat> Rand for Rot2<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
|
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
|
||||||
|
@ -283,6 +298,22 @@ Rotation<Vec3<N>> for Rot3<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: BaseFloat> RotationTo for Rot3<N> {
|
||||||
|
type AngleType = N;
|
||||||
|
type DeltaRotationType = Rot3<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn angle_to(&self, other: &Self) -> N {
|
||||||
|
// FIXME: refactor to avoid the normalization of the rotation axisangle vector.
|
||||||
|
self.rotation_to(other).rotation().norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_to(&self, other: &Self) -> Rot3<N> {
|
||||||
|
*other * ::inv(self).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: Clone + Rand + BaseFloat> Rand for Rot3<N> {
|
impl<N: Clone + Rand + BaseFloat> Rand for Rot3<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
|
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
|
||||||
|
|
|
@ -1,9 +1,50 @@
|
||||||
use std::ops::{Sub, Mul, Neg};
|
use std::ops::{Sub, Mul, Neg};
|
||||||
use num::{Zero, One};
|
use num::{Zero, One};
|
||||||
use traits::structure::{Cast, Row, Basis, BaseFloat};
|
use traits::structure::{Cast, Row, Basis, BaseFloat};
|
||||||
use traits::geometry::{Norm, Cross, CrossMatrix, UniformSphereSample};
|
use traits::geometry::{Norm, Cross, CrossMatrix, RotationTo, UniformSphereSample};
|
||||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
use structs::vec::{Vec1, Vec2, Vec3, Vec4};
|
||||||
use structs::mat::Mat3;
|
use structs::mat::Mat3;
|
||||||
|
use structs::rot::{Rot2, Rot3};
|
||||||
|
|
||||||
|
impl<N: BaseFloat> RotationTo for Vec2<N> {
|
||||||
|
type AngleType = N;
|
||||||
|
type DeltaRotationType = Rot2<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn angle_to(&self, other: &Self) -> N {
|
||||||
|
::cross(self, other).x.atan2(::dot(self, other))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_to(&self, other: &Self) -> Rot2<N> {
|
||||||
|
Rot2::new(Vec1::new(self.angle_to(other)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: BaseFloat> RotationTo for Vec3<N> {
|
||||||
|
type AngleType = N;
|
||||||
|
type DeltaRotationType = Rot3<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn angle_to(&self, other: &Self) -> N {
|
||||||
|
::cross(self, other).norm().atan2(::dot(self, other))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_to(&self, other: &Self) -> Rot3<N> {
|
||||||
|
let mut axis = ::cross(self, other);
|
||||||
|
let norm = axis.normalize_mut();
|
||||||
|
|
||||||
|
if ::is_zero(&norm) {
|
||||||
|
::one()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let axis_angle = axis * norm.atan2(::dot(self, other));
|
||||||
|
|
||||||
|
Rot3::new(axis_angle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: Copy + Mul<N, Output = N> + Sub<N, Output = N>> Cross for Vec2<N> {
|
impl<N: Copy + Mul<N, Output = N> + Sub<N, Output = N>> Cross for Vec2<N> {
|
||||||
type CrossProductType = Vec1<N>;
|
type CrossProductType = Vec1<N>;
|
||||||
|
|
|
@ -79,7 +79,7 @@ macro_rules! at_fast_impl(
|
||||||
// However, f32/f64 does not implement Ord…
|
// However, f32/f64 does not implement Ord…
|
||||||
macro_rules! ord_impl(
|
macro_rules! ord_impl(
|
||||||
($t: ident, $comp0: ident, $($compN: ident),*) => (
|
($t: ident, $comp0: ident, $($compN: ident),*) => (
|
||||||
impl<N: BaseFloat + Copy> POrd for $t<N> {
|
impl<N: BaseFloat> POrd for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inf(&self, other: &$t<N>) -> $t<N> {
|
fn inf(&self, other: &$t<N>) -> $t<N> {
|
||||||
$t::new(self.$comp0.min(other.$comp0)
|
$t::new(self.$comp0.min(other.$comp0)
|
||||||
|
@ -291,7 +291,7 @@ macro_rules! container_impl(
|
||||||
|
|
||||||
macro_rules! basis_impl(
|
macro_rules! basis_impl(
|
||||||
($t: ident, $dim: expr) => (
|
($t: ident, $dim: expr) => (
|
||||||
impl<N: Copy + BaseFloat + ApproxEq<N>> Basis for $t<N> {
|
impl<N: BaseFloat + ApproxEq<N>> Basis for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn canonical_basis<F: FnMut($t<N>) -> bool>(mut f: F) {
|
fn canonical_basis<F: FnMut($t<N>) -> bool>(mut f: F) {
|
||||||
for i in 0..$dim {
|
for i in 0..$dim {
|
||||||
|
@ -547,7 +547,7 @@ macro_rules! translation_impl(
|
||||||
|
|
||||||
macro_rules! norm_impl(
|
macro_rules! norm_impl(
|
||||||
($t: ident, $($compN: ident),+) => (
|
($t: ident, $($compN: ident),+) => (
|
||||||
impl<N: Copy + BaseFloat> Norm<N> for $t<N> {
|
impl<N: BaseFloat> Norm<N> for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sqnorm(&self) -> N {
|
fn sqnorm(&self) -> N {
|
||||||
Dot::dot(self, self)
|
Dot::dot(self, self)
|
||||||
|
|
|
@ -64,6 +64,22 @@ pub trait Rotation<V> {
|
||||||
fn set_rotation(&mut self, V);
|
fn set_rotation(&mut self, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait of object that can be rotated to be superimposed with another one of the same nature.
|
||||||
|
pub trait RotationTo {
|
||||||
|
/// Type of the angle between two elements.
|
||||||
|
type AngleType;
|
||||||
|
|
||||||
|
/// Type of the rotation between two elements.
|
||||||
|
type DeltaRotationType;
|
||||||
|
|
||||||
|
/// Computes an angle nedded to transform the first element to the second one using a
|
||||||
|
/// rotation.
|
||||||
|
fn angle_to(&self, other: &Self) -> Self::AngleType;
|
||||||
|
|
||||||
|
/// Computes the smallest rotation needed to transform the first element to the second one.
|
||||||
|
fn rotation_to(&self, other: &Self) -> Self::DeltaRotationType;
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait of objects able to rotate other objects.
|
/// Trait of objects able to rotate other objects.
|
||||||
///
|
///
|
||||||
/// This is typically implemented by matrices which rotate vectors.
|
/// This is typically implemented by matrices which rotate vectors.
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! Mathematical traits.
|
//! Mathematical traits.
|
||||||
|
|
||||||
pub use traits::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Orig,
|
pub use traits::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Orig,
|
||||||
Rotate, Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
|
Rotate, Rotation, RotationMatrix, RotationWithTranslation, RotationTo,
|
||||||
Transform, Transformation, Translate, Translation, UniformSphereSample};
|
ToHomogeneous, Transform, Transformation, Translate, Translation,
|
||||||
|
UniformSphereSample};
|
||||||
|
|
||||||
pub use traits::structure::{FloatVec, FloatPnt, Basis, Cast, Col, Dim, Indexable, Iterable,
|
pub use traits::structure::{FloatVec, FloatPnt, Basis, Cast, Col, Dim, Indexable, Iterable,
|
||||||
IterableMut, Mat, SquareMat, Row, NumVec, NumPnt, PntAsVec, ColSlice,
|
IterableMut, Mat, SquareMat, Row, NumVec, NumPnt, PntAsVec, ColSlice,
|
||||||
|
|
Loading…
Reference in New Issue