Merge pull request #249 from bjz/by-value

Make lots of methods take vectors, points, and quaternions by value
This commit is contained in:
Brendan Zabarauskas 2015-11-11 11:50:57 +11:00
commit 137c3a7b0a
12 changed files with 245 additions and 245 deletions

View file

@ -65,9 +65,9 @@ impl<S> Matrix2<S> {
impl<S: BaseFloat> Matrix2<S> { impl<S: BaseFloat> Matrix2<S> {
/// Create a transformation matrix that will cause a vector to point at /// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation. /// `dir`, using `up` for orientation.
pub fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Matrix2<S> { pub fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Matrix2<S> {
//TODO: verify look_at 2D //TODO: verify look_at 2D
Matrix2::from_cols(up.clone(), dir.clone()).transpose() Matrix2::from_cols(up, dir).transpose()
} }
#[inline] #[inline]
@ -110,10 +110,10 @@ impl<S> Matrix3<S> {
impl<S: BaseFloat> Matrix3<S> { impl<S: BaseFloat> Matrix3<S> {
/// Create a transformation matrix that will cause a vector to point at /// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation. /// `dir`, using `up` for orientation.
pub fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Matrix3<S> { pub fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Matrix3<S> {
let dir = dir.normalize(); let dir = dir.normalize();
let side = up.cross(&dir).normalize(); let side = up.cross(dir).normalize();
let up = dir.cross(&side).normalize(); let up = dir.cross(side).normalize();
Matrix3::from_cols(side, up, dir).transpose() Matrix3::from_cols(side, up, dir).transpose()
} }
@ -164,7 +164,7 @@ impl<S: BaseFloat> Matrix3<S> {
} }
/// Create a matrix from a rotation around an arbitrary axis /// Create a matrix from a rotation around an arbitrary axis
pub fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Matrix3<S> { pub fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Matrix3<S> {
let (s, c) = sin_cos(angle); let (s, c) = sin_cos(angle);
let _1subc = S::one() - c; let _1subc = S::one() - c;
@ -215,7 +215,7 @@ impl<S> Matrix4<S> {
impl<S: BaseNum> Matrix4<S> { impl<S: BaseNum> Matrix4<S> {
/// Create a translation matrix from a Vector3 /// Create a translation matrix from a Vector3
#[inline] #[inline]
pub fn from_translation(v: &Vector3<S>) -> Matrix4<S> { pub fn from_translation(v: Vector3<S>) -> Matrix4<S> {
Matrix4::new(S::one(), S::zero(), S::zero(), S::zero(), Matrix4::new(S::one(), S::zero(), S::zero(), S::zero(),
S::zero(), S::one(), S::zero(), S::zero(), S::zero(), S::one(), S::zero(), S::zero(),
S::zero(), S::zero(), S::one(), S::zero(), S::zero(), S::zero(), S::one(), S::zero(),
@ -226,15 +226,15 @@ impl<S: BaseNum> Matrix4<S> {
impl<S: BaseFloat> Matrix4<S> { impl<S: BaseFloat> Matrix4<S> {
/// Create a transformation matrix that will cause a vector to point at /// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation. /// `dir`, using `up` for orientation.
pub fn look_at(eye: &Point3<S>, center: &Point3<S>, up: &Vector3<S>) -> Matrix4<S> { pub fn look_at(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
let f = (center - eye).normalize(); let f = (center - eye).normalize();
let s = f.cross(up).normalize(); let s = f.cross(up).normalize();
let u = s.cross(&f); let u = s.cross(f);
Matrix4::new(s.x.clone(), u.x.clone(), -f.x.clone(), S::zero(), Matrix4::new(s.x.clone(), u.x.clone(), -f.x.clone(), S::zero(),
s.y.clone(), u.y.clone(), -f.y.clone(), S::zero(), s.y.clone(), u.y.clone(), -f.y.clone(), S::zero(),
s.z.clone(), u.z.clone(), -f.z.clone(), S::zero(), s.z.clone(), u.z.clone(), -f.z.clone(), S::zero(),
-eye.dot(&s), -eye.dot(&u), eye.dot(&f), S::one()) -eye.dot(s), -eye.dot(u), eye.dot(f), S::one())
} }
} }
@ -275,7 +275,7 @@ pub trait Matrix where
/// Create a new diagonal matrix using the supplied value. /// Create a new diagonal matrix using the supplied value.
fn from_value(value: Self::Element) -> Self; fn from_value(value: Self::Element) -> Self;
/// Create a matrix from a non-uniform scale /// Create a matrix from a non-uniform scale
fn from_diagonal(diagonal: &Self::Column) -> Self; fn from_diagonal(diagonal: Self::Column) -> Self;
/// Create a matrix with all elements equal to zero. /// Create a matrix with all elements equal to zero.
#[inline] #[inline]
@ -303,7 +303,7 @@ pub trait Matrix where
fn sub_m(&self, m: &Self) -> Self; fn sub_m(&self, m: &Self) -> Self;
/// Multiplay a vector by this matrix, returning a new vector. /// Multiplay a vector by this matrix, returning a new vector.
fn mul_v(&self, v: &Self::Column) -> Self::Column; fn mul_v(&self, v: Self::Column) -> Self::Column;
/// Multiply this matrix by another matrix, returning the new matrix. /// Multiply this matrix by another matrix, returning the new matrix.
#[must_use] #[must_use]
@ -440,7 +440,7 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
} }
#[inline] #[inline]
fn from_diagonal(value: &Vector2<S>) -> Matrix2<S> { fn from_diagonal(value: Vector2<S>) -> Matrix2<S> {
Matrix2::new(value.x, S::zero(), Matrix2::new(value.x, S::zero(),
S::zero(), value.y) S::zero(), value.y)
} }
@ -451,7 +451,7 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
#[inline] fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m } #[inline] fn add_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m } #[inline] fn sub_m(&self, m: &Matrix2<S>) -> Matrix2<S> { self - m }
fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { self * other } fn mul_m(&self, other: &Matrix2<S>) -> Matrix2<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector2<S>) -> Vector2<S> { self * v } #[inline] fn mul_v(&self, v: Vector2<S>) -> Vector2<S> { self * v }
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn mul_self_s(&mut self, s: S) {
@ -473,14 +473,14 @@ impl<S: BaseFloat> Matrix for Matrix2<S> {
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix2<S>) { fn add_self_m(&mut self, m: &Matrix2<S>) {
self[0].add_self_v(&m[0]); self[0].add_self_v(m[0]);
self[1].add_self_v(&m[1]); self[1].add_self_v(m[1]);
} }
#[inline] #[inline]
fn sub_self_m(&mut self, m: &Matrix2<S>) { fn sub_self_m(&mut self, m: &Matrix2<S>) {
self[0].sub_self_v(&m[0]); self[0].sub_self_v(m[0]);
self[1].sub_self_v(&m[1]); self[1].sub_self_v(m[1]);
} }
fn transpose(&self) -> Matrix2<S> { fn transpose(&self) -> Matrix2<S> {
@ -540,7 +540,7 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
} }
#[inline] #[inline]
fn from_diagonal(value: &Vector3<S>) -> Matrix3<S> { fn from_diagonal(value: Vector3<S>) -> Matrix3<S> {
Matrix3::new(value.x, S::zero(), S::zero(), Matrix3::new(value.x, S::zero(), S::zero(),
S::zero(), value.y, S::zero(), S::zero(), value.y, S::zero(),
S::zero(), S::zero(), value.z) S::zero(), S::zero(), value.z)
@ -552,7 +552,7 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
#[inline] fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m } #[inline] fn add_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m } #[inline] fn sub_m(&self, m: &Matrix3<S>) -> Matrix3<S> { self - m }
fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> { self * other } fn mul_m(&self, other: &Matrix3<S>) -> Matrix3<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector3<S>) -> Vector3<S> { self * v} #[inline] fn mul_v(&self, v: Vector3<S>) -> Vector3<S> { self * v}
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn mul_self_s(&mut self, s: S) {
@ -577,16 +577,16 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix3<S>) { fn add_self_m(&mut self, m: &Matrix3<S>) {
self[0].add_self_v(&m[0]); self[0].add_self_v(m[0]);
self[1].add_self_v(&m[1]); self[1].add_self_v(m[1]);
self[2].add_self_v(&m[2]); self[2].add_self_v(m[2]);
} }
#[inline] #[inline]
fn sub_self_m(&mut self, m: &Matrix3<S>) { fn sub_self_m(&mut self, m: &Matrix3<S>) {
self[0].sub_self_v(&m[0]); self[0].sub_self_v(m[0]);
self[1].sub_self_v(&m[1]); self[1].sub_self_v(m[1]);
self[2].sub_self_v(&m[2]); self[2].sub_self_v(m[2]);
} }
fn transpose(&self) -> Matrix3<S> { fn transpose(&self) -> Matrix3<S> {
@ -618,9 +618,9 @@ impl<S: BaseFloat> Matrix for Matrix3<S> {
fn invert(&self) -> Option<Matrix3<S>> { fn invert(&self) -> Option<Matrix3<S>> {
let det = self.determinant(); let det = self.determinant();
if det.approx_eq(&S::zero()) { None } else { if det.approx_eq(&S::zero()) { None } else {
Some(Matrix3::from_cols(&self[1].cross(&self[2]) / det, Some(Matrix3::from_cols(self[1].cross(self[2]) / det,
&self[2].cross(&self[0]) / det, self[2].cross(self[0]) / det,
&self[0].cross(&self[1]) / det).transpose()) self[0].cross(self[1]) / det).transpose())
} }
} }
@ -659,7 +659,7 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
} }
#[inline] #[inline]
fn from_diagonal(value: &Vector4<S>) -> Matrix4<S> { fn from_diagonal(value: Vector4<S>) -> Matrix4<S> {
Matrix4::new(value.x, S::zero(), S::zero(), S::zero(), Matrix4::new(value.x, S::zero(), S::zero(), S::zero(),
S::zero(), value.y, S::zero(), S::zero(), S::zero(), value.y, S::zero(), S::zero(),
S::zero(), S::zero(), value.z, S::zero(), S::zero(), S::zero(), value.z, S::zero(),
@ -672,7 +672,7 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
#[inline] fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m } #[inline] fn add_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self + m }
#[inline] fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m } #[inline] fn sub_m(&self, m: &Matrix4<S>) -> Matrix4<S> { self - m }
fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> { self * other } fn mul_m(&self, other: &Matrix4<S>) -> Matrix4<S> { self * other }
#[inline] fn mul_v(&self, v: &Vector4<S>) -> Vector4<S> { self * v } #[inline] fn mul_v(&self, v: Vector4<S>) -> Vector4<S> { self * v }
#[inline] #[inline]
fn mul_self_s(&mut self, s: S) { fn mul_self_s(&mut self, s: S) {
@ -700,18 +700,18 @@ impl<S: BaseFloat> Matrix for Matrix4<S> {
#[inline] #[inline]
fn add_self_m(&mut self, m: &Matrix4<S>) { fn add_self_m(&mut self, m: &Matrix4<S>) {
self[0].add_self_v(&m[0]); self[0].add_self_v(m[0]);
self[1].add_self_v(&m[1]); self[1].add_self_v(m[1]);
self[2].add_self_v(&m[2]); self[2].add_self_v(m[2]);
self[3].add_self_v(&m[3]); self[3].add_self_v(m[3]);
} }
#[inline] #[inline]
fn sub_self_m(&mut self, m: &Matrix4<S>) { fn sub_self_m(&mut self, m: &Matrix4<S>) {
self[0].sub_self_v(&m[0]); self[0].sub_self_v(m[0]);
self[1].sub_self_v(&m[1]); self[1].sub_self_v(m[1]);
self[2].sub_self_v(&m[2]); self[2].sub_self_v(m[2]);
self[3].sub_self_v(&m[3]); self[3].sub_self_v(m[3]);
} }
fn transpose(&self) -> Matrix4<S> { fn transpose(&self) -> Matrix4<S> {
@ -928,7 +928,7 @@ macro_rules! impl_vector_mul_operators {
type Output = $VectorN<S>; type Output = $VectorN<S>;
fn mul(self, v: $VectorN<S>) -> $VectorN<S> { fn mul(self, v: $VectorN<S>) -> $VectorN<S> {
$VectorN::new($(self.row($row_index).dot(&v)),+) $VectorN::new($(self.row($row_index).dot(v)),+)
} }
} }
@ -936,7 +936,7 @@ macro_rules! impl_vector_mul_operators {
type Output = $VectorN<S>; type Output = $VectorN<S>;
fn mul(self, v: &'a $VectorN<S>) -> $VectorN<S> { fn mul(self, v: &'a $VectorN<S>) -> $VectorN<S> {
$VectorN::new($(self.row($row_index).dot(v)),+) $VectorN::new($(self.row($row_index).dot(*v)),+)
} }
} }
} }
@ -950,8 +950,8 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix2<S>> for &'b Matrix2<S> {
type Output = Matrix2<S>; type Output = Matrix2<S>;
fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> { fn mul(self, other: &'a Matrix2<S>) -> Matrix2<S> {
Matrix2::new(self.row(0).dot(&other[0]), self.row(1).dot(&other[0]), Matrix2::new(self.row(0).dot(other[0]), self.row(1).dot(other[0]),
self.row(0).dot(&other[1]), self.row(1).dot(&other[1])) self.row(0).dot(other[1]), self.row(1).dot(other[1]))
} }
} }
@ -959,9 +959,9 @@ impl<'a, 'b, S: BaseNum> Mul<&'a Matrix3<S>> for &'b Matrix3<S> {
type Output = Matrix3<S>; type Output = Matrix3<S>;
fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> { fn mul(self, other: &'a Matrix3<S>) -> Matrix3<S> {
Matrix3::new(self.row(0).dot(&other[0]),self.row(1).dot(&other[0]),self.row(2).dot(&other[0]), Matrix3::new(self.row(0).dot(other[0]),self.row(1).dot(other[0]),self.row(2).dot(other[0]),
self.row(0).dot(&other[1]),self.row(1).dot(&other[1]),self.row(2).dot(&other[1]), self.row(0).dot(other[1]),self.row(1).dot(other[1]),self.row(2).dot(other[1]),
self.row(0).dot(&other[2]),self.row(1).dot(&other[2]),self.row(2).dot(&other[2])) self.row(0).dot(other[2]),self.row(1).dot(other[2]),self.row(2).dot(other[2]))
} }
} }

View file

@ -54,19 +54,19 @@ impl<S: BaseNum> Point3<S> {
impl<S: BaseNum> Point3<S> { impl<S: BaseNum> Point3<S> {
#[inline] #[inline]
pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> { pub fn from_homogeneous(v: Vector4<S>) -> Point3<S> {
let e = v.truncate() * (S::one() / v.w); let e = v.truncate() * (S::one() / v.w);
Point3::new(e.x, e.y, e.z) //FIXME Point3::new(e.x, e.y, e.z) //FIXME
} }
#[inline] #[inline]
pub fn to_homogeneous(&self) -> Vector4<S> { pub fn to_homogeneous(self) -> Vector4<S> {
Vector4::new(self.x, self.y, self.z, S::one()) Vector4::new(self.x, self.y, self.z, S::one())
} }
} }
/// Specifies the numeric operations for point types. /// Specifies the numeric operations for point types.
pub trait Point: Clone where pub trait Point: Copy + Clone where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array1<Element = <Self as Point>::Scalar>, Self: Array1<Element = <Self as Point>::Scalar>,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
@ -90,25 +90,25 @@ pub trait Point: Clone where
fn origin() -> Self; fn origin() -> Self;
/// Create a point from a vector. /// Create a point from a vector.
fn from_vec(v: &Self::Vector) -> Self; fn from_vec(v: Self::Vector) -> Self;
/// Convert a point to a vector. /// Convert a point to a vector.
fn to_vec(&self) -> Self::Vector; fn to_vec(self) -> Self::Vector;
/// Multiply each component by a scalar, returning the new point. /// Multiply each component by a scalar, returning the new point.
#[must_use] #[must_use]
fn mul_s(&self, scalar: Self::Scalar) -> Self; fn mul_s(self, scalar: Self::Scalar) -> Self;
/// Divide each component by a scalar, returning the new point. /// Divide each component by a scalar, returning the new point.
#[must_use] #[must_use]
fn div_s(&self, scalar: Self::Scalar) -> Self; fn div_s(self, scalar: Self::Scalar) -> Self;
/// Subtract a scalar from each component, returning the new point. /// Subtract a scalar from each component, returning the new point.
#[must_use] #[must_use]
fn rem_s(&self, scalar: Self::Scalar) -> Self; fn rem_s(self, scalar: Self::Scalar) -> Self;
/// Add a vector to this point, returning the new point. /// Add a vector to this point, returning the new point.
#[must_use] #[must_use]
fn add_v(&self, v: &Self::Vector) -> Self; fn add_v(self, v: Self::Vector) -> Self;
/// Subtract another point from this one, returning a new vector. /// Subtract another point from this one, returning a new vector.
fn sub_p(&self, p: &Self) -> Self::Vector; fn sub_p(self, p: Self) -> Self::Vector;
/// Multiply each component by a scalar, in-place. /// Multiply each component by a scalar, in-place.
fn mul_self_s(&mut self, scalar: Self::Scalar); fn mul_self_s(&mut self, scalar: Self::Scalar);
@ -118,16 +118,16 @@ pub trait Point: Clone where
fn rem_self_s(&mut self, scalar: Self::Scalar); fn rem_self_s(&mut self, scalar: Self::Scalar);
/// Add a vector to this point, in-place. /// Add a vector to this point, in-place.
fn add_self_v(&mut self, v: &Self::Vector); fn add_self_v(&mut self, v: Self::Vector);
/// This is a weird one, but its useful for plane calculations. /// This is a weird one, but its useful for plane calculations.
fn dot(&self, v: &Self::Vector) -> Self::Scalar; fn dot(self, v: Self::Vector) -> Self::Scalar;
#[must_use] #[must_use]
fn min(&self, p: &Self) -> Self; fn min(self, p: Self) -> Self;
#[must_use] #[must_use]
fn max(&self, p: &Self) -> Self; fn max(self, p: Self) -> Self;
} }
impl<S: BaseNum> Array1 for Point2<S> { impl<S: BaseNum> Array1 for Point2<S> {
@ -144,20 +144,20 @@ impl<S: BaseNum> Point for Point2<S> {
} }
#[inline] #[inline]
fn from_vec(v: &Vector2<S>) -> Point2<S> { fn from_vec(v: Vector2<S>) -> Point2<S> {
Point2::new(v.x, v.y) Point2::new(v.x, v.y)
} }
#[inline] #[inline]
fn to_vec(&self) -> Vector2<S> { fn to_vec(self) -> Vector2<S> {
Vector2::new(self.x, self.y) Vector2::new(self.x, self.y)
} }
#[inline] fn mul_s(&self, scalar: S) -> Point2<S> { self * scalar } #[inline] fn mul_s(self, scalar: S) -> Point2<S> { self * scalar }
#[inline] fn div_s(&self, scalar: S) -> Point2<S> { self / scalar } #[inline] fn div_s(self, scalar: S) -> Point2<S> { self / scalar }
#[inline] fn rem_s(&self, scalar: S) -> Point2<S> { self % scalar } #[inline] fn rem_s(self, scalar: S) -> Point2<S> { self % scalar }
#[inline] fn add_v(&self, v: &Vector2<S>) -> Point2<S> { self + v } #[inline] fn add_v(self, v: Vector2<S>) -> Point2<S> { self + v }
#[inline] fn sub_p(&self, p: &Point2<S>) -> Vector2<S> { self - p } #[inline] fn sub_p(self, p: Point2<S>) -> Vector2<S> { self - p }
#[inline] #[inline]
fn mul_self_s(&mut self, scalar: S) { fn mul_self_s(&mut self, scalar: S) {
@ -178,24 +178,24 @@ impl<S: BaseNum> Point for Point2<S> {
} }
#[inline] #[inline]
fn add_self_v(&mut self, v: &Vector2<S>) { fn add_self_v(&mut self, v: Vector2<S>) {
self.x = self.x + v.x; self.x = self.x + v.x;
self.y = self.y + v.y; self.y = self.y + v.y;
} }
#[inline] #[inline]
fn dot(&self, v: &Vector2<S>) -> S { fn dot(self, v: Vector2<S>) -> S {
self.x * v.x + self.x * v.x +
self.y * v.y self.y * v.y
} }
#[inline] #[inline]
fn min(&self, p: &Point2<S>) -> Point2<S> { fn min(self, p: Point2<S>) -> Point2<S> {
Point2::new(self.x.partial_min(p.x), self.y.partial_min(p.y)) Point2::new(self.x.partial_min(p.x), self.y.partial_min(p.y))
} }
#[inline] #[inline]
fn max(&self, p: &Point2<S>) -> Point2<S> { fn max(self, p: Point2<S>) -> Point2<S> {
Point2::new(self.x.partial_max(p.x), self.y.partial_max(p.y)) Point2::new(self.x.partial_max(p.x), self.y.partial_max(p.y))
} }
} }
@ -224,20 +224,20 @@ impl<S: BaseNum> Point for Point3<S> {
} }
#[inline] #[inline]
fn from_vec(v: &Vector3<S>) -> Point3<S> { fn from_vec(v: Vector3<S>) -> Point3<S> {
Point3::new(v.x, v.y, v.z) Point3::new(v.x, v.y, v.z)
} }
#[inline] #[inline]
fn to_vec(&self) -> Vector3<S> { fn to_vec(self) -> Vector3<S> {
Vector3::new(self.x, self.y, self.z) Vector3::new(self.x, self.y, self.z)
} }
#[inline] fn mul_s(&self, scalar: S) -> Point3<S> { self * scalar } #[inline] fn mul_s(self, scalar: S) -> Point3<S> { self * scalar }
#[inline] fn div_s(&self, scalar: S) -> Point3<S> { self / scalar } #[inline] fn div_s(self, scalar: S) -> Point3<S> { self / scalar }
#[inline] fn rem_s(&self, scalar: S) -> Point3<S> { self % scalar } #[inline] fn rem_s(self, scalar: S) -> Point3<S> { self % scalar }
#[inline] fn add_v(&self, v: &Vector3<S>) -> Point3<S> { self + v } #[inline] fn add_v(self, v: Vector3<S>) -> Point3<S> { self + v }
#[inline] fn sub_p(&self, p: &Point3<S>) -> Vector3<S> { self - p } #[inline] fn sub_p(self, p: Point3<S>) -> Vector3<S> { self - p }
#[inline] #[inline]
fn mul_self_s(&mut self, scalar: S) { fn mul_self_s(&mut self, scalar: S) {
@ -261,26 +261,26 @@ impl<S: BaseNum> Point for Point3<S> {
} }
#[inline] #[inline]
fn add_self_v(&mut self, v: &Vector3<S>) { fn add_self_v(&mut self, v: Vector3<S>) {
self.x = self.x + v.x; self.x = self.x + v.x;
self.y = self.y + v.y; self.y = self.y + v.y;
self.z = self.z + v.z; self.z = self.z + v.z;
} }
#[inline] #[inline]
fn dot(&self, v: &Vector3<S>) -> S { fn dot(self, v: Vector3<S>) -> S {
self.x * v.x + self.x * v.x +
self.y * v.y + self.y * v.y +
self.z * v.z self.z * v.z
} }
#[inline] #[inline]
fn min(&self, p: &Point3<S>) -> Point3<S> { fn min(self, p: Point3<S>) -> Point3<S> {
Point3::new(self.x.partial_min(p.x), self.y.partial_min(p.y), self.z.partial_min(p.z)) Point3::new(self.x.partial_min(p.x), self.y.partial_min(p.y), self.z.partial_min(p.z))
} }
#[inline] #[inline]
fn max(&self, p: &Point3<S>) -> Point3<S> { fn max(self, p: Point3<S>) -> Point3<S> {
Point3::new(self.x.partial_max(p.x), self.y.partial_max(p.y), self.z.partial_max(p.z)) Point3::new(self.x.partial_max(p.x), self.y.partial_max(p.y), self.z.partial_max(p.z))
} }
} }

View file

@ -72,21 +72,21 @@ impl<S: BaseFloat> Quaternion<S> {
/// The dot product of the quaternion and `q`. /// The dot product of the quaternion and `q`.
#[inline] #[inline]
pub fn dot(&self, q: &Quaternion<S>) -> S { pub fn dot(self, q: Quaternion<S>) -> S {
self.s * q.s + self.v.dot(&q.v) self.s * q.s + self.v.dot(q.v)
} }
/// The conjugate of the quaternion. /// The conjugate of the quaternion.
#[inline] #[inline]
pub fn conjugate(&self) -> Quaternion<S> { pub fn conjugate(self) -> Quaternion<S> {
Quaternion::from_sv(self.s.clone(), -self.v.clone()) Quaternion::from_sv(self.s, -self.v)
} }
/// The squared magnitude of the quaternion. This is useful for /// The squared magnitude of the quaternion. This is useful for
/// magnitude comparisons where the exact magnitude does not need to be /// magnitude comparisons where the exact magnitude does not need to be
/// calculated. /// calculated.
#[inline] #[inline]
pub fn magnitude2(&self) -> S { pub fn magnitude2(self) -> S {
self.s * self.s + self.v.length2() self.s * self.s + self.v.length2()
} }
@ -104,12 +104,12 @@ impl<S: BaseFloat> Quaternion<S> {
/// Normalize this quaternion, returning the new quaternion. /// Normalize this quaternion, returning the new quaternion.
#[inline] #[inline]
pub fn normalize(&self) -> Quaternion<S> { pub fn normalize(self) -> Quaternion<S> {
self * (S::one() / self.magnitude()) self * (S::one() / self.magnitude())
} }
/// Do a normalized linear interpolation with `other`, by `amount`. /// Do a normalized linear interpolation with `other`, by `amount`.
pub fn nlerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> { pub fn nlerp(self, other: Quaternion<S>, amount: S) -> Quaternion<S> {
(&(self * (S::one() - amount)) + &(other * amount)).normalize() (&(self * (S::one() - amount)) + &(other * amount)).normalize()
} }
} }
@ -156,8 +156,8 @@ impl<'a, 'b, S: BaseFloat> Mul<&'b Vector3<S>> for &'a Quaternion<S> {
#[inline] #[inline]
fn mul(self, vec: &'b Vector3<S>) -> Vector3<S> { fn mul(self, vec: &'b Vector3<S>) -> Vector3<S> {
let two: S = cast(2i8).unwrap(); let two: S = cast(2i8).unwrap();
let tmp = self.v.cross(vec) + (vec * self.s); let tmp = self.v.cross(*vec) + (vec * self.s);
(self.v.cross(&tmp) * two) + vec (self.v.cross(tmp) * two) + vec
} }
} }
@ -218,7 +218,7 @@ impl<S: BaseFloat> Quaternion<S> {
/// (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/) /// (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
/// - [Arcsynthesis OpenGL tutorial] /// - [Arcsynthesis OpenGL tutorial]
/// (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html) /// (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
pub fn slerp(&self, other: &Quaternion<S>, amount: S) -> Quaternion<S> { pub fn slerp(self, other: Quaternion<S>, amount: S) -> Quaternion<S> {
let dot = self.dot(other); let dot = self.dot(other);
let dot_threshold = cast(0.9995f64).unwrap(); let dot_threshold = cast(0.9995f64).unwrap();
@ -251,7 +251,7 @@ impl<S: BaseFloat> Quaternion<S> {
/// Based on: /// Based on:
/// - [Maths - Conversion Quaternion to Euler] /// - [Maths - Conversion Quaternion to Euler]
/// (http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/) /// (http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/)
pub fn to_euler(&self) -> (Rad<S>, Rad<S>, Rad<S>) { pub fn to_euler(self) -> (Rad<S>, Rad<S>, Rad<S>) {
let sig: S = cast(0.499f64).unwrap(); let sig: S = cast(0.499f64).unwrap();
let two: S = cast(2f64).unwrap(); let two: S = cast(2f64).unwrap();
let one: S = cast(1f64).unwrap(); let one: S = cast(1f64).unwrap();
@ -367,19 +367,19 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
fn one() -> Quaternion<S> { Quaternion::one() } fn one() -> Quaternion<S> { Quaternion::one() }
#[inline] #[inline]
fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Quaternion<S> { fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Quaternion<S> {
Matrix3::look_at(dir, up).into() Matrix3::look_at(dir, up).into()
} }
#[inline] #[inline]
fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Quaternion<S> { fn between_vectors(a: Vector3<S>, b: Vector3<S>) -> Quaternion<S> {
//http://stackoverflow.com/questions/1171849/ //http://stackoverflow.com/questions/1171849/
//finding-quaternion-representing-the-rotation-from-one-vector-to-another //finding-quaternion-representing-the-rotation-from-one-vector-to-another
Quaternion::from_sv(S::one() + a.dot(b), a.cross(b)).normalize() Quaternion::from_sv(S::one() + a.dot(b), a.cross(b)).normalize()
} }
#[inline] #[inline]
fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self * vec } fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self * &vec }
#[inline] #[inline]
fn concat(&self, other: &Quaternion<S>) -> Quaternion<S> { self * other } fn concat(&self, other: &Quaternion<S>) -> Quaternion<S> { self * other }
@ -396,7 +396,7 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
impl<S: BaseFloat> Rotation3<S> for Quaternion<S> where S: 'static { impl<S: BaseFloat> Rotation3<S> for Quaternion<S> where S: 'static {
#[inline] #[inline]
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Quaternion<S> { fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Quaternion<S> {
let (s, c) = sin_cos(angle.mul_s(cast(0.5f64).unwrap())); let (s, c) = sin_cos(angle.mul_s(cast(0.5f64).unwrap()));
Quaternion::from_sv(c, axis.mul_s(s)) Quaternion::from_sv(c, axis.mul_s(s))
} }

View file

@ -34,20 +34,20 @@ pub trait Rotation<P: Point>: PartialEq + Sized where
fn one() -> Self; fn one() -> Self;
/// Create a rotation to a given direction with an 'up' vector /// Create a rotation to a given direction with an 'up' vector
fn look_at(dir: &P::Vector, up: &P::Vector) -> Self; fn look_at(dir: P::Vector, up: P::Vector) -> Self;
/// Create a shortest rotation to transform vector 'a' into 'b'. /// Create a shortest rotation to transform vector 'a' into 'b'.
/// Both given vectors are assumed to have unit length. /// Both given vectors are assumed to have unit length.
fn between_vectors(a: &P::Vector, b: &P::Vector) -> Self; fn between_vectors(a: P::Vector, b: P::Vector) -> Self;
/// Rotate a vector using this rotation. /// Rotate a vector using this rotation.
fn rotate_vector(&self, vec: &P::Vector) -> P::Vector; fn rotate_vector(&self, vec: P::Vector) -> P::Vector;
/// Rotate a point using this rotation, by converting it to its /// Rotate a point using this rotation, by converting it to its
/// representation as a vector. /// representation as a vector.
#[inline] #[inline]
fn rotate_point(&self, point: &P) -> P { fn rotate_point(&self, point: P) -> P {
P::from_vec(&self.rotate_vector(&point.to_vec())) P::from_vec(self.rotate_vector(point.to_vec()))
} }
/// Create a new rotation which combines both this rotation, and another. /// Create a new rotation which combines both this rotation, and another.
@ -85,7 +85,7 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
+ Into<Basis3<S>> + Into<Basis3<S>>
+ Into<Quaternion<S>> { + Into<Quaternion<S>> {
/// Create a rotation using an angle around a given axis. /// Create a rotation using an angle around a given axis.
fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self; fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Self;
/// Create a rotation from a set of euler angles. /// Create a rotation from a set of euler angles.
/// ///
@ -99,19 +99,19 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
/// Create a rotation from an angle around the `x` axis (pitch). /// Create a rotation from an angle around the `x` axis (pitch).
#[inline] #[inline]
fn from_angle_x(theta: Rad<S>) -> Self { fn from_angle_x(theta: Rad<S>) -> Self {
Rotation3::from_axis_angle(&Vector3::unit_x(), theta) Rotation3::from_axis_angle(Vector3::unit_x(), theta)
} }
/// Create a rotation from an angle around the `y` axis (yaw). /// Create a rotation from an angle around the `y` axis (yaw).
#[inline] #[inline]
fn from_angle_y(theta: Rad<S>) -> Self { fn from_angle_y(theta: Rad<S>) -> Self {
Rotation3::from_axis_angle(&Vector3::unit_y(), theta) Rotation3::from_axis_angle(Vector3::unit_y(), theta)
} }
/// Create a rotation from an angle around the `z` axis (roll). /// Create a rotation from an angle around the `z` axis (roll).
#[inline] #[inline]
fn from_angle_z(theta: Rad<S>) -> Self { fn from_angle_z(theta: Rad<S>) -> Self {
Rotation3::from_axis_angle(&Vector3::unit_z(), theta) Rotation3::from_axis_angle(Vector3::unit_z(), theta)
} }
} }
@ -143,7 +143,7 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
/// let rot: Basis2<f64> = Rotation2::from_angle(rad(0.5f64 * f64::consts::PI)); /// let rot: Basis2<f64> = Rotation2::from_angle(rad(0.5f64 * f64::consts::PI));
/// ///
/// // Rotate the vector using the two-dimensional rotation matrix: /// // Rotate the vector using the two-dimensional rotation matrix:
/// let unit_y = rot.rotate_vector(&unit_x); /// let unit_y = rot.rotate_vector(unit_x);
/// ///
/// // Since sin(π/2) may not be exactly zero due to rounding errors, we can /// // Since sin(π/2) may not be exactly zero due to rounding errors, we can
/// // use cgmath's approx_eq() feature to show that it is close enough. /// // use cgmath's approx_eq() feature to show that it is close enough.
@ -151,12 +151,12 @@ pub trait Rotation3<S: BaseFloat>: Rotation<Point3<S>>
/// ///
/// // This is exactly equivalent to using the raw matrix itself: /// // This is exactly equivalent to using the raw matrix itself:
/// let unit_y2: Matrix2<_> = rot.into(); /// let unit_y2: Matrix2<_> = rot.into();
/// let unit_y2 = unit_y2.mul_v(&unit_x); /// let unit_y2 = unit_y2.mul_v(unit_x);
/// assert_eq!(unit_y2, unit_y); /// assert_eq!(unit_y2, unit_y);
/// ///
/// // Note that we can also concatenate rotations: /// // Note that we can also concatenate rotations:
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI)); /// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
/// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(&unit_x); /// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(unit_x);
/// assert!(unit_y3.approx_eq(&unit_y2)); /// assert!(unit_y3.approx_eq(&unit_y2));
/// ``` /// ```
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)] #[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
@ -181,17 +181,17 @@ impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } } fn one() -> Basis2<S> { Basis2 { mat: Matrix2::one() } }
#[inline] #[inline]
fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Basis2<S> { fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Basis2<S> {
Basis2 { mat: Matrix2::look_at(dir, up) } Basis2 { mat: Matrix2::look_at(dir, up) }
} }
#[inline] #[inline]
fn between_vectors(a: &Vector2<S>, b: &Vector2<S>) -> Basis2<S> { fn between_vectors(a: Vector2<S>, b: Vector2<S>) -> Basis2<S> {
Rotation2::from_angle(acos(a.dot(b)) ) Rotation2::from_angle(acos(a.dot(b)) )
} }
#[inline] #[inline]
fn rotate_vector(&self, vec: &Vector2<S>) -> Vector2<S> { self.mat.mul_v(vec) } fn rotate_vector(&self, vec: Vector2<S>) -> Vector2<S> { self.mat.mul_v(vec) }
#[inline] #[inline]
fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } } fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }
@ -264,18 +264,18 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Basis3<S> {
fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } } fn one() -> Basis3<S> { Basis3 { mat: Matrix3::one() } }
#[inline] #[inline]
fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Basis3<S> { fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Basis3<S> {
Basis3 { mat: Matrix3::look_at(dir, up) } Basis3 { mat: Matrix3::look_at(dir, up) }
} }
#[inline] #[inline]
fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Basis3<S> { fn between_vectors(a: Vector3<S>, b: Vector3<S>) -> Basis3<S> {
let q: Quaternion<S> = Rotation::between_vectors(a, b); let q: Quaternion<S> = Rotation::between_vectors(a, b);
q.into() q.into()
} }
#[inline] #[inline]
fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self.mat.mul_v(vec) } fn rotate_vector(&self, vec: Vector3<S>) -> Vector3<S> { self.mat.mul_v(vec) }
#[inline] #[inline]
fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } } fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }
@ -304,7 +304,7 @@ impl<S: BaseFloat> ApproxEq for Basis3<S> {
} }
impl<S: BaseFloat> 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> { fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Basis3<S> {
Basis3 { mat: Matrix3::from_axis_angle(axis, angle) } Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
} }

View file

@ -34,18 +34,18 @@ pub trait Transform<P: Point>: Sized {
/// Create a transformation that rotates a vector to look at `center` from /// Create a transformation that rotates a vector to look at `center` from
/// `eye`, using `up` for orientation. /// `eye`, using `up` for orientation.
fn look_at(eye: &P, center: &P, up: &P::Vector) -> Self; fn look_at(eye: P, center: P, up: P::Vector) -> Self;
/// Transform a vector using this transform. /// Transform a vector using this transform.
fn transform_vector(&self, vec: &P::Vector) -> P::Vector; fn transform_vector(&self, vec: P::Vector) -> P::Vector;
/// Transform a point using this transform. /// Transform a point using this transform.
fn transform_point(&self, point: &P) -> P; fn transform_point(&self, point: P) -> P;
/// Transform a vector as a point using this transform. /// Transform a vector as a point using this transform.
#[inline] #[inline]
fn transform_as_point(&self, vec: &P::Vector) -> P::Vector { fn transform_as_point(&self, vec: P::Vector) -> P::Vector {
self.transform_point(&P::from_vec(vec)).to_vec() self.transform_point(P::from_vec(vec)).to_vec()
} }
/// Combine this transform with another, yielding a new transformation /// Combine this transform with another, yielding a new transformation
@ -92,9 +92,9 @@ impl<P: Point, R: Rotation<P>> Transform<P> for Decomposed<P::Vector, R> where
} }
#[inline] #[inline]
fn look_at(eye: &P, center: &P, up: &P::Vector) -> Decomposed<P::Vector, R> { fn look_at(eye: P, center: P, up: P::Vector) -> Decomposed<P::Vector, R> {
let rot = R::look_at(&center.sub_p(eye), up); let rot = R::look_at(center.sub_p(eye.clone()), up);
let disp = rot.rotate_vector(&P::origin().sub_p(eye)); let disp = rot.rotate_vector(P::origin().sub_p(eye));
Decomposed { Decomposed {
scale: <P as Point>::Scalar::one(), scale: <P as Point>::Scalar::one(),
rot: rot, rot: rot,
@ -103,20 +103,20 @@ impl<P: Point, R: Rotation<P>> Transform<P> for Decomposed<P::Vector, R> where
} }
#[inline] #[inline]
fn transform_vector(&self, vec: &P::Vector) -> P::Vector { fn transform_vector(&self, vec: P::Vector) -> P::Vector {
self.rot.rotate_vector(&vec.mul_s(self.scale.clone())) self.rot.rotate_vector(vec.mul_s(self.scale))
} }
#[inline] #[inline]
fn transform_point(&self, point: &P) -> P { fn transform_point(&self, point: P) -> P {
self.rot.rotate_point(&point.mul_s(self.scale.clone())).add_v(&self.disp) self.rot.rotate_point(point.mul_s(self.scale)).add_v(self.disp.clone())
} }
fn concat(&self, other: &Decomposed<P::Vector, R>) -> Decomposed<P::Vector, R> { fn concat(&self, other: &Decomposed<P::Vector, R>) -> Decomposed<P::Vector, R> {
Decomposed { Decomposed {
scale: self.scale * other.scale, scale: self.scale * other.scale,
rot: self.rot.concat(&other.rot), rot: self.rot.concat(&other.rot),
disp: self.transform_as_point(&other.disp), disp: self.transform_as_point(other.disp.clone()),
} }
} }
@ -126,7 +126,7 @@ impl<P: Point, R: Rotation<P>> Transform<P> for Decomposed<P::Vector, R> where
} else { } else {
let s = <P as Point>::Scalar::one() / self.scale; let s = <P as Point>::Scalar::one() / self.scale;
let r = self.rot.invert(); let r = self.rot.invert();
let d = r.rotate_vector(&self.disp).mul_s(-s); let d = r.rotate_vector(self.disp.clone()).mul_s(-s);
Some(Decomposed { Some(Decomposed {
scale: s, scale: s,
rot: r, rot: r,
@ -181,18 +181,18 @@ impl<S: BaseFloat> Transform<Point3<S>> for AffineMatrix3<S> {
} }
#[inline] #[inline]
fn look_at(eye: &Point3<S>, center: &Point3<S>, up: &Vector3<S>) -> AffineMatrix3<S> { fn look_at(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> AffineMatrix3<S> {
AffineMatrix3 { mat: Matrix4::look_at(eye, center, up) } AffineMatrix3 { mat: Matrix4::look_at(eye, center, up) }
} }
#[inline] #[inline]
fn transform_vector(&self, vec: &Vector3<S>) -> Vector3<S> { fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
self.mat.mul_v(&vec.extend(S::zero())).truncate() self.mat.mul_v(vec.extend(S::zero())).truncate()
} }
#[inline] #[inline]
fn transform_point(&self, point: &Point3<S>) -> Point3<S> { fn transform_point(&self, point: Point3<S>) -> Point3<S> {
Point3::from_homogeneous(&self.mat.mul_v(&point.to_homogeneous())) Point3::from_homogeneous(self.mat.mul_v(point.to_homogeneous()))
} }
#[inline] #[inline]

View file

@ -39,9 +39,9 @@
//! let a: Vector2<f64> = Vector2::new(3.0, 4.0); //! let a: Vector2<f64> = Vector2::new(3.0, 4.0);
//! let b: Vector2<f64> = Vector2::new(-3.0, -4.0); //! let b: Vector2<f64> = Vector2::new(-3.0, -4.0);
//! //!
//! assert_eq!(&a + &b, Vector2::zero()); //! assert_eq!(a + b, Vector2::zero());
//! assert_eq!(-(&a * &b), Vector2::new(9.0f64, 16.0f64)); //! assert_eq!(-(a * b), Vector2::new(9.0f64, 16.0f64));
//! assert_eq!(&a / &Vector2::one(), a); //! assert_eq!(a / Vector2::one(), a);
//! //!
//! // As with Rust's `int` and `f32` types, Vectors of different types cannot //! // As with Rust's `int` and `f32` types, Vectors of different types cannot
//! // be added and so on with impunity. The following will fail to compile: //! // be added and so on with impunity. The following will fail to compile:
@ -49,10 +49,10 @@
//! //!
//! // Instead, we need to convert the Vector2 to a Vector3 by "extending" it //! // Instead, we need to convert the Vector2 to a Vector3 by "extending" it
//! // with the value for the last coordinate: //! // with the value for the last coordinate:
//! let c: Vector3<f64> = &a.extend(0.0) + &Vector3::new(1.0, 0.0, 2.0); //! let c: Vector3<f64> = a.extend(0.0) + Vector3::new(1.0, 0.0, 2.0);
//! //!
//! // Similarly, we can "truncate" a Vector4 down to a Vector3: //! // Similarly, we can "truncate" a Vector4 down to a Vector3:
//! let d: Vector3<f64> = &c + &Vector4::unit_x().truncate(); //! let d: Vector3<f64> = c + Vector4::unit_x().truncate();
//! //!
//! assert_eq!(d, Vector3::new(5.0f64, 4.0f64, 2.0f64)); //! assert_eq!(d, Vector3::new(5.0f64, 4.0f64, 2.0f64));
//! ``` //! ```
@ -68,10 +68,10 @@
//! // All vectors implement the dot product as a method: //! // All vectors implement the dot product as a method:
//! let a: Vector2<f64> = Vector2::new(3.0, 6.0); //! let a: Vector2<f64> = Vector2::new(3.0, 6.0);
//! let b: Vector2<f64> = Vector2::new(-2.0, 1.0); //! let b: Vector2<f64> = Vector2::new(-2.0, 1.0);
//! assert_eq!(a.dot(&b), 0.0); //! assert_eq!(a.dot(b), 0.0);
//! //!
//! // But there is also a top-level function: //! // But there is also a top-level function:
//! assert_eq!(a.dot(&b), dot(a, b)); //! assert_eq!(a.dot(b), dot(a, b));
//! //!
//! // 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:
@ -83,7 +83,7 @@
//! // Cross products are defined for 3-dimensional vectors: //! // Cross products are defined for 3-dimensional vectors:
//! let e: Vector3<f64> = Vector3::unit_x(); //! let e: Vector3<f64> = Vector3::unit_x();
//! let f: Vector3<f64> = Vector3::unit_y(); //! let f: Vector3<f64> = Vector3::unit_y();
//! assert_eq!(e.cross(&f), Vector3::unit_z()); //! assert_eq!(e.cross(f), Vector3::unit_z());
//! ``` //! ```
//! //!
//! Several other useful methods are provided as well. Vector fields can be //! Several other useful methods are provided as well. Vector fields can be
@ -111,7 +111,7 @@ use num::{BaseNum, BaseFloat};
/// A trait that specifies a range of numeric operations for vectors. Not all /// 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 /// of these make sense from a linear algebra point of view, but are included
/// for pragmatic reasons. /// for pragmatic reasons.
pub trait Vector: Clone where pub trait Vector: Copy + Clone where
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092 // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Array1<Element = <Self as Vector>::Scalar>, Self: Array1<Element = <Self as Vector>::Scalar>,
// FIXME: blocked by rust-lang/rust#20671 // FIXME: blocked by rust-lang/rust#20671
@ -144,35 +144,35 @@ pub trait Vector: Clone where
/// 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, scalar: Self::Scalar) -> Self; fn add_s(self, scalar: Self::Scalar) -> Self;
/// Subtract a scalar from this vector, returning a new vector. /// Subtract a scalar from this vector, returning a new vector.
#[must_use] #[must_use]
fn sub_s(&self, scalar: Self::Scalar) -> Self; fn sub_s(self, scalar: Self::Scalar) -> Self;
/// Multiply this vector by a scalar, returning a new vector. /// Multiply this vector by a scalar, returning a new vector.
#[must_use] #[must_use]
fn mul_s(&self, scalar: Self::Scalar) -> Self; fn mul_s(self, scalar: Self::Scalar) -> Self;
/// Divide this vector by a scalar, returning a new vector. /// Divide this vector by a scalar, returning a new vector.
#[must_use] #[must_use]
fn div_s(&self, scalar: Self::Scalar) -> Self; fn div_s(self, scalar: Self::Scalar) -> Self;
/// Take the remainder of this vector by a scalar, returning a new vector. /// Take the remainder of this vector by a scalar, returning a new vector.
#[must_use] #[must_use]
fn rem_s(&self, scalar: Self::Scalar) -> Self; fn rem_s(self, scalar: Self::Scalar) -> Self;
/// Add this vector to another, returning a new vector. /// Add this vector to another, returning a new vector.
#[must_use] #[must_use]
fn add_v(&self, v: &Self) -> Self; fn add_v(self, v: Self) -> Self;
/// Subtract another vector from this one, returning a new vector. /// Subtract another vector from this one, returning a new vector.
#[must_use] #[must_use]
fn sub_v(&self, v: &Self) -> Self; fn sub_v(self, v: Self) -> Self;
/// Multiply this vector by another, returning a new vector. /// Multiply this vector by another, returning a new vector.
#[must_use] #[must_use]
fn mul_v(&self, v: &Self) -> Self; fn mul_v(self, v: Self) -> Self;
/// Divide this vector by another, returning a new vector. /// Divide this vector by another, returning a new vector.
#[must_use] #[must_use]
fn div_v(&self, v: &Self) -> Self; fn div_v(self, v: Self) -> Self;
/// Take the remainder of this vector by another, returning a new scalar. /// Take the remainder of this vector by another, returning a new scalar.
#[must_use] #[must_use]
fn rem_v(&self, v: &Self) -> Self; fn rem_v(self, v: Self) -> Self;
/// Add a scalar to this vector in-place. /// Add a scalar to this vector in-place.
fn add_self_s(&mut self, scalar: Self::Scalar); fn add_self_s(&mut self, scalar: Self::Scalar);
@ -186,33 +186,33 @@ pub trait Vector: Clone where
fn rem_self_s(&mut self, scalar: Self::Scalar); fn rem_self_s(&mut self, scalar: Self::Scalar);
/// Add another vector to this one, in-place. /// Add another vector to this one, in-place.
fn add_self_v(&mut self, v: &Self); fn add_self_v(&mut self, v: Self);
/// Subtract another vector from this one, in-place. /// Subtract another vector from this one, in-place.
fn sub_self_v(&mut self, v: &Self); fn sub_self_v(&mut self, v: Self);
/// Multiply this matrix by another, in-place. /// Multiply this matrix by another, in-place.
fn mul_self_v(&mut self, v: &Self); fn mul_self_v(&mut self, v: Self);
/// Divide this matrix by anothor, in-place. /// Divide this matrix by anothor, in-place.
fn div_self_v(&mut self, v: &Self); fn div_self_v(&mut self, v: Self);
/// Take the remainder of this vector by another, in-place. /// Take the remainder of this vector by another, in-place.
fn rem_self_v(&mut self, v: &Self); fn rem_self_v(&mut self, v: Self);
/// The sum of the components of the vector. /// The sum of the components of the vector.
fn sum(&self) -> Self::Scalar; fn sum(self) -> Self::Scalar;
/// The product of the components of the vector. /// The product of the components of the vector.
fn product(&self) -> Self::Scalar; fn product(self) -> Self::Scalar;
/// Vector dot product. /// Vector dot product.
#[inline] #[inline]
fn dot(&self, v: &Self) -> Self::Scalar { self.mul_v(v).sum() } fn dot(self, v: Self) -> Self::Scalar { self.mul_v(v).sum() }
/// The minimum component of the vector. /// The minimum component of the vector.
fn comp_min(&self) -> Self::Scalar; fn comp_min(self) -> Self::Scalar;
/// The maximum component of the vector. /// The maximum component of the vector.
fn comp_max(&self) -> Self::Scalar; fn comp_max(self) -> Self::Scalar;
} }
/// Dot product of two vectors. /// Dot product of two vectors.
#[inline] pub fn dot<V: Vector>(a: V, b: V) -> V::Scalar { a.dot(&b) } #[inline] pub fn dot<V: Vector>(a: V, b: V) -> V::Scalar { a.dot(b) }
// Utility macro for generating associated functions for the vectors // Utility macro for generating associated functions for the vectors
macro_rules! vec { macro_rules! vec {
@ -259,17 +259,17 @@ macro_rules! vec {
#[inline] fn from_value(scalar: S) -> $VectorN<S> { $VectorN { $($field: scalar),+ } } #[inline] fn from_value(scalar: S) -> $VectorN<S> { $VectorN { $($field: scalar),+ } }
#[inline] fn add_s(&self, scalar: S) -> $VectorN<S> { self + scalar } #[inline] fn add_s(self, scalar: S) -> $VectorN<S> { self + scalar }
#[inline] fn sub_s(&self, scalar: S) -> $VectorN<S> { self - scalar } #[inline] fn sub_s(self, scalar: S) -> $VectorN<S> { self - scalar }
#[inline] fn mul_s(&self, scalar: S) -> $VectorN<S> { self * scalar } #[inline] fn mul_s(self, scalar: S) -> $VectorN<S> { self * scalar }
#[inline] fn div_s(&self, scalar: S) -> $VectorN<S> { self / scalar } #[inline] fn div_s(self, scalar: S) -> $VectorN<S> { self / scalar }
#[inline] fn rem_s(&self, scalar: S) -> $VectorN<S> { self % scalar } #[inline] fn rem_s(self, scalar: S) -> $VectorN<S> { self % scalar }
#[inline] fn add_v(&self, v: &$VectorN<S>) -> $VectorN<S> { self + v } #[inline] fn add_v(self, v: $VectorN<S>) -> $VectorN<S> { self + v }
#[inline] fn sub_v(&self, v: &$VectorN<S>) -> $VectorN<S> { self - v } #[inline] fn sub_v(self, v: $VectorN<S>) -> $VectorN<S> { self - v }
#[inline] fn mul_v(&self, v: &$VectorN<S>) -> $VectorN<S> { self * v } #[inline] fn mul_v(self, v: $VectorN<S>) -> $VectorN<S> { self * v }
#[inline] fn div_v(&self, v: &$VectorN<S>) -> $VectorN<S> { self / v } #[inline] fn div_v(self, v: $VectorN<S>) -> $VectorN<S> { self / v }
#[inline] fn rem_v(&self, v: &$VectorN<S>) -> $VectorN<S> { self % v } #[inline] fn rem_v(self, v: $VectorN<S>) -> $VectorN<S> { self % v }
#[inline] fn add_self_s(&mut self, scalar: S) { *self = &*self + scalar; } #[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 sub_self_s(&mut self, scalar: S) { *self = &*self - scalar; }
@ -277,16 +277,16 @@ macro_rules! vec {
#[inline] fn div_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 rem_self_s(&mut self, scalar: S) { *self = &*self % scalar; }
#[inline] fn add_self_v(&mut self, v: &$VectorN<S>) { *self = &*self + v; } #[inline] fn add_self_v(&mut self, v: $VectorN<S>) { *self = &*self + v; }
#[inline] fn sub_self_v(&mut self, v: &$VectorN<S>) { *self = &*self - v; } #[inline] fn sub_self_v(&mut self, v: $VectorN<S>) { *self = &*self - v; }
#[inline] fn mul_self_v(&mut self, v: &$VectorN<S>) { *self = &*self * v; } #[inline] fn mul_self_v(&mut self, v: $VectorN<S>) { *self = &*self * v; }
#[inline] fn div_self_v(&mut self, v: &$VectorN<S>) { *self = &*self / v; } #[inline] fn div_self_v(&mut self, v: $VectorN<S>) { *self = &*self / v; }
#[inline] fn rem_self_v(&mut self, v: &$VectorN<S>) { *self = &*self % v; } #[inline] fn rem_self_v(&mut self, v: $VectorN<S>) { *self = &*self % v; }
#[inline] fn sum(&self) -> S { fold!(add, { $(self.$field),+ }) } #[inline] fn sum(self) -> S { fold!(add, { $(self.$field),+ }) }
#[inline] fn product(&self) -> S { fold!(mul, { $(self.$field),+ }) } #[inline] fn product(self) -> S { fold!(mul, { $(self.$field),+ }) }
#[inline] fn comp_min(&self) -> S { fold!(partial_min, { $(self.$field),+ }) } #[inline] fn comp_min(self) -> S { fold!(partial_min, { $(self.$field),+ }) }
#[inline] fn comp_max(&self) -> S { fold!(partial_max, { $(self.$field),+ }) } #[inline] fn comp_max(self) -> S { fold!(partial_max, { $(self.$field),+ }) }
} }
impl<S: Neg<Output = S>> Neg for $VectorN<S> { impl<S: Neg<Output = S>> Neg for $VectorN<S> {
@ -555,14 +555,14 @@ impl<S: BaseNum> Vector2<S> {
/// The perpendicular dot product of the vector and `other`. /// The perpendicular dot product of the vector and `other`.
#[inline] #[inline]
pub fn perp_dot(&self, other: &Vector2<S>) -> S { pub fn perp_dot(self, other: Vector2<S>) -> S {
(self.x * other.y) - (self.y * other.x) (self.x * other.y) - (self.y * other.x)
} }
/// Create a `Vector3`, using the `x` and `y` values from this vector, and the /// Create a `Vector3`, using the `x` and `y` values from this vector, and the
/// provided `z`. /// provided `z`.
#[inline] #[inline]
pub fn extend(&self, z: S)-> Vector3<S> { pub fn extend(self, z: S)-> Vector3<S> {
Vector3::new(self.x, self.y, z) Vector3::new(self.x, self.y, z)
} }
} }
@ -590,7 +590,7 @@ impl<S: BaseNum> Vector3<S> {
/// Returns the cross product of the vector and `other`. /// Returns the cross product of the vector and `other`.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn cross(&self, other: &Vector3<S>) -> Vector3<S> { pub fn cross(self, other: Vector3<S>) -> Vector3<S> {
Vector3::new((self.y * other.z) - (self.z * other.y), Vector3::new((self.y * other.z) - (self.z * other.y),
(self.z * other.x) - (self.x * other.z), (self.z * other.x) - (self.x * other.z),
(self.x * other.y) - (self.y * other.x)) (self.x * other.y) - (self.y * other.x))
@ -599,20 +599,20 @@ impl<S: BaseNum> Vector3<S> {
/// Calculates the cross product of the vector and `other`, then stores the /// Calculates the cross product of the vector and `other`, then stores the
/// result in `self`. /// result in `self`.
#[inline] #[inline]
pub fn cross_self(&mut self, other: &Vector3<S>) { pub fn cross_self(&mut self, other: Vector3<S>) {
*self = self.cross(other) *self = self.cross(other)
} }
/// Create a `Vector4`, using the `x`, `y` and `z` values from this vector, and the /// Create a `Vector4`, using the `x`, `y` and `z` values from this vector, and the
/// provided `w`. /// provided `w`.
#[inline] #[inline]
pub fn extend(&self, w: S)-> Vector4<S> { pub fn extend(self, w: S)-> Vector4<S> {
Vector4::new(self.x, self.y, self.z, w) Vector4::new(self.x, self.y, self.z, w)
} }
/// Create a `Vector2`, dropping the `z` value. /// Create a `Vector2`, dropping the `z` value.
#[inline] #[inline]
pub fn truncate(&self)-> Vector2<S> { pub fn truncate(self)-> Vector2<S> {
Vector2::new(self.x, self.y) Vector2::new(self.x, self.y)
} }
} }
@ -645,7 +645,7 @@ impl<S: BaseNum> Vector4<S> {
/// Create a `Vector3`, dropping the `w` value. /// Create a `Vector3`, dropping the `w` value.
#[inline] #[inline]
pub fn truncate(&self)-> Vector3<S> { pub fn truncate(self)-> Vector3<S> {
Vector3::new(self.x, self.y, self.z) Vector3::new(self.x, self.y, self.z)
} }
@ -671,7 +671,7 @@ pub trait EuclideanVector: Vector + Sized where
{ {
/// Returns `true` if the vector is perpendicular (at right angles) to the /// Returns `true` if the vector is perpendicular (at right angles) to the
/// other vector. /// other vector.
fn is_perpendicular(&self, other: &Self) -> bool { fn is_perpendicular(self, other: Self) -> bool {
self.dot(other).approx_eq(&Self::Scalar::zero()) self.dot(other).approx_eq(&Self::Scalar::zero())
} }
@ -679,32 +679,32 @@ pub trait EuclideanVector: Vector + Sized where
/// expensive square root operation like in the `length` method and can /// expensive square root operation like in the `length` method and can
/// therefore be more efficient for comparing the lengths of two vectors. /// therefore be more efficient for comparing the lengths of two vectors.
#[inline] #[inline]
fn length2(&self) -> Self::Scalar { fn length2(self) -> Self::Scalar {
self.dot(self) self.dot(self)
} }
/// The norm of the vector. /// The norm of the vector.
#[inline] #[inline]
fn length(&self) -> Self::Scalar { fn length(self) -> Self::Scalar {
// Not sure why these annotations are needed // Not sure why these annotations are needed
<<Self as Vector>::Scalar as ::rust_num::Float>::sqrt(self.dot(self)) <<Self as Vector>::Scalar as ::rust_num::Float>::sqrt(self.dot(self))
} }
/// The angle between the vector and `other`, in radians. /// The angle between the vector and `other`, in radians.
fn angle(&self, other: &Self) -> Rad<Self::Scalar>; fn angle(self, other: Self) -> Rad<Self::Scalar>;
/// Returns a vector with the same direction, but with a `length` (or /// Returns a vector with the same direction, but with a `length` (or
/// `norm`) of `1`. /// `norm`) of `1`.
#[inline] #[inline]
#[must_use] #[must_use]
fn normalize(&self) -> Self { fn normalize(self) -> Self {
self.normalize_to(Self::Scalar::one()) self.normalize_to(Self::Scalar::one())
} }
/// Returns a vector with the same direction and a given `length`. /// Returns a vector with the same direction and a given `length`.
#[inline] #[inline]
#[must_use] #[must_use]
fn normalize_to(&self, length: Self::Scalar) -> Self { fn normalize_to(self, length: Self::Scalar) -> Self {
self.mul_s(length / self.length()) self.mul_s(length / self.length())
} }
@ -712,8 +712,8 @@ pub trait EuclideanVector: Vector + Sized where
/// towards the length of `other` by the specified amount. /// towards the length of `other` by the specified amount.
#[inline] #[inline]
#[must_use] #[must_use]
fn lerp(&self, other: &Self, amount: Self::Scalar) -> Self { fn lerp(self, other: Self, amount: Self::Scalar) -> Self {
self.add_v(&other.sub_v(self).mul_s(amount)) self.add_v(other.sub_v(self).mul_s(amount))
} }
/// Normalises the vector to a length of `1`. /// Normalises the vector to a length of `1`.
@ -733,29 +733,29 @@ pub trait EuclideanVector: Vector + Sized where
/// Linearly interpolates the length of the vector towards the length of /// Linearly interpolates the length of the vector towards the length of
/// `other` by the specified amount. /// `other` by the specified amount.
fn lerp_self(&mut self, other: &Self, amount: Self::Scalar) { fn lerp_self(&mut self, other: Self, amount: Self::Scalar) {
let v = other.sub_v(self).mul_s(amount); let v = other.sub_v(*self).mul_s(amount);
self.add_self_v(&v); self.add_self_v(v);
} }
} }
impl<S: BaseFloat> EuclideanVector for Vector2<S> { impl<S: BaseFloat> EuclideanVector for Vector2<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector2<S>) -> Rad<S> { fn angle(self, other: Vector2<S>) -> Rad<S> {
atan2(self.perp_dot(other), self.dot(other)) atan2(self.perp_dot(other), self.dot(other))
} }
} }
impl<S: BaseFloat> EuclideanVector for Vector3<S> { impl<S: BaseFloat> EuclideanVector for Vector3<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector3<S>) -> Rad<S> { fn angle(self, other: Vector3<S>) -> Rad<S> {
atan2(self.cross(other).length(), self.dot(other)) atan2(self.cross(other).length(), self.dot(other))
} }
} }
impl<S: BaseFloat> EuclideanVector for Vector4<S> { impl<S: BaseFloat> EuclideanVector for Vector4<S> {
#[inline] #[inline]
fn angle(&self, other: &Vector4<S>) -> Rad<S> { fn angle(self, other: Vector4<S>) -> Rad<S> {
acos(self.dot(other) / (self.length() * other.length())) acos(self.dot(other) / (self.length() * other.length()))
} }
} }

View file

@ -193,9 +193,9 @@ fn test_sub_m() {
#[test] #[test]
fn test_mul_v() { fn test_mul_v() {
assert_eq!(matrix2::A.mul_v(&matrix2::V), Vector2::new(5.0f64, 11.0f64)); assert_eq!(matrix2::A.mul_v(matrix2::V), Vector2::new(5.0f64, 11.0f64));
assert_eq!(matrix3::A.mul_v(&matrix3::V), Vector3::new(14.0f64, 32.0f64, 50.0f64)); assert_eq!(matrix3::A.mul_v(matrix3::V), Vector3::new(14.0f64, 32.0f64, 50.0f64));
assert_eq!(matrix4::A.mul_v(&matrix4::V), Vector4::new(30.0f64, 70.0f64, 110.0f64, 150.0f64)); assert_eq!(matrix4::A.mul_v(matrix4::V), Vector4::new(30.0f64, 70.0f64, 110.0f64, 150.0f64));
} }
#[test] #[test]
@ -328,9 +328,9 @@ fn test_invert() {
#[test] #[test]
fn test_from_translation() { fn test_from_translation() {
let mat = Matrix4::from_translation(&Vector3::new(1.0f64, 2.0f64, 3.0f64)); let mat = Matrix4::from_translation(Vector3::new(1.0f64, 2.0f64, 3.0f64));
let vertex = Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64); let vertex = Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64);
let res = mat.mul_v(&vertex); let res = mat.mul_v(vertex);
assert_eq!(res, Vector4::new(1., 2., 3., 1.)); assert_eq!(res, Vector4::new(1., 2., 3., 1.));
} }
@ -398,13 +398,13 @@ fn test_predicates() {
fn test_from_angle() { fn test_from_angle() {
// Rotate the vector (1, 0) by π/2 radians to the vector (0, 1) // Rotate the vector (1, 0) by π/2 radians to the vector (0, 1)
let rot1 = Matrix2::from_angle(rad(0.5f64 * f64::consts::PI)); let rot1 = Matrix2::from_angle(rad(0.5f64 * f64::consts::PI));
assert!(rot1.mul_v(&Vector2::unit_x()).approx_eq(&Vector2::unit_y())); assert!(rot1.mul_v(Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
// Rotate the vector (-1, 0) by -π/2 radians to the vector (0, 1) // Rotate the vector (-1, 0) by -π/2 radians to the vector (0, 1)
let rot2 = -rot1; let rot2 = -rot1;
assert!(rot2.mul_v(&-Vector2::unit_x()).approx_eq(&Vector2::unit_y())); assert!(rot2.mul_v(-Vector2::unit_x()).approx_eq(&Vector2::unit_y()));
// Rotate the vector (1, 1) by π radians to the vector (-1, -1) // Rotate the vector (1, 1) by π radians to the vector (-1, -1)
let rot3: Matrix2<f64> = Matrix2::from_angle(rad(f64::consts::PI)); let rot3: Matrix2<f64> = Matrix2::from_angle(rad(f64::consts::PI));
assert!(rot3.mul_v(&Vector2::new(1.0, 1.0)).approx_eq(&Vector2::new(-1.0, -1.0))); assert!(rot3.mul_v(Vector2::new(1.0, 1.0)).approx_eq(&Vector2::new(-1.0, -1.0)));
} }

View file

@ -22,5 +22,5 @@ use cgmath::ApproxEq;
#[test] #[test]
fn test_homogeneous() { fn test_homogeneous() {
let p = Point3::new(1.0f64, 2.0f64, 3.0f64); let p = Point3::new(1.0f64, 2.0f64, 3.0f64);
assert!(p.approx_eq(&Point3::from_homogeneous(&p.to_homogeneous()))); assert!(p.approx_eq(&Point3::from_homogeneous(p.to_homogeneous())));
} }

View file

@ -28,9 +28,9 @@ fn test_ortho_scale() {
let vec_far: Vector4<f32> = Vector4::new(1., 1., 1., 1.); let vec_far: Vector4<f32> = Vector4::new(1., 1., 1., 1.);
let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.); let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.);
let near = o.mul_v(&vec_near); let near = o.mul_v(vec_near);
let orig = o.mul_v(&vec_orig); let orig = o.mul_v(vec_orig);
let far = o.mul_v(&vec_far); let far = o.mul_v(vec_far);
assert_eq!(near, Vector4::new(-1f32, -1., 1., 1.)); assert_eq!(near, Vector4::new(-1f32, -1., 1., 1.));
assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.)); assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.));
@ -38,9 +38,9 @@ fn test_ortho_scale() {
let o: Matrix4<f32> = ortho(-2., 2., -2., 2., -2., 2.); let o: Matrix4<f32> = ortho(-2., 2., -2., 2., -2., 2.);
let near = o.mul_v(&vec_near); let near = o.mul_v(vec_near);
let orig = o.mul_v(&vec_orig); let orig = o.mul_v(vec_orig);
let far = o.mul_v(&vec_far); let far = o.mul_v(vec_far);
assert_eq!(near, Vector4::new(-0.5f32, -0.5, 0.5, 1.)); assert_eq!(near, Vector4::new(-0.5f32, -0.5, 0.5, 1.));
assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.)); assert_eq!(orig, Vector4::new(0f32, 0., 0., 1.));
@ -56,14 +56,14 @@ fn test_ortho_translate() {
let vec_orig: Vector4<f32> = Vector4::new(0., 0., 0., 1.); let vec_orig: Vector4<f32> = Vector4::new(0., 0., 0., 1.);
let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.); let o: Matrix4<f32> = ortho(-1., 1., -1., 1., -1., 1.);
let orig = o.mul_v(&vec_orig); let orig = o.mul_v(vec_orig);
assert_eq!(orig, Vector4::new(0., 0., 0., 1.)); assert_eq!(orig, Vector4::new(0., 0., 0., 1.));
let o: Matrix4<f32> = ortho(0., 2., 0., 2., 0., 2.); let o: Matrix4<f32> = ortho(0., 2., 0., 2., 0., 2.);
let orig = o.mul_v(&vec_orig); let orig = o.mul_v(vec_orig);
assert_eq!(orig, Vector4::new(-1., -1., -1., 1.)); assert_eq!(orig, Vector4::new(-1., -1., -1., 1.));
let o: Matrix4<f32> = ortho(-2., 0., -2., 0., -2., 0.); let o: Matrix4<f32> = ortho(-2., 0., -2., 0., -2., 0.);
let orig = o.mul_v(&vec_orig); let orig = o.mul_v(vec_orig);
assert_eq!(orig, Vector4::new(1., 1., 1., 1.)); assert_eq!(orig, Vector4::new(1., 1., 1., 1.));
} }

