Merge pull request #358 from bjz/rotation-one
Make Rotation trait depend on One
This commit is contained in:
commit
a7f4aa1756
4 changed files with 33 additions and 67 deletions
|
@ -58,12 +58,6 @@ impl<S: BaseFloat> Quaternion<S> {
|
||||||
Quaternion { s: s, v: v }
|
Quaternion { s: s, v: v }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The multiplicative identity.
|
|
||||||
#[inline]
|
|
||||||
pub fn one() -> Quaternion<S> {
|
|
||||||
Quaternion::from_sv(S::one(), Vector3::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The conjugate of the quaternion.
|
/// The conjugate of the quaternion.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn conjugate(self) -> Quaternion<S> {
|
pub fn conjugate(self) -> Quaternion<S> {
|
||||||
|
@ -131,6 +125,13 @@ impl<S: BaseFloat> Zero for Quaternion<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat> One for Quaternion<S> {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Quaternion<S> {
|
||||||
|
Quaternion::from_sv(S::one(), Vector3::zero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> VectorSpace for Quaternion<S> {
|
impl<S: BaseFloat> VectorSpace for Quaternion<S> {
|
||||||
type Scalar = S;
|
type Scalar = S;
|
||||||
}
|
}
|
||||||
|
@ -332,9 +333,6 @@ impl<S: BaseFloat> From<Quaternion<S>> for Basis3<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
|
impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
|
||||||
#[inline]
|
|
||||||
fn one() -> Quaternion<S> { Quaternion::one() }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Quaternion<S> {
|
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Quaternion<S> {
|
||||||
Matrix3::look_at(dir, up).into()
|
Matrix3::look_at(dir, up).into()
|
||||||
|
@ -350,17 +348,8 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self * vec }
|
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self * vec }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat(&self, other: &Quaternion<S>) -> Quaternion<S> { self * other }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat_self(&mut self, other: &Quaternion<S>) { *self = &*self * other; }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn invert(&self) -> Quaternion<S> { self.conjugate() / self.magnitude2() }
|
fn invert(&self) -> Quaternion<S> { self.conjugate() / self.magnitude2() }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn invert_self(&mut self) { *self = self.invert() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation3<S> for Quaternion<S> {
|
impl<S: BaseFloat> Rotation3<S> for Quaternion<S> {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::*;
|
||||||
|
|
||||||
use structure::*;
|
use structure::*;
|
||||||
|
|
||||||
|
@ -28,14 +29,11 @@ use vector::{Vector2, Vector3};
|
||||||
|
|
||||||
/// A trait for a generic rotation. A rotation is a transformation that
|
/// A trait for a generic rotation. A rotation is a transformation that
|
||||||
/// creates a circular motion, and preserves at least one point in the space.
|
/// creates a circular motion, and preserves at least one point in the space.
|
||||||
pub trait Rotation<P: EuclideanSpace>: PartialEq + Sized where
|
pub trait Rotation<P: EuclideanSpace>: Sized + Copy + One where
|
||||||
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
|
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
|
||||||
Self: ApproxEq<Epsilon = <P as EuclideanSpace>::Scalar>,
|
Self: ApproxEq<Epsilon = <P as EuclideanSpace>::Scalar>,
|
||||||
<P as EuclideanSpace>::Scalar: BaseFloat,
|
<P as EuclideanSpace>::Scalar: BaseFloat,
|
||||||
{
|
{
|
||||||
/// Create the identity transform (causes no transformation).
|
|
||||||
fn one() -> Self;
|
|
||||||
|
|
||||||
/// Create a rotation to a given direction with an 'up' vector
|
/// Create a rotation to a given direction with an 'up' vector
|
||||||
fn look_at(dir: P::Diff, up: P::Diff) -> Self;
|
fn look_at(dir: P::Diff, up: P::Diff) -> Self;
|
||||||
|
|
||||||
|
@ -53,24 +51,9 @@ pub trait Rotation<P: EuclideanSpace>: PartialEq + Sized where
|
||||||
P::from_vec(self.rotate_vector(point.to_vec()))
|
P::from_vec(self.rotate_vector(point.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new rotation which combines both this rotation, and another.
|
|
||||||
fn concat(&self, other: &Self) -> Self;
|
|
||||||
|
|
||||||
/// Create a new rotation which "un-does" this rotation. That is,
|
/// Create a new rotation which "un-does" this rotation. That is,
|
||||||
/// `r.concat(r.invert())` is the identity.
|
/// `r * r.invert()` is the identity.
|
||||||
fn invert(&self) -> Self;
|
fn invert(&self) -> Self;
|
||||||
|
|
||||||
/// Modify this rotation in-place by combining it with another.
|
|
||||||
#[inline]
|
|
||||||
fn concat_self(&mut self, other: &Self) {
|
|
||||||
*self = Self::concat(self, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invert this rotation in-place.
|
|
||||||
#[inline]
|
|
||||||
fn invert_self(&mut self) {
|
|
||||||
*self = self.invert();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A two-dimensional rotation.
|
/// A two-dimensional rotation.
|
||||||
|
@ -151,7 +134,7 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
|
||||||
///
|
///
|
||||||
/// // Note that we can also concatenate rotations:
|
/// // Note that we can also concatenate rotations:
|
||||||
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
|
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
|
||||||
/// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(unit_x);
|
/// let unit_y3 = (rot_half * rot_half).rotate_vector(unit_x);
|
||||||
/// assert!(unit_y3.approx_eq(&unit_y2));
|
/// assert!(unit_y3.approx_eq(&unit_y2));
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
|
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
|
@ -172,9 +155,6 @@ impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
||||||
#[inline]
|
|
||||||
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::identity() } }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Basis2<S> {
|
fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Basis2<S> {
|
||||||
Basis2 { mat: Matrix2::look_at(dir, up) }
|
Basis2 { mat: Matrix2::look_at(dir, up) }
|
||||||
|
@ -188,18 +168,21 @@ impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat * vec }
|
fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat * vec }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat * other.mat } }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat_self(&mut self, other: &Basis2<S>) { self.mat = self.mat * other.mat; }
|
|
||||||
|
|
||||||
// TODO: we know the matrix is orthogonal, so this could be re-written
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
||||||
// to be faster
|
// to be faster
|
||||||
#[inline]
|
#[inline]
|
||||||
fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }
|
fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat> One for Basis2<S> {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_operator!(<S: BaseFloat> Mul<Basis2<S> > for Basis2<S> {
|
||||||
|
fn mul(lhs, rhs) -> Basis2<S> { Basis2 { mat: lhs.mat * rhs.mat } }
|
||||||
|
});
|
||||||
|
|
||||||
impl<S: BaseFloat> ApproxEq for Basis2<S> {
|
impl<S: BaseFloat> ApproxEq for Basis2<S> {
|
||||||
type Epsilon = S;
|
type Epsilon = S;
|
||||||
|
|
||||||
|
@ -257,9 +240,6 @@ impl<S: BaseFloat> From<Basis3<S>> for Quaternion<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
|
impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
|
||||||
#[inline]
|
|
||||||
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::identity() } }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Basis3<S> {
|
fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Basis3<S> {
|
||||||
Basis3 { mat: Matrix3::look_at(dir, up) }
|
Basis3 { mat: Matrix3::look_at(dir, up) }
|
||||||
|
@ -274,18 +254,21 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat * vec }
|
fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat * vec }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat * other.mat } }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn concat_self(&mut self, other: &Basis3<S>) { self.mat = self.mat * other.mat; }
|
|
||||||
|
|
||||||
// TODO: we know the matrix is orthogonal, so this could be re-written
|
// TODO: we know the matrix is orthogonal, so this could be re-written
|
||||||
// to be faster
|
// to be faster
|
||||||
#[inline]
|
#[inline]
|
||||||
fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }
|
fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat> One for Basis3<S> {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_operator!(<S: BaseFloat> Mul<Basis3<S> > for Basis3<S> {
|
||||||
|
fn mul(lhs, rhs) -> Basis3<S> { Basis3 { mat: lhs.mat * rhs.mat } }
|
||||||
|
});
|
||||||
|
|
||||||
impl<S: BaseFloat> ApproxEq for Basis3<S> {
|
impl<S: BaseFloat> ApproxEq for Basis3<S> {
|
||||||
type Epsilon = S;
|
type Epsilon = S;
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,6 @@ pub trait Transform<P: EuclideanSpace>: Sized {
|
||||||
/// Transform a point using this transform.
|
/// Transform a point using this transform.
|
||||||
fn transform_point(&self, point: P) -> P;
|
fn transform_point(&self, point: P) -> P;
|
||||||
|
|
||||||
/// Transform a vector as a point using this transform.
|
|
||||||
#[inline]
|
|
||||||
fn transform_as_point(&self, vec: P::Diff) -> P::Diff {
|
|
||||||
self.transform_point(P::from_vec(vec)).to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Combine this transform with another, yielding a new transformation
|
/// Combine this transform with another, yielding a new transformation
|
||||||
/// which has the effects of both.
|
/// which has the effects of both.
|
||||||
fn concat(&self, other: &Self) -> Self;
|
fn concat(&self, other: &Self) -> Self;
|
||||||
|
@ -108,8 +102,8 @@ impl<P: EuclideanSpace, R: Rotation<P>> Transform<P> for Decomposed<P::Diff, R>
|
||||||
fn concat(&self, other: &Decomposed<P::Diff, R>) -> Decomposed<P::Diff, R> {
|
fn concat(&self, other: &Decomposed<P::Diff, R>) -> Decomposed<P::Diff, R> {
|
||||||
Decomposed {
|
Decomposed {
|
||||||
scale: self.scale * other.scale,
|
scale: self.scale * other.scale,
|
||||||
rot: self.rot.concat(&other.rot),
|
rot: self.rot * other.rot,
|
||||||
disp: self.transform_as_point(other.disp.clone()),
|
disp: self.disp + other.disp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ mod rotation {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invert_basis2() {
|
fn test_invert_basis2() {
|
||||||
let a: Basis2<_> = rotation::a2();
|
let a: Basis2<_> = rotation::a2();
|
||||||
let a = a.concat(&a.invert());
|
let a = a * a.invert();
|
||||||
let a: &Matrix2<_> = a.as_ref();
|
let a: &Matrix2<_> = a.as_ref();
|
||||||
assert!(a.is_identity());
|
assert!(a.is_identity());
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ fn test_invert_basis2() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invert_basis3() {
|
fn test_invert_basis3() {
|
||||||
let a: Basis3<_> = rotation::a3();
|
let a: Basis3<_> = rotation::a3();
|
||||||
let a = a.concat(&a.invert());
|
let a = a * a.invert();
|
||||||
let a: &Matrix3<_> = a.as_ref();
|
let a: &Matrix3<_> = a.as_ref();
|
||||||
assert!(a.is_identity());
|
assert!(a.is_identity());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue