From 78f86a33cda184a7e6a5432e2bdfe14e186f8098 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 3 Oct 2015 15:17:09 +1000 Subject: [PATCH 1/8] Make vectors an associated type on Point --- src/point.rs | 25 +++++++---- src/quaternion.rs | 2 +- src/rotation.rs | 22 +++++----- src/transform.rs | 105 ++++++++++++++++------------------------------ 4 files changed, 63 insertions(+), 91 deletions(-) diff --git a/src/point.rs b/src/point.rs index 613e1df1..3378b86b 100644 --- a/src/point.rs +++ b/src/point.rs @@ -66,7 +66,7 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point>: Array1 + Clone // where +pub trait Point: Array1 + Clone // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, @@ -76,13 +76,16 @@ pub trait Point>: Array1 + Clone // where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { + /// The associated displacement vector. + type Vector: Vector; + /// Create a point at the origin. fn origin() -> Self; /// Create a point from a vector. - fn from_vec(v: &V) -> Self; + fn from_vec(v: &Self::Vector) -> Self; /// Convert a point to a vector. - fn to_vec(&self) -> V; + fn to_vec(&self) -> Self::Vector; /// Multiply each component by a scalar, returning the new point. #[must_use] @@ -96,9 +99,9 @@ pub trait Point>: Array1 + Clone // where /// Add a vector to this point, returning the new point. #[must_use] - fn add_v(&self, v: &V) -> Self; + fn add_v(&self, v: &Self::Vector) -> Self; /// Subtract another point from this one, returning a new vector. - fn sub_p(&self, p: &Self) -> V; + fn sub_p(&self, p: &Self) -> Self::Vector; /// Multiply each component by a scalar, in-place. fn mul_self_s(&mut self, s: S); @@ -108,10 +111,10 @@ pub trait Point>: Array1 + Clone // where fn rem_self_s(&mut self, s: S); /// Add a vector to this point, in-place. - fn add_self_v(&mut self, v: &V); + fn add_self_v(&mut self, v: &Self::Vector); /// This is a weird one, but its useful for plane calculations. - fn dot(&self, v: &V) -> S; + fn dot(&self, v: &Self::Vector) -> S; #[must_use] fn min(&self, p: &Self) -> Self; @@ -122,7 +125,9 @@ pub trait Point>: Array1 + Clone // where impl Array1 for Point2 {} -impl Point> for Point2 { +impl Point for Point2 { + type Vector = Vector2; + #[inline] fn origin() -> Point2 { Point2::new(S::zero(), S::zero()) @@ -195,7 +200,9 @@ impl ApproxEq for Point2 { impl Array1 for Point3 {} -impl Point> for Point3 { +impl Point for Point3 { + type Vector = Vector3; + #[inline] fn origin() -> Point3 { Point3::new(S::zero(), S::zero(), S::zero()) diff --git a/src/quaternion.rs b/src/quaternion.rs index 29ddcc53..73cdff5f 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -339,7 +339,7 @@ impl From> for Basis3 { fn from(quat: Quaternion) -> Basis3 { Basis3::from_quaternion(&quat) } } -impl Rotation, Point3> for Quaternion { +impl Rotation> for Quaternion { #[inline] fn one() -> Quaternion { Quaternion::one() } diff --git a/src/rotation.rs b/src/rotation.rs index ec683d9f..f7340b19 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -25,19 +25,19 @@ use vector::{Vector, Vector2, Vector3}; /// 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. -pub trait Rotation, P: Point>: PartialEq + ApproxEq + Sized { +pub trait Rotation>: PartialEq + ApproxEq + Sized { /// Create the identity transform (causes no transformation). fn one() -> Self; /// Create a rotation to a given direction with an 'up' vector - fn look_at(dir: &V, up: &V) -> Self; + fn look_at(dir: &P::Vector, up: &P::Vector) -> Self; /// Create a shortest rotation to transform vector 'a' into 'b'. /// Both given vectors are assumed to have unit length. - fn between_vectors(a: &V, b: &V) -> Self; + fn between_vectors(a: &P::Vector, b: &P::Vector) -> Self; /// Rotate a vector using this rotation. - fn rotate_vector(&self, vec: &V) -> V; + fn rotate_vector(&self, vec: &P::Vector) -> P::Vector; /// Rotate a point using this rotation, by converting it to its /// representation as a vector. @@ -67,7 +67,7 @@ pub trait Rotation, P: Point>: PartialEq + Appr } /// A two-dimensional rotation. -pub trait Rotation2: Rotation, Point2> +pub trait Rotation2: Rotation> + Into> + Into> { /// Create a rotation by a given angle. Thus is a redundant case of both @@ -76,7 +76,7 @@ pub trait Rotation2: Rotation, Point2> } /// A three-dimensional rotation. -pub trait Rotation3: Rotation, Point3> +pub trait Rotation3: Rotation> + Into> + Into> + Into> { @@ -172,7 +172,7 @@ impl From> for Matrix2 { fn from(b: Basis2) -> Matrix2 { b.mat } } -impl Rotation, Point2> for Basis2 { +impl Rotation> for Basis2 { #[inline] fn one() -> Basis2 { Basis2 { mat: Matrix2::one() } } @@ -213,7 +213,7 @@ impl ApproxEq for Basis2 { } } -impl Rotation2 for Basis2 { +impl Rotation2 for Basis2 { fn from_angle(theta: Rad) -> Basis2 { Basis2 { mat: Matrix2::from_angle(theta) } } } @@ -248,12 +248,12 @@ impl From> for Matrix3 { fn from(b: Basis3) -> Matrix3 { b.mat } } -impl From> for Quaternion { +impl From> for Quaternion { #[inline] fn from(b: Basis3) -> Quaternion { b.mat.into() } } -impl Rotation, Point3> for Basis3 { +impl Rotation> for Basis3 { #[inline] fn one() -> Basis3 { Basis3 { mat: Matrix3::one() } } @@ -295,7 +295,7 @@ impl ApproxEq for Basis3 { } } -impl Rotation3 for Basis3 { +impl Rotation3 for Basis3 { fn from_axis_angle(axis: &Vector3, angle: Rad) -> Basis3 { Basis3 { mat: Matrix3::from_axis_angle(axis, angle) } } diff --git a/src/transform.rs b/src/transform.rs index 6560eb28..900df117 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -27,24 +27,24 @@ use vector::*; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// can be applied to points or vectors. An affine transformation is one which -pub trait Transform, P: Point>: Sized { +pub trait Transform>: Sized { /// Create an identity transformation. That is, a transformation which /// does nothing. fn one() -> Self; /// Create a transformation that rotates a vector to look at `center` from /// `eye`, using `up` for orientation. - fn look_at(eye: &P, center: &P, up: &V) -> Self; + fn look_at(eye: &P, center: &P, up: &P::Vector) -> Self; /// Transform a vector using this transform. - fn transform_vector(&self, vec: &V) -> V; + fn transform_vector(&self, vec: &P::Vector) -> P::Vector; /// Transform a point using this transform. fn transform_point(&self, point: &P) -> P; /// Transform a vector as a point using this transform. #[inline] - fn transform_as_point(&self, vec: &V) -> V { + fn transform_as_point(&self, vec: &P::Vector) -> P::Vector { self.transform_point(&P::from_vec(vec)).to_vec() } @@ -78,23 +78,18 @@ pub struct Decomposed { pub disp: V, } -impl< - S: BaseFloat, - V: Vector, - P: Point, - R: Rotation, -> Transform for Decomposed { +impl, R: Rotation> Transform for Decomposed { #[inline] - fn one() -> Decomposed { + fn one() -> Decomposed { Decomposed { scale: S::one(), rot: R::one(), - disp: V::zero(), + disp: P::Vector::zero(), } } #[inline] - fn look_at(eye: &P, center: &P, up: &V) -> Decomposed { + fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed { let rot = R::look_at(¢er.sub_p(eye), up); let disp = rot.rotate_vector(&P::origin().sub_p(eye)); Decomposed { @@ -105,7 +100,7 @@ impl< } #[inline] - fn transform_vector(&self, vec: &V) -> V { + fn transform_vector(&self, vec: &P::Vector) -> P::Vector { self.rot.rotate_vector(&vec.mul_s(self.scale.clone())) } @@ -114,7 +109,7 @@ impl< self.rot.rotate_point(&point.mul_s(self.scale.clone())).add_v(&self.disp) } - fn concat(&self, other: &Decomposed) -> Decomposed { + fn concat(&self, other: &Decomposed) -> Decomposed { Decomposed { scale: self.scale * other.scale, rot: self.rot.concat(&other.rot), @@ -122,7 +117,7 @@ impl< } } - fn invert(&self) -> Option> { + fn invert(&self) -> Option> { if self.scale.approx_eq(&S::zero()) { None } else { @@ -138,13 +133,10 @@ impl< } } -pub trait Transform2: Transform, Point2> + Into> {} -pub trait Transform3: Transform, Point3> + Into> {} +pub trait Transform2: Transform> + Into> {} +pub trait Transform3: Transform> + Into> {} -impl< - S: BaseFloat + 'static, - R: Rotation2, -> From, R>> for Matrix3 { +impl> From, R>> for Matrix3 { fn from(dec: Decomposed, R>) -> Matrix3 { let m: Matrix2<_> = dec.rot.into(); let mut m: Matrix3<_> = m.mul_s(dec.scale).into(); @@ -153,10 +145,7 @@ impl< } } -impl< - S: BaseFloat + 'static, - R: Rotation3, -> From, R>> for Matrix4 { +impl> From, R>> for Matrix4 { fn from(dec: Decomposed, R>) -> Matrix4 { let m: Matrix3<_> = dec.rot.into(); let mut m: Matrix4<_> = m.mul_s(dec.scale).into(); @@ -165,20 +154,11 @@ impl< } } -impl< - S: BaseFloat + 'static, - R: Rotation2, -> Transform2 for Decomposed, R> {} +impl> Transform2 for Decomposed, R> {} -impl< - S: BaseFloat + 'static, - R: Rotation3, -> Transform3 for Decomposed, R> {} +impl> Transform3 for Decomposed, R> {} -impl< - S: BaseFloat, - R: fmt::Debug + Rotation3, -> fmt::Debug for Decomposed, R> { +impl> fmt::Debug for Decomposed, R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(scale({:?}), rot({:?}), disp{:?})", self.scale, self.rot, self.disp) @@ -191,7 +171,7 @@ pub struct AffineMatrix3 { pub mat: Matrix4, } -impl Transform, Point3> for AffineMatrix3 { +impl Transform> for AffineMatrix3 { #[inline] fn one() -> AffineMatrix3 { AffineMatrix3 { mat: Matrix4::one() } @@ -227,22 +207,22 @@ impl From> for Matrix4 { #[inline] fn from(aff: AffineMatrix3) -> Matrix4 { aff.mat } } -impl Transform3 for AffineMatrix3 {} +impl Transform3 for AffineMatrix3 {} /// A trait that allows extracting components (rotation, translation, scale) /// from an arbitrary transformations -pub trait ToComponents, P: Point, R: Rotation> { +pub trait ToComponents, R: Rotation> { /// Extract the (scale, rotation, translation) triple - fn decompose(&self) -> (V, R, V); + fn decompose(&self) -> (P::Vector, R, P::Vector); } pub trait ToComponents2>: - ToComponents, Point2, R> {} + ToComponents, R> {} pub trait ToComponents3>: - ToComponents, Point3, R> {} + ToComponents, R> {} -pub trait CompositeTransform, P: Point, R: Rotation>: - Transform + ToComponents {} +pub trait CompositeTransform, R: Rotation>: + Transform + ToComponents {} pub trait CompositeTransform2>: Transform2 + ToComponents2 {} pub trait CompositeTransform3>: @@ -250,31 +230,16 @@ pub trait CompositeTransform3>: impl< S: BaseFloat, - V: Vector + Clone, - P: Point, - R: Rotation + Clone, -> ToComponents for Decomposed { - fn decompose(&self) -> (V, R, V) { - (V::one().mul_s(self.scale), self.rot.clone(), self.disp.clone()) + P: Point, + R: Rotation + Clone, +> ToComponents for Decomposed { + fn decompose(&self) -> (P::Vector, R, P::Vector) { + (P::Vector::one().mul_s(self.scale), self.rot.clone(), self.disp.clone()) } } -impl< - S: BaseFloat, - R: Rotation2 + Clone, -> ToComponents2 for Decomposed, R> {} - -impl< - S: BaseFloat, - R: Rotation3 + Clone, -> ToComponents3 for Decomposed, R> {} - -impl< - S: BaseFloat + 'static, - R: Rotation2 + Clone, -> CompositeTransform2 for Decomposed, R> {} +impl + Clone> ToComponents2 for Decomposed, R> {} +impl + Clone> ToComponents3 for Decomposed, R> {} -impl< - S: BaseFloat + 'static, - R: Rotation3 + Clone, -> CompositeTransform3 for Decomposed, R> {} +impl + Clone> CompositeTransform2 for Decomposed, R> {} +impl + Clone> CompositeTransform3 for Decomposed, R> {} From 0584bcac648c933f993ae2bc7f19fd5cc3003610 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 14:00:39 +1100 Subject: [PATCH 2/8] Make epsilon an associated type on ApproxEq --- src/angle.rs | 12 +++++++----- src/approx.rs | 20 +++++++++++--------- src/matrix.rs | 14 ++++++++++---- src/num.rs | 2 +- src/point.rs | 8 ++++++-- src/quaternion.rs | 4 +++- src/rotation.rs | 10 +++++++--- src/vector.rs | 6 ++++-- 8 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/angle.rs b/src/angle.rs index 0a0075b7..51a48dd4 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -80,7 +80,7 @@ pub trait Angle > : Clone + Zero + PartialEq + PartialOrd -+ ApproxEq ++ ApproxEq + Neg + Into> + Into> @@ -279,16 +279,18 @@ fmt::Debug for Deg { } } -impl -ApproxEq for Rad { +impl ApproxEq for Rad { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Rad, epsilon: &S) -> bool { self.s.approx_eq_eps(&other.s, epsilon) } } -impl -ApproxEq for Deg { +impl ApproxEq for Deg { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Deg, epsilon: &S) -> bool { self.s.approx_eq_eps(&other.s, epsilon) diff --git a/src/approx.rs b/src/approx.rs index 9d72430b..901952ef 100644 --- a/src/approx.rs +++ b/src/approx.rs @@ -16,23 +16,26 @@ use rust_num::{Float, NumCast}; use rust_num::traits::cast; -pub trait ApproxEq: Sized { - fn approx_epsilon(_hack: Option) -> T { +pub trait ApproxEq: Sized { + type Epsilon: NumCast + Float; + + fn approx_epsilon() -> Self::Epsilon { cast(1.0e-5f64).unwrap() } fn approx_eq(&self, other: &Self) -> bool { - let eps: T = ApproxEq::approx_epsilon(None::); - self.approx_eq_eps(other, &eps) + self.approx_eq_eps(other, &Self::approx_epsilon()) } - fn approx_eq_eps(&self, other: &Self, epsilon: &T) -> bool; + fn approx_eq_eps(&self, other: &Self, epsilon: &Self::Epsilon) -> bool; } macro_rules! approx_float( ($S:ident) => ( - impl ApproxEq<$S> for $S { + impl ApproxEq for $S { + type Epsilon = $S; + #[inline] fn approx_eq_eps(&self, other: &$S, epsilon: &$S) -> bool { (*self - *other).abs() < *epsilon @@ -62,9 +65,8 @@ macro_rules! assert_approx_eq( ($given: expr, $expected: expr) => ({ let (given_val, expected_val) = (&($given), &($expected)); if !given_val.approx_eq(expected_val) { - panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`, tolerance: `{:?}`)", - *given_val, *expected_val, - ApproxEq::approx_epsilon(Some(*given_val)) + panic!("assertion failed: `left ≈ right` (left: `{:?}`, right: `{:?}`)", + *given_val, *expected_val ); } }) diff --git a/src/matrix.rs b/src/matrix.rs index 1b3df687..3fd337cf 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -249,7 +249,7 @@ impl> Matrix4 { } } -pub trait Matrix + 'static>: Array2 + ApproxEq + Sized // where +pub trait Matrix + 'static>: Array2 + ApproxEq + Sized // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -790,7 +790,9 @@ impl Matrix> for Matrix4 { } } -impl ApproxEq for Matrix2 { +impl ApproxEq for Matrix2 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Matrix2, epsilon: &S) -> bool { self[0].approx_eq_eps(&other[0], epsilon) && @@ -798,7 +800,9 @@ impl ApproxEq for Matrix2 { } } -impl ApproxEq for Matrix3 { +impl ApproxEq for Matrix3 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Matrix3, epsilon: &S) -> bool { self[0].approx_eq_eps(&other[0], epsilon) && @@ -807,7 +811,9 @@ impl ApproxEq for Matrix3 { } } -impl ApproxEq for Matrix4 { +impl ApproxEq for Matrix4 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Matrix4, epsilon: &S) -> bool { self[0].approx_eq_eps(&other[0], epsilon) && diff --git a/src/num.rs b/src/num.rs index 787edb0f..9811d17f 100644 --- a/src/num.rs +++ b/src/num.rs @@ -110,7 +110,7 @@ impl BaseInt for u64 {} impl BaseInt for usize {} /// Base floating point types -pub trait BaseFloat : BaseNum + Float + ApproxEq {} +pub trait BaseFloat : BaseNum + Float + ApproxEq {} impl BaseFloat for f32 {} impl BaseFloat for f64 {} diff --git a/src/point.rs b/src/point.rs index 3378b86b..1f917f14 100644 --- a/src/point.rs +++ b/src/point.rs @@ -190,7 +190,9 @@ impl Point for Point2 { } } -impl ApproxEq for Point2 { +impl ApproxEq for Point2 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Point2, epsilon: &S) -> bool { self.x.approx_eq_eps(&other.x, epsilon) && @@ -270,7 +272,9 @@ impl Point for Point3 { } } -impl ApproxEq for Point3 { +impl ApproxEq for Point3 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Point3, epsilon: &S) -> bool { self.x.approx_eq_eps(&other.x, epsilon) && diff --git a/src/quaternion.rs b/src/quaternion.rs index 73cdff5f..51802e87 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -170,7 +170,9 @@ impl<'a, 'b, S: BaseFloat> Mul<&'b Quaternion> for &'a Quaternion { } } -impl ApproxEq for Quaternion { +impl ApproxEq for Quaternion { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Quaternion, epsilon: &S) -> bool { self.s.approx_eq_eps(&other.s, epsilon) && diff --git a/src/rotation.rs b/src/rotation.rs index f7340b19..eb3930e8 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -25,7 +25,7 @@ use vector::{Vector, Vector2, Vector3}; /// 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. -pub trait Rotation>: PartialEq + ApproxEq + Sized { +pub trait Rotation>: PartialEq + ApproxEq + Sized { /// Create the identity transform (causes no transformation). fn one() -> Self; @@ -206,7 +206,9 @@ impl Rotation> for Basis2 { fn invert_self(&mut self) { self.mat.invert_self(); } } -impl ApproxEq for Basis2 { +impl ApproxEq for Basis2 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Basis2, epsilon: &S) -> bool { self.mat.approx_eq_eps(&other.mat, epsilon) @@ -288,7 +290,9 @@ impl Rotation> for Basis3 { fn invert_self(&mut self) { self.mat.invert_self(); } } -impl ApproxEq for Basis3 { +impl ApproxEq for Basis3 { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &Basis3, epsilon: &S) -> bool { self.mat.approx_eq_eps(&other.mat, epsilon) diff --git a/src/vector.rs b/src/vector.rs index 4acbb516..fa13ea59 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -287,7 +287,9 @@ macro_rules! vec { fn neg(self) -> $VectorN { $VectorN::new($(-self.$field),+) } } - impl ApproxEq for $VectorN { + impl ApproxEq for $VectorN { + type Epsilon = S; + #[inline] fn approx_eq_eps(&self, other: &$VectorN, epsilon: &S) -> bool { $(self.$field.approx_eq_eps(&other.$field, epsilon))&&+ @@ -618,7 +620,7 @@ impl Vector4 { /// Specifies geometric operations for vectors. This is only implemented for /// 2-dimensional and 3-dimensional vectors. pub trait EuclideanVector: Vector - + ApproxEq + + ApproxEq + Sized { /// Returns `true` if the vector is perpendicular (at right angles) to the /// other vector. From a434f18ba4ccdeba0e096daf20f8a0ee082739d3 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 14:15:11 +1100 Subject: [PATCH 3/8] Make array type parameters associated types --- src/array.rs | 31 +++++++++++++++++++++---------- src/matrix.rs | 22 ++++++++++++++++++---- src/point.rs | 10 +++++++--- src/quaternion.rs | 4 +++- src/vector.rs | 6 ++++-- 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/array.rs b/src/array.rs index f2e0e59c..0bbfd328 100644 --- a/src/array.rs +++ b/src/array.rs @@ -18,14 +18,19 @@ use std::ptr; use std::ops::*; /// An array containing elements of type `Element` -pub trait Array1: Index + IndexMut { +pub trait Array1 where + Self: Index::Element>, + Self: IndexMut::Element>, +{ + type Element: Copy; + /// Get the pointer to the first element of the array. - fn ptr<'a>(&'a self) -> &'a Element { + fn ptr<'a>(&'a self) -> &'a Self::Element { &self[0] } /// Get a mutable pointer to the first element of the array. - fn mut_ptr<'a>(&'a mut self) -> &'a mut Element { + fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element { &mut self[0] } @@ -38,21 +43,27 @@ pub trait Array1: Index + IndexMut Element { + fn replace_elem(&mut self, i: usize, src: Self::Element) -> Self::Element { mem::replace(&mut self[i], src) } } /// A column-major array -pub trait Array2+'static, Row: Array1, Element: Copy>: - Index + IndexMut { +pub trait Array2 where + Self: Index::Column>, + Self: IndexMut::Column>, +{ + type Element: Copy; + type Column: Array1; + type Row: Array1; + /// Get the pointer to the first element of the array. - fn ptr<'a>(&'a self) -> &'a Element { + fn ptr<'a>(&'a self) -> &'a Self::Element { &self[0][0] } /// Get a mutable pointer to the first element of the array. - fn mut_ptr<'a>(&'a mut self) -> &'a mut Element { + fn mut_ptr<'a>(&'a mut self) -> &'a mut Self::Element { &mut self[0][0] } @@ -64,12 +75,12 @@ pub trait Array2+'static, Row: Array1, Element: /// Replace a column in the array. #[inline] - fn replace_col(&mut self, c: usize, src: Column) -> Column { + fn replace_col(&mut self, c: usize, src: Self::Column) -> Self::Column { mem::replace(&mut self[c], src) } /// Get a row from this array by-value. - fn row(&self, r: usize) -> Row; + fn row(&self, r: usize) -> Self::Row; /// Swap two rows of this array. fn swap_rows(&mut self, a: usize, b: usize); diff --git a/src/matrix.rs b/src/matrix.rs index 3fd337cf..5b05ab8b 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -249,7 +249,9 @@ impl> Matrix4 { } } -pub trait Matrix + 'static>: Array2 + ApproxEq + Sized // where +pub trait Matrix> where + Self: Array2, + Self: ApproxEq + Sized, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -359,7 +361,11 @@ pub trait Matrix + 'static>: Array2 + Approx fn is_symmetric(&self) -> bool; } -impl Array2, Vector2, S> for Matrix2 { +impl Array2 for Matrix2 { + type Element = S; + type Column = Vector2; + type Row = Vector2; + #[inline] fn row(&self, r: usize) -> Vector2 { Vector2::new(self[0][r], @@ -373,7 +379,11 @@ impl Array2, Vector2, S> for Matrix2 { } } -impl Array2, Vector3, S> for Matrix3 { +impl Array2 for Matrix3 { + type Element = S; + type Column = Vector3; + type Row = Vector3; + #[inline] fn row(&self, r: usize) -> Vector3 { Vector3::new(self[0][r], @@ -389,7 +399,11 @@ impl Array2, Vector3, S> for Matrix3 { } } -impl Array2, Vector4, S> for Matrix4 { +impl Array2 for Matrix4 { + type Element = S; + type Column = Vector4; + type Row = Vector4; + #[inline] fn row(&self, r: usize) -> Vector4 { Vector4::new(self[0][r], diff --git a/src/point.rs b/src/point.rs index 1f917f14..809c94d7 100644 --- a/src/point.rs +++ b/src/point.rs @@ -66,7 +66,7 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point: Array1 + Clone // where +pub trait Point: Array1 + Clone // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, @@ -123,7 +123,9 @@ pub trait Point: Array1 + Clone // where fn max(&self, p: &Self) -> Self; } -impl Array1 for Point2 {} +impl Array1 for Point2 { + type Element = S; +} impl Point for Point2 { type Vector = Vector2; @@ -200,7 +202,9 @@ impl ApproxEq for Point2 { } } -impl Array1 for Point3 {} +impl Array1 for Point3 { + type Element = S; +} impl Point for Point3 { type Vector = Vector3; diff --git a/src/quaternion.rs b/src/quaternion.rs index 51802e87..6c9635a8 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -40,7 +40,9 @@ pub struct Quaternion { pub v: Vector3, } -impl Array1 for Quaternion {} +impl Array1 for Quaternion { + type Element = S; +} impl Quaternion { /// Construct a new quaternion from one scalar component and three diff --git a/src/vector.rs b/src/vector.rs index fa13ea59..77e63f13 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -111,7 +111,7 @@ use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. -pub trait Vector: Array1 + Clone // where +pub trait Vector: Array1 + Clone // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -245,7 +245,9 @@ macro_rules! vec { } } - impl<$S: Copy> Array1<$S> for $VectorN<$S> {} + impl Array1 for $VectorN { + type Element = S; + } impl Vector for $VectorN { #[inline] fn from_value(s: S) -> $VectorN { $VectorN { $($field: s),+ } } From 25aea84e0d9b970245aca4ff2c2c2ffaa465e55b Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 14:30:59 +1100 Subject: [PATCH 4/8] Make scalar an an associated type on Vector --- src/matrix.rs | 2 +- src/point.rs | 2 +- src/vector.rs | 73 +++++++++++++++++++++++++++------------------------ 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/matrix.rs b/src/matrix.rs index 5b05ab8b..21f448a7 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -249,7 +249,7 @@ impl> Matrix4 { } } -pub trait Matrix> where +pub trait Matrix> where Self: Array2, Self: ApproxEq + Sized, // FIXME: blocked by rust-lang/rust#20671 diff --git a/src/point.rs b/src/point.rs index 809c94d7..11756ce5 100644 --- a/src/point.rs +++ b/src/point.rs @@ -77,7 +77,7 @@ pub trait Point: Array1 + Clone // where // for<'a> &'a Self: Rem, { /// The associated displacement vector. - type Vector: Vector; + type Vector: Vector; /// Create a point at the origin. fn origin() -> Self; diff --git a/src/vector.rs b/src/vector.rs index 77e63f13..fdd08be3 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -111,7 +111,7 @@ use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. -pub trait Vector: Array1 + Clone // where +pub trait Vector: Array1::Scalar> + Clone // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -127,31 +127,34 @@ pub trait Vector: Array1 + Clone // where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { + // The associated scalar + type Scalar: BaseNum; + /// Construct a vector from a single value, replicating it. - fn from_value(s: S) -> Self; + fn from_value(scalar: Self::Scalar) -> Self; /// The zero vector (with all components set to zero) #[inline] - fn zero() -> Self { Self::from_value(S::zero()) } + fn zero() -> Self { Self::from_value(Self::Scalar::zero()) } /// The identity vector (with all components set to one) #[inline] - fn one() -> Self { Self::from_value(S::one()) } + fn one() -> Self { Self::from_value(Self::Scalar::one()) } /// Add a scalar to this vector, returning a new vector. #[must_use] - fn add_s(&self, s: S) -> Self; + fn add_s(&self, scalar: Self::Scalar) -> Self; /// Subtract a scalar from this vector, returning a new vector. #[must_use] - fn sub_s(&self, s: S) -> Self; + fn sub_s(&self, scalar: Self::Scalar) -> Self; /// Multiply this vector by a scalar, returning a new vector. #[must_use] - fn mul_s(&self, s: S) -> Self; + fn mul_s(&self, scalar: Self::Scalar) -> Self; /// Divide this vector by a scalar, returning a new vector. #[must_use] - fn div_s(&self, s: S) -> Self; + fn div_s(&self, scalar: Self::Scalar) -> Self; /// Take the remainder of this vector by a scalar, returning a new vector. #[must_use] - fn rem_s(&self, s: S) -> Self; + fn rem_s(&self, scalar: Self::Scalar) -> Self; /// Add this vector to another, returning a new vector. #[must_use] @@ -170,15 +173,15 @@ pub trait Vector: Array1 + Clone // where fn rem_v(&self, v: &Self) -> Self; /// Add a scalar to this vector in-place. - fn add_self_s(&mut self, s: S); + fn add_self_s(&mut self, scalar: Self::Scalar); /// Subtract a scalar from this vector, in-place. - fn sub_self_s(&mut self, s: S); + fn sub_self_s(&mut self, scalar: Self::Scalar); /// Multiply this vector by a scalar, in-place. - fn mul_self_s(&mut self, s: S); + fn mul_self_s(&mut self, scalar: Self::Scalar); /// Divide this vector by a scalar, in-place. - fn div_self_s(&mut self, s: S); + fn div_self_s(&mut self, scalar: Self::Scalar); /// Take the remainder of this vector by a scalar, in-place. - fn rem_self_s(&mut self, s: S); + fn rem_self_s(&mut self, scalar: Self::Scalar); /// Add another vector to this one, in-place. fn add_self_v(&mut self, v: &Self); @@ -192,22 +195,22 @@ pub trait Vector: Array1 + Clone // where fn rem_self_v(&mut self, v: &Self); /// The sum of the components of the vector. - fn sum(&self) -> S; + fn sum(&self) -> Self::Scalar; /// The product of the components of the vector. - fn product(&self) -> S; + fn product(&self) -> Self::Scalar; /// Vector dot product. #[inline] - fn dot(&self, v: &Self) -> S { self.mul_v(v).sum() } + fn dot(&self, v: &Self) -> Self::Scalar { self.mul_v(v).sum() } /// The minimum component of the vector. - fn comp_min(&self) -> S; + fn comp_min(&self) -> Self::Scalar; /// The maximum component of the vector. - fn comp_max(&self) -> S; + fn comp_max(&self) -> Self::Scalar; } /// Dot product of two vectors. -#[inline] pub fn dot>(a: V, b: V) -> S { a.dot(&b) } +#[inline] pub fn dot(a: V, b: V) -> V::Scalar { a.dot(&b) } // Utility macro for generating associated functions for the vectors macro_rules! vec { @@ -249,14 +252,16 @@ macro_rules! vec { type Element = S; } - impl Vector for $VectorN { - #[inline] fn from_value(s: S) -> $VectorN { $VectorN { $($field: s),+ } } + impl Vector for $VectorN { + type Scalar = S; + + #[inline] fn from_value(scalar: S) -> $VectorN { $VectorN { $($field: scalar),+ } } - #[inline] fn add_s(&self, s: S) -> $VectorN { self + s } - #[inline] fn sub_s(&self, s: S) -> $VectorN { self - s } - #[inline] fn mul_s(&self, s: S) -> $VectorN { self * s } - #[inline] fn div_s(&self, s: S) -> $VectorN { self / s } - #[inline] fn rem_s(&self, s: S) -> $VectorN { self % s } + #[inline] fn add_s(&self, scalar: S) -> $VectorN { self + scalar } + #[inline] fn sub_s(&self, scalar: S) -> $VectorN { self - scalar } + #[inline] fn mul_s(&self, scalar: S) -> $VectorN { self * scalar } + #[inline] fn div_s(&self, scalar: S) -> $VectorN { self / scalar } + #[inline] fn rem_s(&self, scalar: S) -> $VectorN { self % scalar } #[inline] fn add_v(&self, v: &$VectorN) -> $VectorN { self + v } #[inline] fn sub_v(&self, v: &$VectorN) -> $VectorN { self - v } @@ -264,11 +269,11 @@ macro_rules! vec { #[inline] fn div_v(&self, v: &$VectorN) -> $VectorN { self / v } #[inline] fn rem_v(&self, v: &$VectorN) -> $VectorN { self % v } - #[inline] fn add_self_s(&mut self, s: S) { *self = &*self + s; } - #[inline] fn sub_self_s(&mut self, s: S) { *self = &*self - s; } - #[inline] fn mul_self_s(&mut self, s: S) { *self = &*self * s; } - #[inline] fn div_self_s(&mut self, s: S) { *self = &*self / s; } - #[inline] fn rem_self_s(&mut self, s: S) { *self = &*self % s; } + #[inline] fn add_self_s(&mut self, scalar: S) { *self = &*self + scalar; } + #[inline] fn sub_self_s(&mut self, scalar: S) { *self = &*self - scalar; } + #[inline] fn mul_self_s(&mut self, scalar: S) { *self = &*self * scalar; } + #[inline] fn div_self_s(&mut self, scalar: S) { *self = &*self / scalar; } + #[inline] fn rem_self_s(&mut self, scalar: S) { *self = &*self % scalar; } #[inline] fn add_self_v(&mut self, v: &$VectorN) { *self = &*self + v; } #[inline] fn sub_self_v(&mut self, v: &$VectorN) { *self = &*self - v; } @@ -621,9 +626,7 @@ impl Vector4 { /// Specifies geometric operations for vectors. This is only implemented for /// 2-dimensional and 3-dimensional vectors. -pub trait EuclideanVector: Vector - + ApproxEq - + Sized { +pub trait EuclideanVector: Vector + ApproxEq::Scalar> + Sized { /// Returns `true` if the vector is perpendicular (at right angles) to the /// other vector. fn is_perpendicular(&self, other: &Self) -> bool { From 669e43ab59d28b6a3bc997195c88feb4aae1f47f Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 15:23:22 +1100 Subject: [PATCH 5/8] Make scalar type parametrs out of transform and rotation traits --- src/point.rs | 88 +++++++++++++++++++++++----------------------- src/quaternion.rs | 2 +- src/rotation.rs | 12 ++++--- src/transform.rs | 88 +++++++++++++++++++++++----------------------- src/vector.rs | 35 +++++++++--------- tests/transform.rs | 2 +- 6 files changed, 116 insertions(+), 111 deletions(-) diff --git a/src/point.rs b/src/point.rs index 11756ce5..a40d9678 100644 --- a/src/point.rs +++ b/src/point.rs @@ -66,7 +66,7 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point: Array1 + Clone // where +pub trait Point: Array1::Vector as Vector>::Scalar> + Clone // where // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, @@ -77,7 +77,7 @@ pub trait Point: Array1 + Clone // where // for<'a> &'a Self: Rem, { /// The associated displacement vector. - type Vector: Vector; + type Vector: Vector; /// Create a point at the origin. fn origin() -> Self; @@ -89,13 +89,13 @@ pub trait Point: Array1 + Clone // where /// Multiply each component by a scalar, returning the new point. #[must_use] - fn mul_s(&self, s: S) -> Self; + fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; /// Divide each component by a scalar, returning the new point. #[must_use] - fn div_s(&self, s: S) -> Self; + fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; /// Subtract a scalar from each component, returning the new point. #[must_use] - fn rem_s(&self, s: S) -> Self; + fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; /// Add a vector to this point, returning the new point. #[must_use] @@ -104,17 +104,17 @@ pub trait Point: Array1 + Clone // where fn sub_p(&self, p: &Self) -> Self::Vector; /// Multiply each component by a scalar, in-place. - fn mul_self_s(&mut self, s: S); + fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); /// Divide each component by a scalar, in-place. - fn div_self_s(&mut self, s: S); + fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); /// Take the remainder of each component by a scalar, in-place. - fn rem_self_s(&mut self, s: S); + fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); /// Add a vector to this point, in-place. fn add_self_v(&mut self, v: &Self::Vector); /// This is a weird one, but its useful for plane calculations. - fn dot(&self, v: &Self::Vector) -> S; + fn dot(&self, v: &Self::Vector) -> <::Vector as Vector>::Scalar; #[must_use] fn min(&self, p: &Self) -> Self; @@ -127,7 +127,7 @@ impl Array1 for Point2 { type Element = S; } -impl Point for Point2 { +impl Point for Point2 { type Vector = Vector2; #[inline] @@ -145,28 +145,28 @@ impl Point for Point2 { Vector2::new(self.x, self.y) } - #[inline] fn mul_s(&self, s: S) -> Point2 { self * s } - #[inline] fn div_s(&self, s: S) -> Point2 { self / s } - #[inline] fn rem_s(&self, s: S) -> Point2 { self % s } + #[inline] fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self * scalar } + #[inline] fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self / scalar } + #[inline] fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self % scalar } #[inline] fn add_v(&self, v: &Vector2) -> Point2 { self + v } #[inline] fn sub_p(&self, p: &Point2) -> Vector2 { self - p } #[inline] - fn mul_self_s(&mut self, s: S) { - self.x = self.x * s; - self.y = self.y * s; + fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x * scalar; + self.y = self.y * scalar; } #[inline] - fn div_self_s(&mut self, s: S) { - self.x = self.x / s; - self.y = self.y / s; + fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x / scalar; + self.y = self.y / scalar; } #[inline] - fn rem_self_s(&mut self, s: S) { - self.x = self.x % s; - self.y = self.y % s; + fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x % scalar; + self.y = self.y % scalar; } #[inline] @@ -206,7 +206,7 @@ impl Array1 for Point3 { type Element = S; } -impl Point for Point3 { +impl Point for Point3 { type Vector = Vector3; #[inline] @@ -224,31 +224,31 @@ impl Point for Point3 { Vector3::new(self.x, self.y, self.z) } - #[inline] fn mul_s(&self, s: S) -> Point3 { self * s } - #[inline] fn div_s(&self, s: S) -> Point3 { self / s } - #[inline] fn rem_s(&self, s: S) -> Point3 { self % s } + #[inline] fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self * scalar } + #[inline] fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self / scalar } + #[inline] fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self % scalar } #[inline] fn add_v(&self, v: &Vector3) -> Point3 { self + v } #[inline] fn sub_p(&self, p: &Point3) -> Vector3 { self - p } #[inline] - fn mul_self_s(&mut self, s: S) { - self.x = self.x * s; - self.y = self.y * s; - self.z = self.z * s; + fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x * scalar; + self.y = self.y * scalar; + self.z = self.z * scalar; } #[inline] - fn div_self_s(&mut self, s: S) { - self.x = self.x / s; - self.y = self.y / s; - self.z = self.z / s; + fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x / scalar; + self.y = self.y / scalar; + self.z = self.z / scalar; } #[inline] - fn rem_self_s(&mut self, s: S) { - self.x = self.x % s; - self.y = self.y % s; - self.z = self.z % s; + fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + self.x = self.x % scalar; + self.y = self.y % scalar; + self.z = self.z % scalar; } #[inline] @@ -294,8 +294,8 @@ macro_rules! impl_operators { type Output = $PointN; #[inline] - fn mul(self, s: S) -> $PointN { - $PointN::new($(self.$field * s),+) + fn mul(self, scalar: S) -> $PointN { + $PointN::new($(self.$field * scalar),+) } } @@ -303,8 +303,8 @@ macro_rules! impl_operators { type Output = $PointN; #[inline] - fn div(self, s: S) -> $PointN { - $PointN::new($(self.$field / s),+) + fn div(self, scalar: S) -> $PointN { + $PointN::new($(self.$field / scalar),+) } } @@ -312,8 +312,8 @@ macro_rules! impl_operators { type Output = $PointN; #[inline] - fn rem(self, s: S) -> $PointN { - $PointN::new($(self.$field % s),+) + fn rem(self, scalar: S) -> $PointN { + $PointN::new($(self.$field % scalar),+) } } diff --git a/src/quaternion.rs b/src/quaternion.rs index 6c9635a8..b40799f7 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -343,7 +343,7 @@ impl From> for Basis3 { fn from(quat: Quaternion) -> Basis3 { Basis3::from_quaternion(&quat) } } -impl Rotation> for Quaternion { +impl Rotation> for Quaternion { #[inline] fn one() -> Quaternion { Quaternion::one() } diff --git a/src/rotation.rs b/src/rotation.rs index eb3930e8..b2c7c42e 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -25,7 +25,9 @@ use vector::{Vector, Vector2, Vector3}; /// 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. -pub trait Rotation>: PartialEq + ApproxEq + Sized { +pub trait Rotation: PartialEq + ApproxEq::Vector as Vector>::Scalar> + Sized where + <

