Added ToComponents. Moved from_value into .

This commit is contained in:
Dzmitry Malyshau 2015-03-01 01:05:22 -05:00
parent 0c74d2a551
commit bf257a3e49
4 changed files with 69 additions and 23 deletions

View file

@ -15,7 +15,7 @@
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![crate_type = "dylib"] #![crate_type = "dylib"]
#![feature(old_impl_check, plugin, core, hash, std_misc)] #![feature(old_impl_check, plugin, core, std_misc)]
#![plugin(rand_macros)] #![plugin(rand_macros)]
//! Computer graphics-centric math. //! Computer graphics-centric math.

View file

@ -16,7 +16,7 @@
use std::fmt; use std::fmt;
use approx::ApproxEq; use approx::ApproxEq;
use matrix::{Matrix, Matrix4, ToMatrix4}; use matrix::{Matrix, ToMatrix3, Matrix4, ToMatrix4};
use num::{BaseNum, BaseFloat, zero, one}; use num::{BaseNum, BaseFloat, zero, one};
use point::{Point, Point3}; use point::{Point, Point3};
use ray::Ray; use ray::Ray;
@ -84,7 +84,12 @@ pub struct Decomposed<S, V, R> {
pub disp: V, pub disp: V,
} }
impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform<S, V, P> for Decomposed<S, V, R> { impl<
S: BaseFloat,
V: Vector<S>,
P: Point<S, V>,
R: Rotation<S, V, P>
> Transform<S, V, P> for Decomposed<S, V, R> {
#[inline] #[inline]
fn identity() -> Decomposed<S, V, R> { fn identity() -> Decomposed<S, V, R> {
Decomposed { Decomposed {
@ -142,7 +147,10 @@ impl<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> Transform
pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {} pub trait Transform3<S>: Transform<S, Vector3<S>, Point3<S>> + ToMatrix4<S> {}
impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> { impl<
S: BaseFloat + 'static,
R: Rotation3<S>
> ToMatrix4<S> for Decomposed<S, Vector3<S>, R> {
fn to_matrix4(&self) -> Matrix4<S> { fn to_matrix4(&self) -> Matrix4<S> {
let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4(); let mut m = self.rot.to_matrix3().mul_s(self.scale.clone()).to_matrix4();
m.w = self.disp.extend(one()); m.w = self.disp.extend(one());
@ -150,9 +158,15 @@ impl<S: BaseFloat + 'static, R: Rotation3<S>> ToMatrix4<S> for Decomposed<S, Vec
} }
} }
impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<S,Vector3<S>,R> where S: 'static {} impl<
S: BaseFloat + 'static,
R: Rotation3<S>
> Transform3<S> for Decomposed<S, Vector3<S>, R> {}
impl<S: BaseFloat, R: fmt::Debug + Rotation3<S>> fmt::Debug for Decomposed<S,Vector3<S>,R> { impl<
S: BaseFloat,
R: fmt::Debug + Rotation3<S>
> fmt::Debug for Decomposed<S, Vector3<S>, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(scale({:?}), rot({:?}), disp{:?})", write!(f, "(scale({:?}), rot({:?}), disp{:?})",
self.scale, self.rot, self.disp) self.scale, self.rot, self.disp)
@ -202,3 +216,40 @@ impl<S: BaseNum> ToMatrix4<S> for AffineMatrix3<S> {
} }
impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> where S: 'static {} impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> where S: 'static {}
/// A trait that allows extracting components (rotation, translation, scale)
/// from an arbitrary transformation/
pub trait ToComponents<S, V: Vector<S>, P: Point<S, V>> {
/// Associated rotation type
type Rotation;
/// Extract translation component
fn to_translation(&self) -> V;
/// Extract rotation component
fn to_rotation(&self) -> Self::Rotation;
/// Extract scale component
fn to_scale(&self) -> V;
}
impl<
S: BaseFloat,
V: Vector<S> + Clone,
P: Point<S, V>,
R: Rotation<S, V, P> + Clone,
> ToComponents<S, V, P> for Decomposed<S, V, R> {
type Rotation = R;
fn to_translation(&self) -> V {
self.disp.clone()
}
fn to_rotation(&self) -> R {
self.rot.clone()
}
fn to_scale(&self) -> V {
Vector::from_value(self.scale)
}
}
pub trait ToComponents3<S>: ToComponents<S, Vector3<S>, Point3<S>>
where Self::Rotation: ToMatrix3<S> {}

View file

@ -22,11 +22,11 @@
//! vector are also provided: //! vector are also provided:
//! //!
//! ```rust //! ```rust
//! use cgmath::{Vector2, Vector3, Vector4, one, zero, vec3}; //! use cgmath::{Vector, Vector2, Vector3, Vector4, zero, vec2, vec3};
//! //!
//! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x()); //! assert_eq!(Vector2::new(1.0f64, 0.0f64), Vector2::unit_x());
//! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero()); //! assert_eq!(vec3(0.0f64, 0.0f64, 0.0f64), zero());
//! assert_eq!(Vector4::from_value(1.0f64), one()); //! assert_eq!(Vector::from_value(1.0f64), vec2(1.0, 1.0));
//! ``` //! ```
//! //!
//! Vectors can be manipulated with typical mathematical operations (addition, //! Vectors can be manipulated with typical mathematical operations (addition,
@ -76,7 +76,7 @@
//! //!
//! // Scalar multiplication can return a new object, or be done in place //! // Scalar multiplication can return a new object, or be done in place
//! // to avoid an allocation: //! // to avoid an allocation:
//! let mut c: Vector4<f64> = Vector4::from_value(3.0); //! let mut c: Vector4<f64> = Vector::from_value(3.0);
//! let d: Vector4<f64> = c.mul_s(2.0); //! let d: Vector4<f64> = c.mul_s(2.0);
//! c.mul_self_s(2.0); //! c.mul_self_s(2.0);
//! assert_eq!(c, d); //! assert_eq!(c, d);
@ -110,6 +110,8 @@ use num::{BaseNum, BaseFloat, Zero, One, zero, one};
/// of these make sense from a linear algebra point of view, but are included /// of these make sense from a linear algebra point of view, but are included
/// for pragmatic reasons. /// for pragmatic reasons.
pub trait Vector<S: BaseNum>: Array1<S> + Zero + One + Neg<Output=Self> { pub trait Vector<S: BaseNum>: Array1<S> + Zero + One + Neg<Output=Self> {
/// Construct a vector from a single value, replicating it.
fn from_value(s: S) -> Self;
/// Add a scalar to this vector, returning a new vector. /// Add a scalar to this vector, returning a new vector.
#[must_use] #[must_use]
fn add_s(&self, s: S) -> Self; fn add_s(&self, s: S) -> Self;
@ -206,14 +208,6 @@ macro_rules! vec(
$Self_::new($($field),+) $Self_::new($($field),+)
} }
impl<$S: Copy> $Self_<$S> {
/// Construct a vector from a single value, replicating it.
#[inline]
pub fn from_value(value: $S) -> $Self_<$S> {
$Self_ { $($field: value),+ }
}
}
impl<$S: Zero> Zero for $Self_<$S> { impl<$S: Zero> Zero for $Self_<$S> {
#[inline] #[inline]
fn zero() -> $Self_<S> { $Self_ { $($field: zero()),+ } } fn zero() -> $Self_<S> { $Self_ { $($field: zero()),+ } }
@ -292,6 +286,7 @@ macro_rules! vec(
} }
impl<S: BaseNum> Vector<S> for $Self_<S> { impl<S: BaseNum> Vector<S> for $Self_<S> {
#[inline] fn from_value(s: S) -> $Self_<S> { $Self_ { $($field: s),+ } }
#[inline] fn add_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field + s),+) } #[inline] fn add_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field + s),+) }
#[inline] fn sub_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field - s),+) } #[inline] fn sub_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field - s),+) }
#[inline] fn mul_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field * s),+) } #[inline] fn mul_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field * s),+) }

View file

@ -31,9 +31,9 @@ fn test_constructor() {
#[test] #[test]
fn test_from_value() { fn test_from_value() {
assert_eq!(Vector2::from_value(102is), Vector2::new(102is, 102is)); assert_eq!(Vector::from_value(102is), Vector2::new(102is, 102is));
assert_eq!(Vector3::from_value(22is), Vector3::new(22is, 22is, 22is)); assert_eq!(Vector::from_value(22is), Vector3::new(22is, 22is, 22is));
assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64)); assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
} }
#[test] #[test]