Make vectors an associated type on Point
This commit is contained in:
parent
28ea56442a
commit
78f86a33cd
4 changed files with 63 additions and 91 deletions
25
src/point.rs
25
src/point.rs
|
@ -66,7 +66,7 @@ impl<S: BaseNum> Point3<S> {
|
|||
}
|
||||
|
||||
/// Specifies the numeric operations for point types.
|
||||
pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone // where
|
||||
pub trait Point<S: BaseNum>: Array1<S> + 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<S: BaseNum, V: Vector<S>>: Array1<S> + Clone // where
|
|||
// for<'a> &'a Self: Div<S, Output = Self>,
|
||||
// for<'a> &'a Self: Rem<S, Output = Self>,
|
||||
{
|
||||
/// The associated displacement vector.
|
||||
type Vector: Vector<S>;
|
||||
|
||||
/// 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<S: BaseNum, V: Vector<S>>: Array1<S> + 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<S: BaseNum, V: Vector<S>>: Array1<S> + 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<S: BaseNum, V: Vector<S>>: Array1<S> + Clone // where
|
|||
|
||||
impl<S: BaseNum> Array1<S> for Point2<S> {}
|
||||
|
||||
impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
|
||||
impl<S: BaseNum> Point<S> for Point2<S> {
|
||||
type Vector = Vector2<S>;
|
||||
|
||||
#[inline]
|
||||
fn origin() -> Point2<S> {
|
||||
Point2::new(S::zero(), S::zero())
|
||||
|
@ -195,7 +200,9 @@ impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
|
|||
|
||||
impl<S: BaseNum> Array1<S> for Point3<S> {}
|
||||
|
||||
impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
|
||||
impl<S: BaseNum> Point<S> for Point3<S> {
|
||||
type Vector = Vector3<S>;
|
||||
|
||||
#[inline]
|
||||
fn origin() -> Point3<S> {
|
||||
Point3::new(S::zero(), S::zero(), S::zero())
|
||||
|
|
|
@ -339,7 +339,7 @@ impl<S: BaseFloat> From<Quaternion<S>> for Basis3<S> {
|
|||
fn from(quat: Quaternion<S>) -> Basis3<S> { Basis3::from_quaternion(&quat) }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Quaternion<S> {
|
||||
impl<S: BaseFloat + 'static> Rotation<S, Point3<S>> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn one() -> Quaternion<S> { Quaternion::one() }
|
||||
|
||||
|
|
|
@ -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<S: BaseFloat, V: Vector<S>, P: Point<S, V>>: PartialEq + ApproxEq<S> + Sized {
|
||||
pub trait Rotation<S: BaseFloat, P: Point<S>>: PartialEq + ApproxEq<S> + 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<S: BaseFloat, V: Vector<S>, P: Point<S, V>>: PartialEq + Appr
|
|||
}
|
||||
|
||||
/// A two-dimensional rotation.
|
||||
pub trait Rotation2<S: BaseFloat>: Rotation<S, Vector2<S>, Point2<S>>
|
||||
pub trait Rotation2<S: BaseFloat>: Rotation<S, Point2<S>>
|
||||
+ Into<Matrix2<S>>
|
||||
+ Into<Basis2<S>> {
|
||||
/// Create a rotation by a given angle. Thus is a redundant case of both
|
||||
|
@ -76,7 +76,7 @@ pub trait Rotation2<S: BaseFloat>: Rotation<S, Vector2<S>, Point2<S>>
|
|||
}
|
||||
|
||||
/// A three-dimensional rotation.
|
||||
pub trait Rotation3<S: BaseFloat>: Rotation<S, Vector3<S>, Point3<S>>
|
||||
pub trait Rotation3<S: BaseFloat>: Rotation<S, Point3<S>>
|
||||
+ Into<Matrix3<S>>
|
||||
+ Into<Basis3<S>>
|
||||
+ Into<Quaternion<S>> {
|
||||
|
@ -172,7 +172,7 @@ impl<S: BaseFloat> From<Basis2<S>> for Matrix2<S> {
|
|||
fn from(b: Basis2<S>) -> Matrix2<S> { b.mat }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
|
||||
impl<S: BaseFloat> Rotation<S, Point2<S>> for Basis2<S> {
|
||||
#[inline]
|
||||
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
|
||||
|
||||
|
@ -213,7 +213,7 @@ impl<S: BaseFloat> ApproxEq<S> for Basis2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Rotation2<S> for Basis2<S> {
|
||||
impl<S: BaseFloat> Rotation2<S> for Basis2<S> {
|
||||
fn from_angle(theta: Rad<S>) -> Basis2<S> { Basis2 { mat: Matrix2::from_angle(theta) } }
|
||||
}
|
||||
|
||||
|
@ -248,12 +248,12 @@ impl<S: BaseFloat> From<Basis3<S>> for Matrix3<S> {
|
|||
fn from(b: Basis3<S>) -> Matrix3<S> { b.mat }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> From<Basis3<S>> for Quaternion<S> {
|
||||
impl<S: BaseFloat> From<Basis3<S>> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn from(b: Basis3<S>) -> Quaternion<S> { b.mat.into() }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
|
||||
impl<S: BaseFloat> Rotation<S, Point3<S>> for Basis3<S> {
|
||||
#[inline]
|
||||
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
|
||||
|
||||
|
@ -295,7 +295,7 @@ impl<S: BaseFloat> ApproxEq<S> for Basis3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Rotation3<S> for Basis3<S> {
|
||||
impl<S: BaseFloat> Rotation3<S> for Basis3<S> {
|
||||
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Basis3<S> {
|
||||
Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
|
||||
}
|
||||
|
|
105
src/transform.rs
105
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<S: BaseNum, V: Vector<S>, P: Point<S, V>>: Sized {
|
||||
pub trait Transform<S: BaseNum, P: Point<S>>: 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<S, V, R> {
|
|||
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, P: Point<S>, R: Rotation<S, P>> Transform<S, P> for Decomposed<S, P::Vector, R> {
|
||||
#[inline]
|
||||
fn one() -> Decomposed<S, V, R> {
|
||||
fn one() -> Decomposed<S, P::Vector, R> {
|
||||
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<S, V, R> {
|
||||
fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed<S, P::Vector, R> {
|
||||
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<S, V, R>) -> Decomposed<S, V, R> {
|
||||
fn concat(&self, other: &Decomposed<S, P::Vector, R>) -> Decomposed<S, P::Vector, R> {
|
||||
Decomposed {
|
||||
scale: self.scale * other.scale,
|
||||
rot: self.rot.concat(&other.rot),
|
||||
|
@ -122,7 +117,7 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn invert(&self) -> Option<Decomposed<S, V, R>> {
|
||||
fn invert(&self) -> Option<Decomposed<S, P::Vector, R>> {
|
||||
if self.scale.approx_eq(&S::zero()) {
|
||||
None
|
||||
} else {
|
||||
|
@ -138,13 +133,10 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Transform2<S: BaseNum>: Transform<S, Vector2<S>, Point2<S>> + Into<Matrix3<S>> {}
|
||||
pub trait Transform3<S: BaseNum>: Transform<S, Vector3<S>, Point3<S>> + Into<Matrix4<S>> {}
|
||||
pub trait Transform2<S: BaseNum>: Transform<S, Point2<S>> + Into<Matrix3<S>> {}
|
||||
pub trait Transform3<S: BaseNum>: Transform<S, Point3<S>> + Into<Matrix4<S>> {}
|
||||
|
||||
impl<
|
||||
S: BaseFloat + 'static,
|
||||
R: Rotation2<S>,
|
||||
> From<Decomposed<S, Vector2<S>, R>> for Matrix3<S> {
|
||||
impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<S, Vector2<S>, R>> for Matrix3<S> {
|
||||
fn from(dec: Decomposed<S, Vector2<S>, R>) -> Matrix3<S> {
|
||||
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<S>,
|
||||
> From<Decomposed<S, Vector3<S>, R>> for Matrix4<S> {
|
||||
impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<S, Vector3<S>, R>> for Matrix4<S> {
|
||||
fn from(dec: Decomposed<S, Vector3<S>, R>) -> Matrix4<S> {
|
||||
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<S>,
|
||||
> Transform2<S> for Decomposed<S, Vector2<S>, R> {}
|
||||
impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<S, Vector2<S>, R> {}
|
||||
|
||||
impl<
|
||||
S: BaseFloat + 'static,
|
||||
R: Rotation3<S>,
|
||||
> Transform3<S> for Decomposed<S, Vector3<S>, R> {}
|
||||
impl<S: BaseFloat, 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 {
|
||||
write!(f, "(scale({:?}), rot({:?}), disp{:?})",
|
||||
self.scale, self.rot, self.disp)
|
||||
|
@ -191,7 +171,7 @@ pub struct AffineMatrix3<S> {
|
|||
pub mat: Matrix4<S>,
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Transform<S, Vector3<S>, Point3<S>> for AffineMatrix3<S> {
|
||||
impl<S: BaseFloat> Transform<S, Point3<S>> for AffineMatrix3<S> {
|
||||
#[inline]
|
||||
fn one() -> AffineMatrix3<S> {
|
||||
AffineMatrix3 { mat: Matrix4::one() }
|
||||
|
@ -227,22 +207,22 @@ impl<S: BaseNum> From<AffineMatrix3<S>> for Matrix4<S> {
|
|||
#[inline] fn from(aff: AffineMatrix3<S>) -> Matrix4<S> { aff.mat }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat + 'static> Transform3<S> for AffineMatrix3<S> {}
|
||||
impl<S: BaseFloat> Transform3<S> for AffineMatrix3<S> {}
|
||||
|
||||
/// A trait that allows extracting components (rotation, translation, scale)
|
||||
/// from an arbitrary transformations
|
||||
pub trait ToComponents<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>> {
|
||||
pub trait ToComponents<S: BaseFloat, P: Point<S>, R: Rotation<S, P>> {
|
||||
/// Extract the (scale, rotation, translation) triple
|
||||
fn decompose(&self) -> (V, R, V);
|
||||
fn decompose(&self) -> (P::Vector, R, P::Vector);
|
||||
}
|
||||
|
||||
pub trait ToComponents2<S: BaseFloat, R: Rotation2<S>>:
|
||||
ToComponents<S, Vector2<S>, Point2<S>, R> {}
|
||||
ToComponents<S, Point2<S>, R> {}
|
||||
pub trait ToComponents3<S: BaseFloat, R: Rotation3<S>>:
|
||||
ToComponents<S, Vector3<S>, Point3<S>, R> {}
|
||||
ToComponents<S, Point3<S>, R> {}
|
||||
|
||||
pub trait CompositeTransform<S: BaseFloat, V: Vector<S>, P: Point<S, V>, R: Rotation<S, V, P>>:
|
||||
Transform<S, V, P> + ToComponents<S, V, P, R> {}
|
||||
pub trait CompositeTransform<S: BaseFloat, P: Point<S>, R: Rotation<S, P>>:
|
||||
Transform<S, P> + ToComponents<S, P, R> {}
|
||||
pub trait CompositeTransform2<S: BaseFloat, R: Rotation2<S>>:
|
||||
Transform2<S> + ToComponents2<S, R> {}
|
||||
pub trait CompositeTransform3<S: BaseFloat, R: Rotation3<S>>:
|
||||
|
@ -250,31 +230,16 @@ pub trait CompositeTransform3<S: BaseFloat, R: Rotation3<S>>:
|
|||
|
||||
impl<
|
||||
S: BaseFloat,
|
||||
V: Vector<S> + Clone,
|
||||
P: Point<S, V>,
|
||||
R: Rotation<S, V, P> + Clone,
|
||||
> ToComponents<S, V, P, R> for Decomposed<S, V, R> {
|
||||
fn decompose(&self) -> (V, R, V) {
|
||||
(V::one().mul_s(self.scale), self.rot.clone(), self.disp.clone())
|
||||
P: Point<S>,
|
||||
R: Rotation<S, P> + Clone,
|
||||
> ToComponents<S, P, R> for Decomposed<S, P::Vector, R> {
|
||||
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<S> + Clone,
|
||||
> ToComponents2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||
impl<S: BaseFloat, R: Rotation2<S> + Clone> ToComponents2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||
impl<S: BaseFloat, R: Rotation3<S> + Clone> ToComponents3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||
|
||||
impl<
|
||||
S: BaseFloat,
|
||||
R: Rotation3<S> + Clone,
|
||||
> ToComponents3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||
|
||||
impl<
|
||||
S: BaseFloat + 'static,
|
||||
R: Rotation2<S> + Clone,
|
||||
> CompositeTransform2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||
|
||||
impl<
|
||||
S: BaseFloat + 'static,
|
||||
R: Rotation3<S> + Clone,
|
||||
> CompositeTransform3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||
impl<S: BaseFloat, R: Rotation2<S> + Clone> CompositeTransform2<S, R> for Decomposed<S, Vector2<S>, R> {}
|
||||
impl<S: BaseFloat, R: Rotation3<S> + Clone> CompositeTransform3<S, R> for Decomposed<S, Vector3<S>, R> {}
|
||||
|
|
Loading…
Reference in a new issue