::Vector as Vector>::Scalar: BaseFloat, +{ /// Create the identity transform (causes no transformation). fn one() -> Self; @@ -67,7 +69,7 @@ pub trait Rotation>: PartialEq + ApproxEq } /// A two-dimensional rotation. -pub trait Rotation2: Rotation> +pub trait Rotation2: Rotation> + Into> + Into> { /// Create a rotation by a given angle. Thus is a redundant case of both @@ -76,7 +78,7 @@ pub trait Rotation2: Rotation> } /// A three-dimensional rotation. -pub trait Rotation3: Rotation> +pub trait Rotation3: Rotation> + Into> + Into> + Into> { @@ -172,7 +174,7 @@ impl From> for Matrix2 { fn from(b: Basis2) -> Matrix2 { b.mat } } -impl Rotation> for Basis2 { +impl Rotation> for Basis2 { #[inline] fn one() -> Basis2 { Basis2 { mat: Matrix2::one() } } @@ -255,7 +257,7 @@ impl From> for Quaternion { fn from(b: Basis3) -> Quaternion { b.mat.into() } } -impl Rotation> for Basis3 { +impl Rotation> for Basis3 { #[inline] fn one() -> Basis3 { Basis3 { mat: Matrix3::one() } } diff --git a/src/transform.rs b/src/transform.rs index 900df117..d732b24e 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -27,7 +27,7 @@ use vector::*; /// A trait representing an [affine /// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that /// can be applied to points or vectors. An affine transformation is one which -pub trait Transform>: Sized { +pub trait Transform: Sized { /// Create an identity transformation. That is, a transformation which /// does nothing. fn one() -> Self; @@ -72,28 +72,30 @@ pub trait Transform>: Sized { /// A generic transformation consisting of a rotation, /// displacement vector and scale amount. #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub struct Decomposed { - pub scale: S, +pub struct Decomposed { + pub scale: V::Scalar, pub rot: R, pub disp: V, } -impl, R: Rotation> Transform for Decomposed { +impl> Transform

for Decomposed where + <

::Vector as Vector>::Scalar: BaseFloat, +{ #[inline] - fn one() -> Decomposed { + fn one() -> Decomposed { Decomposed { - scale: S::one(), + scale: <

::Vector as Vector>::Scalar::one(), rot: R::one(), disp: P::Vector::zero(), } } #[inline] - fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed { + fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed { let rot = R::look_at(¢er.sub_p(eye), up); let disp = rot.rotate_vector(&P::origin().sub_p(eye)); Decomposed { - scale: S::one(), + scale: <