View file

@ -26,7 +26,7 @@ mod rotation {
pub fn a3<R: Rotation3<f64>>() -> R { pub fn a3<R: Rotation3<f64>>() -> R {
let axis = Vector3::new(1.0, 1.0, 0.0).normalize(); let axis = Vector3::new(1.0, 1.0, 0.0).normalize();
Rotation3::from_axis_angle(&axis, deg(30.0).into()) Rotation3::from_axis_angle(axis, deg(30.0).into())
} }
} }

View file

@ -27,8 +27,8 @@ fn test_invert() {
disp: Vector3::new(6.0f64,-7.0,8.0) disp: Vector3::new(6.0f64,-7.0,8.0)
}; };
let ti = t.invert().expect("Expected successful inversion"); let ti = t.invert().expect("Expected successful inversion");
let vt = t.transform_vector( &v ); let vt = t.transform_vector(v);
assert!(v.approx_eq( &ti.transform_vector( &vt ) )); assert!(v.approx_eq(&ti.transform_vector(vt)));
} }
#[test] #[test]
@ -36,10 +36,10 @@ fn test_look_at() {
let eye = Point3::new(0.0f64, 0.0, -5.0); let eye = Point3::new(0.0f64, 0.0, -5.0);
let center = Point3::new(0.0f64, 0.0, 0.0); let center = Point3::new(0.0f64, 0.0, 0.0);
let up = Vector3::new(1.0f64, 0.0, 0.0); let up = Vector3::new(1.0f64, 0.0, 0.0);
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at(&eye, &center, &up); let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at(eye, center, up);
let point = Point3::new(1.0f64, 0.0, 0.0); let point = Point3::new(1.0f64, 0.0, 0.0);
let view_point = Point3::new(0.0f64, 1.0, 5.0); let view_point = Point3::new(0.0f64, 1.0, 5.0);
assert!( t.transform_point(&point).approx_eq(&view_point) ); assert!(t.transform_point(point).approx_eq(&view_point));
} }
#[test] #[test]