::Vector as Vector>::Scalar::one(), rot: rot, disp: disp, } @@ -109,7 +111,7 @@ impl, R: Rotation> Transform for Decompose self.rot.rotate_point(&point.mul_s(self.scale.clone())).add_v(&self.disp) } - fn concat(&self, other: &Decomposed) -> Decomposed { + fn concat(&self, other: &Decomposed) -> Decomposed { Decomposed { scale: self.scale * other.scale, rot: self.rot.concat(&other.rot), @@ -117,11 +119,11 @@ impl, R: Rotation> Transform for Decompose } } - fn invert(&self) -> Option> { - if self.scale.approx_eq(&S::zero()) { + fn invert(&self) -> Option> { + if self.scale.approx_eq(&<

::Vector as Vector>::Scalar::zero()) { None } else { - let s = S::one() / self.scale; + let s = <

::Vector as Vector>::Scalar::one() / self.scale; let r = self.rot.invert(); let d = r.rotate_vector(&self.disp).mul_s(-s); Some(Decomposed { @@ -133,11 +135,11 @@ impl, R: Rotation> Transform for Decompose } } -pub trait Transform2: Transform> + Into> {} -pub trait Transform3: Transform> + Into> {} +pub trait Transform2: Transform> + Into> {} +pub trait Transform3: Transform> + Into> {} -impl> From, R>> for Matrix3 { - fn from(dec: Decomposed, R>) -> Matrix3 { +impl> From, R>> for Matrix3 { + fn from(dec: Decomposed, R>) -> Matrix3 { let m: Matrix2<_> = dec.rot.into(); let mut m: Matrix3<_> = m.mul_s(dec.scale).into(); m.z = dec.disp.extend(S::one()); @@ -145,8 +147,8 @@ impl> From, R>> for Matri } } -impl> From, R>> for Matrix4 { - fn from(dec: Decomposed, R>) -> Matrix4 { +impl> From, R>> for Matrix4 { + fn from(dec: Decomposed, R>) -> Matrix4 { let m: Matrix3<_> = dec.rot.into(); let mut m: Matrix4<_> = m.mul_s(dec.scale).into(); m.w = dec.disp.extend(S::one()); @@ -154,11 +156,11 @@ impl> From, R>> for Matri } } -impl> Transform2 for Decomposed, R> {} +impl> Transform2 for Decomposed, R> {} -impl> Transform3 for Decomposed, R> {} +impl> Transform3 for Decomposed, R> {} -impl> fmt::Debug for Decomposed, R> { +impl> fmt::Debug for Decomposed, R> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(scale({:?}), rot({:?}), disp{:?})", self.scale, self.rot, self.disp) @@ -171,7 +173,7 @@ pub struct AffineMatrix3 { pub mat: Matrix4, } -impl Transform> for AffineMatrix3 { +impl Transform> for AffineMatrix3 { #[inline] fn one() -> AffineMatrix3 { AffineMatrix3 { mat: Matrix4::one() } @@ -211,35 +213,33 @@ impl Transform3 for AffineMatrix3 {} /// A trait that allows extracting components (rotation, translation, scale) /// from an arbitrary transformations -pub trait ToComponents, R: Rotation> { +pub trait ToComponents> where + <

::Vector as Vector>::Scalar: BaseFloat, +{ /// Extract the (scale, rotation, translation) triple fn decompose(&self) -> (P::Vector, R, P::Vector); } -pub trait ToComponents2>: - ToComponents, R> {} -pub trait ToComponents3>: - ToComponents, R> {} - -pub trait CompositeTransform, R: Rotation>: - Transform + ToComponents {} -pub trait CompositeTransform2>: - Transform2 + ToComponents2 {} -pub trait CompositeTransform3>: - Transform3 + ToComponents3 {} - -impl< - S: BaseFloat, - P: Point, - R: Rotation + Clone, -> ToComponents for Decomposed { +pub trait ToComponents2>: ToComponents, R> {} +pub trait ToComponents3>: ToComponents, R> {} + +pub trait CompositeTransform>: Transform

+ ToComponents where + <

::Vector as Vector>::Scalar: BaseFloat, +{} + +pub trait CompositeTransform2>: Transform2 + ToComponents2 {} +pub trait CompositeTransform3>: Transform3 + ToComponents3 {} + +impl + Clone> ToComponents for Decomposed where + <

::Vector as Vector>::Scalar: BaseFloat, +{ fn decompose(&self) -> (P::Vector, R, P::Vector) { (P::Vector::one().mul_s(self.scale), self.rot.clone(), self.disp.clone()) } } -impl + Clone> ToComponents2 for Decomposed, R> {} -impl + Clone> ToComponents3 for Decomposed, R> {} +impl + Clone> ToComponents2 for Decomposed, R> {} +impl + Clone> ToComponents3 for Decomposed, R> {} -impl + Clone> CompositeTransform2 for Decomposed, R> {} -impl + Clone> CompositeTransform3 for Decomposed, R> {} +impl + Clone> CompositeTransform2 for Decomposed, R> {} +impl + Clone> CompositeTransform3 for Decomposed, R> {} diff --git a/src/vector.rs b/src/vector.rs index fdd08be3..73a092b8 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -127,7 +127,7 @@ pub trait Vector: Array1::Scalar> + Clone // where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { - // The associated scalar + /// The associated scalar. type Scalar: BaseNum; /// Construct a vector from a single value, replicating it. @@ -626,42 +626,45 @@ impl Vector4 { /// Specifies geometric operations for vectors. This is only implemented for /// 2-dimensional and 3-dimensional vectors. -pub trait EuclideanVector: Vector + ApproxEq::Scalar> + Sized { +pub trait EuclideanVector: Vector + Sized where + ::Scalar: BaseFloat, + Self: ApproxEq::Scalar>, +{ /// Returns `true` if the vector is perpendicular (at right angles) to the /// other vector. fn is_perpendicular(&self, other: &Self) -> bool { - self.dot(other).approx_eq(&S::zero()) + self.dot(other).approx_eq(&Self::Scalar::zero()) } /// Returns the squared length of the vector. This does not perform an /// expensive square root operation like in the `length` method and can /// therefore be more efficient for comparing the lengths of two vectors. #[inline] - fn length2(&self) -> S { + fn length2(&self) -> Self::Scalar { self.dot(self) } /// The norm of the vector. #[inline] - fn length(&self) -> S { - self.dot(self).sqrt() + fn length(&self) -> Self::Scalar { + <::Scalar as ::rust_num::Float>::sqrt(self.dot(self)) } /// The angle between the vector and `other`, in radians. - fn angle(&self, other: &Self) -> Rad; + fn angle(&self, other: &Self) -> Rad; /// Returns a vector with the same direction, but with a `length` (or /// `norm`) of `1`. #[inline] #[must_use] fn normalize(&self) -> Self { - self.normalize_to(S::one()) + self.normalize_to(Self::Scalar::one()) } /// Returns a vector with the same direction and a given `length`. #[inline] #[must_use] - fn normalize_to(&self, length: S) -> Self { + fn normalize_to(&self, length: Self::Scalar) -> Self { self.mul_s(length / self.length()) } @@ -669,47 +672,47 @@ pub trait EuclideanVector: Vector + ApproxEq Self { + fn lerp(&self, other: &Self, amount: Self::Scalar) -> Self { self.add_v(&other.sub_v(self).mul_s(amount)) } /// Normalises the vector to a length of `1`. #[inline] fn normalize_self(&mut self) { - let rlen = self.length().recip(); + let rlen = <::Scalar as ::rust_num::Float>::recip(self.length()); self.mul_self_s(rlen); } /// Normalizes the vector to `length`. #[inline] - fn normalize_self_to(&mut self, length: S) { + fn normalize_self_to(&mut self, length: Self::Scalar) { let n = length / self.length(); self.mul_self_s(n); } /// Linearly interpolates the length of the vector towards the length of /// `other` by the specified amount. - fn lerp_self(&mut self, other: &Self, amount: S) { + fn lerp_self(&mut self, other: &Self, amount: Self::Scalar) { let v = other.sub_v(self).mul_s(amount); self.add_self_v(&v); } } -impl EuclideanVector for Vector2 { +impl EuclideanVector for Vector2 { #[inline] fn angle(&self, other: &Vector2) -> Rad { atan2(self.perp_dot(other), self.dot(other)) } } -impl EuclideanVector for Vector3 { +impl EuclideanVector for Vector3 { #[inline] fn angle(&self, other: &Vector3) -> Rad { atan2(self.cross(other).length(), self.dot(other)) } } -impl EuclideanVector for Vector4 { +impl EuclideanVector for Vector4 { #[inline] fn angle(&self, other: &Vector4) -> Rad { acos(self.dot(other) / (self.length() * other.length())) diff --git a/tests/transform.rs b/tests/transform.rs index e6654d8e..51e27f0f 100644 --- a/tests/transform.rs +++ b/tests/transform.rs @@ -36,7 +36,7 @@ fn test_look_at() { let eye = Point3::new(0.0f64, 0.0, -5.0); let center = Point3::new(0.0f64, 0.0, 0.0); let up = Vector3::new(1.0f64, 0.0, 0.0); - let t: Decomposed,Quaternion> = Transform::look_at(&eye, ¢er, &up); + let t: Decomposed, Quaternion> = Transform::look_at(&eye, ¢er, &up); let point = Point3::new(1.0f64, 0.0, 0.0); let view_point = Point3::new(0.0f64, 1.0, 5.0); assert!( t.transform_point(&point).approx_eq(&view_point) ); From cda76e3bbbb9fb847b7b56e090c0e421de29ff3a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 15:32:17 +1100 Subject: [PATCH 6/8] Remove type parameters from Matrix trait --- src/matrix.rs | 61 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/matrix.rs b/src/matrix.rs index 21f448a7..3dbbc38b 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -249,9 +249,14 @@ impl> Matrix4 { } } -pub trait Matrix> where - Self: Array2, - Self: ApproxEq + Sized, +pub trait Matrix where + Self: Array2< + Element = <::ColumnRow as Vector>::Scalar, + Column = ::ColumnRow, + Row = ::ColumnRow, + >, + Self: ApproxEq::ColumnRow as Vector>::Scalar> + Sized, + Self::Element: BaseFloat, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -263,28 +268,30 @@ pub trait Matrix> where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { + type ColumnRow: Vector; + /// Create a new diagonal matrix using the supplied value. - fn from_value(value: S) -> Self; + fn from_value(value: Self::Element) -> Self; /// Create a matrix from a non-uniform scale - fn from_diagonal(value: &V) -> Self; + fn from_diagonal(diagonal: &Self::Column) -> Self; /// Create a matrix with all elements equal to zero. #[inline] - fn zero() -> Self { Self::from_value(S::zero()) } + fn zero() -> Self { Self::from_value(Self::Element::zero()) } /// Create a matrix where the each element of the diagonal is equal to one. #[inline] - fn one() -> Self { Self::from_value(S::one()) } + fn one() -> Self { Self::from_value(Self::Element::one()) } /// Multiply this matrix by a scalar, returning the new matrix. #[must_use] - fn mul_s(&self, s: S) -> Self; + fn mul_s(&self, s: Self::Element) -> Self; /// Divide this matrix by a scalar, returning the new matrix. #[must_use] - fn div_s(&self, s: S) -> Self; + fn div_s(&self, s: Self::Element) -> Self; /// Take the remainder of this matrix by a scalar, returning the new /// matrix. #[must_use] - fn rem_s(&self, s: S) -> Self; + fn rem_s(&self, s: Self::Element) -> Self; /// Add this matrix with another matrix, returning the new metrix. #[must_use] @@ -294,18 +301,18 @@ pub trait Matrix> where fn sub_m(&self, m: &Self) -> Self; /// Multiplay a vector by this matrix, returning a new vector. - fn mul_v(&self, v: &V) -> V; + fn mul_v(&self, v: &Self::Column) -> Self::Column; /// Multiply this matrix by another matrix, returning the new matrix. #[must_use] fn mul_m(&self, m: &Self) -> Self; /// Multiply this matrix by a scalar, in-place. - fn mul_self_s(&mut self, s: S); + fn mul_self_s(&mut self, s: Self::Element); /// Divide this matrix by a scalar, in-place. - fn div_self_s(&mut self, s: S); + fn div_self_s(&mut self, s: Self::Element); /// Take the remainder of this matrix, in-place. - fn rem_self_s(&mut self, s: S); + fn rem_self_s(&mut self, s: Self::Element); /// Add this matrix with another matrix, in-place. fn add_self_m(&mut self, m: &Self); @@ -322,14 +329,14 @@ pub trait Matrix> where /// Transpose this matrix in-place. fn transpose_self(&mut self); /// Take the determinant of this matrix. - fn determinant(&self) -> S; + fn determinant(&self) -> Self::Element; /// Return a vector containing the diagonal of this matrix. - fn diagonal(&self) -> V; + fn diagonal(&self) -> Self::Column; /// Return the trace of this matrix. That is, the sum of the diagonal. #[inline] - fn trace(&self) -> S { self.diagonal().sum() } + fn trace(&self) -> Self::Element { self.diagonal().sum() } /// Invert this matrix, returning a new matrix. `m.mul_m(m.invert())` is /// the identity matrix. Returns `None` if this matrix is not invertible @@ -345,7 +352,7 @@ pub trait Matrix> where /// Test if this matrix is invertible. #[inline] - fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&S::zero()) } + fn is_invertible(&self) -> bool { !self.determinant().approx_eq(&Self::Element::zero()) } /// Test if this matrix is the identity matrix. That is, it is diagonal /// and every element in the diagonal is one. @@ -361,7 +368,7 @@ pub trait Matrix> where fn is_symmetric(&self) -> bool; } -impl Array2 for Matrix2 { +impl Array2 for Matrix2 { type Element = S; type Column = Vector2; type Row = Vector2; @@ -379,7 +386,7 @@ impl Array2 for Matrix2 { } } -impl Array2 for Matrix3 { +impl Array2 for Matrix3 { type Element = S; type Column = Vector3; type Row = Vector3; @@ -399,7 +406,7 @@ impl Array2 for Matrix3 { } } -impl Array2 for Matrix4 { +impl Array2 for Matrix4 { type Element = S; type Column = Vector4; type Row = Vector4; @@ -421,7 +428,9 @@ impl Array2 for Matrix4 { } } -impl Matrix> for Matrix2 { +impl Matrix for Matrix2 { + type ColumnRow = Vector2; + #[inline] fn from_value(value: S) -> Matrix2 { Matrix2::new(value, S::zero(), @@ -518,7 +527,9 @@ impl Matrix> for Matrix2 { } } -impl Matrix> for Matrix3 { +impl Matrix for Matrix3 { + type ColumnRow = Vector3; + #[inline] fn from_value(value: S) -> Matrix3 { Matrix3::new(value, S::zero(), S::zero(), @@ -634,7 +645,9 @@ impl Matrix> for Matrix3 { } } -impl Matrix> for Matrix4 { +impl Matrix for Matrix4 { + type ColumnRow = Vector4; + #[inline] fn from_value(value: S) -> Matrix4 { Matrix4::new(value, S::zero(), S::zero(), S::zero(), From 89e656b1f6cd9ad1eb283a2cb6273fc71e29c53b Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 15:40:52 +1100 Subject: [PATCH 7/8] Add comments noting rust bugs --- src/array.rs | 2 ++ src/matrix.rs | 2 ++ src/point.rs | 4 +++- src/rotation.rs | 4 +++- src/transform.rs | 3 +++ src/vector.rs | 7 ++++++- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/array.rs b/src/array.rs index 0bbfd328..ba8fb55a 100644 --- a/src/array.rs +++ b/src/array.rs @@ -19,6 +19,7 @@ use std::ops::*; /// An array containing elements of type `Element` pub trait Array1 where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 Self: Index::Element>, Self: IndexMut::Element>, { @@ -50,6 +51,7 @@ pub trait Array1 where /// A column-major array pub trait Array2 where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 Self: Index::Column>, Self: IndexMut::Column>, { diff --git a/src/matrix.rs b/src/matrix.rs index 3dbbc38b..bc34d41a 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -250,6 +250,7 @@ impl> Matrix4 { } pub trait Matrix where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 Self: Array2< Element = <::ColumnRow as Vector>::Scalar, Column = ::ColumnRow, @@ -268,6 +269,7 @@ pub trait Matrix where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { + // FIXME: Will not be needed once equality constraints in where clauses is implemented type ColumnRow: Vector; /// Create a new diagonal matrix using the supplied value. diff --git a/src/point.rs b/src/point.rs index a40d9678..2b21109f 100644 --- a/src/point.rs +++ b/src/point.rs @@ -66,7 +66,9 @@ impl Point3 { } /// Specifies the numeric operations for point types. -pub trait Point: Array1::Vector as Vector>::Scalar> + Clone // where +pub trait Point: Clone where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 + Self: Array1::Vector as Vector>::Scalar>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, diff --git a/src/rotation.rs b/src/rotation.rs index b2c7c42e..7e1fed6d 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -25,7 +25,9 @@ use vector::{Vector, Vector2, Vector3}; /// 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. -pub trait Rotation: PartialEq + ApproxEq::Vector as Vector>::Scalar> + Sized where +pub trait Rotation: PartialEq + Sized where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 + Self: ApproxEq::Vector as Vector>::Scalar>, <

::Vector as Vector>::Scalar: BaseFloat, { /// Create the identity transform (causes no transformation). diff --git a/src/transform.rs b/src/transform.rs index d732b24e..5a0e2fb1 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -79,6 +79,7 @@ pub struct Decomposed { } impl> Transform

for Decomposed where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 <

::Vector as Vector>::Scalar: BaseFloat, { #[inline] @@ -224,6 +225,7 @@ pub trait ToComponents2>: ToComponents, pub trait ToComponents3>: ToComponents, R> {} pub trait CompositeTransform>: Transform

+ ToComponents where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 <

::Vector as Vector>::Scalar: BaseFloat, {} @@ -231,6 +233,7 @@ pub trait CompositeTransform2>: Transform2 + To pub trait CompositeTransform3>: Transform3 + ToComponents3 {} impl + Clone> ToComponents for Decomposed where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 <

::Vector as Vector>::Scalar: BaseFloat, { fn decompose(&self) -> (P::Vector, R, P::Vector) { diff --git a/src/vector.rs b/src/vector.rs index 73a092b8..2b11b163 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -111,7 +111,9 @@ use num::{BaseNum, BaseFloat}; /// A trait that specifies a range of numeric operations for vectors. Not all /// of these make sense from a linear algebra point of view, but are included /// for pragmatic reasons. -pub trait Vector: Array1::Scalar> + Clone // where +pub trait Vector: Clone where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 + Self: Array1::Scalar>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>, @@ -627,6 +629,7 @@ impl Vector4 { /// Specifies geometric operations for vectors. This is only implemented for /// 2-dimensional and 3-dimensional vectors. pub trait EuclideanVector: Vector + Sized where + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 ::Scalar: BaseFloat, Self: ApproxEq::Scalar>, { @@ -647,6 +650,7 @@ pub trait EuclideanVector: Vector + Sized where /// The norm of the vector. #[inline] fn length(&self) -> Self::Scalar { + // Not sure why these annotations are needed <::Scalar as ::rust_num::Float>::sqrt(self.dot(self)) } @@ -679,6 +683,7 @@ pub trait EuclideanVector: Vector + Sized where /// Normalises the vector to a length of `1`. #[inline] fn normalize_self(&mut self) { + // Not sure why these annotations are needed let rlen = <::Scalar as ::rust_num::Float>::recip(self.length()); self.mul_self_s(rlen); } From 490997c93f70443ca20d249b2228e86831e5ff26 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 3 Nov 2015 15:50:07 +1100 Subject: [PATCH 8/8] Add an alias to Vector::Scalar in Point --- src/point.rs | 49 +++++++++++++++++++++++++++--------------------- src/rotation.rs | 4 ++-- src/transform.rs | 17 +++++++++-------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/point.rs b/src/point.rs index 2b21109f..c2d05682 100644 --- a/src/point.rs +++ b/src/point.rs @@ -68,7 +68,7 @@ impl Point3 { /// Specifies the numeric operations for point types. pub trait Point: Clone where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: Array1::Vector as Vector>::Scalar>, + Self: Array1::Scalar>, // FIXME: blocked by rust-lang/rust#20671 // // for<'a, 'b> &'a Self: Add<&'b V, Output = Self>, @@ -78,8 +78,13 @@ pub trait Point: Clone where // for<'a> &'a Self: Div, // for<'a> &'a Self: Rem, { + /// The associated scalar. + /// + /// Due to the equality constraints demanded by `Self::Vector`, this is effectively just an + /// alias to `Self::Vector::Scalar`. + type Scalar: BaseNum; /// The associated displacement vector. - type Vector: Vector; + type Vector: Vector; /// Create a point at the origin. fn origin() -> Self; @@ -91,13 +96,13 @@ pub trait Point: Clone where /// Multiply each component by a scalar, returning the new point. #[must_use] - fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; + fn mul_s(&self, scalar: Self::Scalar) -> Self; /// Divide each component by a scalar, returning the new point. #[must_use] - fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; + fn div_s(&self, scalar: Self::Scalar) -> Self; /// Subtract a scalar from each component, returning the new point. #[must_use] - fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Self; + fn rem_s(&self, scalar: Self::Scalar) -> Self; /// Add a vector to this point, returning the new point. #[must_use] @@ -106,17 +111,17 @@ pub trait Point: Clone where fn sub_p(&self, p: &Self) -> Self::Vector; /// Multiply each component by a scalar, in-place. - fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); + fn mul_self_s(&mut self, scalar: Self::Scalar); /// Divide each component by a scalar, in-place. - fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); + fn div_self_s(&mut self, scalar: Self::Scalar); /// Take the remainder of each component by a scalar, in-place. - fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar); + fn rem_self_s(&mut self, scalar: Self::Scalar); /// Add a vector to this point, in-place. fn add_self_v(&mut self, v: &Self::Vector); /// This is a weird one, but its useful for plane calculations. - fn dot(&self, v: &Self::Vector) -> <::Vector as Vector>::Scalar; + fn dot(&self, v: &Self::Vector) -> Self::Scalar; #[must_use] fn min(&self, p: &Self) -> Self; @@ -130,6 +135,7 @@ impl Array1 for Point2 { } impl Point for Point2 { + type Scalar = S; type Vector = Vector2; #[inline] @@ -147,26 +153,26 @@ impl Point for Point2 { Vector2::new(self.x, self.y) } - #[inline] fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self * scalar } - #[inline] fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self / scalar } - #[inline] fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point2 { self % scalar } + #[inline] fn mul_s(&self, scalar: S) -> Point2 { self * scalar } + #[inline] fn div_s(&self, scalar: S) -> Point2 { self / scalar } + #[inline] fn rem_s(&self, scalar: S) -> Point2 { self % scalar } #[inline] fn add_v(&self, v: &Vector2) -> Point2 { self + v } #[inline] fn sub_p(&self, p: &Point2) -> Vector2 { self - p } #[inline] - fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn mul_self_s(&mut self, scalar: S) { self.x = self.x * scalar; self.y = self.y * scalar; } #[inline] - fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn div_self_s(&mut self, scalar: S) { self.x = self.x / scalar; self.y = self.y / scalar; } #[inline] - fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn rem_self_s(&mut self, scalar: S) { self.x = self.x % scalar; self.y = self.y % scalar; } @@ -209,6 +215,7 @@ impl Array1 for Point3 { } impl Point for Point3 { + type Scalar = S; type Vector = Vector3; #[inline] @@ -226,28 +233,28 @@ impl Point for Point3 { Vector3::new(self.x, self.y, self.z) } - #[inline] fn mul_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self * scalar } - #[inline] fn div_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self / scalar } - #[inline] fn rem_s(&self, scalar: <::Vector as Vector>::Scalar) -> Point3 { self % scalar } + #[inline] fn mul_s(&self, scalar: S) -> Point3 { self * scalar } + #[inline] fn div_s(&self, scalar: S) -> Point3 { self / scalar } + #[inline] fn rem_s(&self, scalar: S) -> Point3 { self % scalar } #[inline] fn add_v(&self, v: &Vector3) -> Point3 { self + v } #[inline] fn sub_p(&self, p: &Point3) -> Vector3 { self - p } #[inline] - fn mul_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn mul_self_s(&mut self, scalar: S) { self.x = self.x * scalar; self.y = self.y * scalar; self.z = self.z * scalar; } #[inline] - fn div_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn div_self_s(&mut self, scalar: S) { self.x = self.x / scalar; self.y = self.y / scalar; self.z = self.z / scalar; } #[inline] - fn rem_self_s(&mut self, scalar: <::Vector as Vector>::Scalar) { + fn rem_self_s(&mut self, scalar: S) { self.x = self.x % scalar; self.y = self.y % scalar; self.z = self.z % scalar; diff --git a/src/rotation.rs b/src/rotation.rs index 7e1fed6d..068bfccf 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -27,8 +27,8 @@ use vector::{Vector, Vector2, Vector3}; /// creates a circular motion, and preserves at least one point in the space. pub trait Rotation: PartialEq + Sized where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - Self: ApproxEq::Vector as Vector>::Scalar>, - <

::Vector as Vector>::Scalar: BaseFloat, + Self: ApproxEq::Scalar>, +

::Scalar: BaseFloat, { /// Create the identity transform (causes no transformation). fn one() -> Self; diff --git a/src/transform.rs b/src/transform.rs index 5a0e2fb1..a1583ab7 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -80,12 +80,12 @@ pub struct Decomposed { impl> Transform

for Decomposed where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - <

::Vector as Vector>::Scalar: BaseFloat, +

::Scalar: BaseFloat, { #[inline] fn one() -> Decomposed { Decomposed { - scale: <

::Vector as Vector>::Scalar::one(), + scale:

::Scalar::one(), rot: R::one(), disp: P::Vector::zero(), } @@ -96,7 +96,7 @@ impl> Transform

for Decomposed where let rot = R::look_at(¢er.sub_p(eye), up); let disp = rot.rotate_vector(&P::origin().sub_p(eye)); Decomposed { - scale: <

::Vector as Vector>::Scalar::one(), + scale:

::Scalar::one(), rot: rot, disp: disp, } @@ -121,10 +121,10 @@ impl> Transform

for Decomposed where } fn invert(&self) -> Option> { - if self.scale.approx_eq(&<

::Vector as Vector>::Scalar::zero()) { + if self.scale.approx_eq(&

::Scalar::zero()) { None } else { - let s = <

::Vector as Vector>::Scalar::one() / self.scale; + let s =

::Scalar::one() / self.scale; let r = self.rot.invert(); let d = r.rotate_vector(&self.disp).mul_s(-s); Some(Decomposed { @@ -215,7 +215,8 @@ impl Transform3 for AffineMatrix3 {} /// A trait that allows extracting components (rotation, translation, scale) /// from an arbitrary transformations pub trait ToComponents> where - <

::Vector as Vector>::Scalar: BaseFloat, + // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 +

::Scalar: BaseFloat, { /// Extract the (scale, rotation, translation) triple fn decompose(&self) -> (P::Vector, R, P::Vector); @@ -226,7 +227,7 @@ pub trait ToComponents3>: ToComponents, pub trait CompositeTransform>: Transform

+ ToComponents where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - <

::Vector as Vector>::Scalar: BaseFloat, +

::Scalar: BaseFloat, {} pub trait CompositeTransform2>: Transform2 + ToComponents2 {} @@ -234,7 +235,7 @@ pub trait CompositeTransform3>: Transform3 + To impl + Clone> ToComponents for Decomposed where // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 - <

::Vector as Vector>::Scalar: BaseFloat, +

::Scalar: BaseFloat, { fn decompose(&self) -> (P::Vector, R, P::Vector) { (P::Vector::one().mul_s(self.scale), self.rot.clone(), self.disp.clone())