View file

@ -35,9 +35,9 @@ fn test_from_value() {
#[test] #[test]
fn test_dot() { fn test_dot() {
assert_eq!(Vector2::new(1isize, 2isize).dot(&Vector2::new(3isize, 4isize)), 11isize); assert_eq!(Vector2::new(1isize, 2isize).dot(Vector2::new(3isize, 4isize)), 11isize);
assert_eq!(Vector3::new(1isize, 2isize, 3isize).dot(&Vector3::new(4isize, 5isize, 6isize)), 32isize); assert_eq!(Vector3::new(1isize, 2isize, 3isize).dot(Vector3::new(4isize, 5isize, 6isize)), 32isize);
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).dot(&Vector4::new(5isize, 6isize, 7isize, 8isize)), 70isize); assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).dot(Vector4::new(5isize, 6isize, 7isize, 8isize)), 70isize);
} }
#[test] #[test]
@ -89,18 +89,18 @@ fn test_cross() {
let a = Vector3::new(1isize, 2isize, 3isize); let a = Vector3::new(1isize, 2isize, 3isize);
let b = Vector3::new(4isize, 5isize, 6isize); let b = Vector3::new(4isize, 5isize, 6isize);
let r = Vector3::new(-3isize, 6isize, -3isize); let r = Vector3::new(-3isize, 6isize, -3isize);
assert_eq!(a.cross(&b), r); assert_eq!(a.cross(b), r);
let mut a = a; let mut a = a;
a.cross_self(&b); a.cross_self(b);
assert_eq!(a, r); assert_eq!(a, r);
} }
#[test] #[test]
fn test_is_perpendicular() { fn test_is_perpendicular() {
assert!(Vector2::new(1.0f64, 0.0f64).is_perpendicular(&Vector2::new(0.0f64, 1.0f64))); assert!(Vector2::new(1.0f64, 0.0f64).is_perpendicular(Vector2::new(0.0f64, 1.0f64)));
assert!(Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(&Vector3::new(0.0f64, 0.0f64, 1.0f64))); assert!(Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(Vector3::new(0.0f64, 0.0f64, 1.0f64)));
assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(&Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64))); assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64)));
} }
#[cfg(test)] #[cfg(test)]
@ -146,17 +146,17 @@ mod test_length {
#[test] #[test]
fn test_angle() { fn test_angle() {
assert!(Vector2::new(1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) )); assert!(Vector2::new(1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
assert!(Vector2::new(10.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) )); assert!(Vector2::new(10.0f64, 0.0f64).angle(Vector2::new(0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
assert!(Vector2::new(-1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &-rad(f64::consts::FRAC_PI_2) )); assert!(Vector2::new(-1.0f64, 0.0f64).angle(Vector2::new(0.0f64, 1.0f64)).approx_eq( &-rad(f64::consts::FRAC_PI_2) ));
assert!(Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(&Vector3::new(1.0f64, 1.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) )); assert!(Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(Vector3::new(1.0f64, 1.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
assert!(Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(&Vector3::new(5.0f64, 5.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) )); assert!(Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(Vector3::new(5.0f64, 5.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
assert!(Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(&Vector3::new(1.0f64, -1.0f64, 0.0f64)).approx_eq( &rad(2.0f64 * f64::consts::FRAC_PI_3) )); assert!(Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(Vector3::new(1.0f64, -1.0f64, 0.0f64)).approx_eq( &rad(2.0f64 * f64::consts::FRAC_PI_3) ));
assert!(Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) )); assert!(Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
assert!(Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) )); assert!(Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
assert!(Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) )); assert!(Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
} }
#[test] #[test]