diff --git a/src/lib.rs b/src/lib.rs index 4b285f3c..dd1f2f42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,7 +72,6 @@ pub use matrix4d::{Matrix4D, TypedMatrix4D}; pub use point::{ Point2D, TypedPoint2D, Point3D, TypedPoint3D, - Point4D, TypedPoint4D, }; pub use vector::{ Vector2D, TypedVector2D, diff --git a/src/point.rs b/src/point.rs index a738baed..a4f35e27 100644 --- a/src/point.rs +++ b/src/point.rs @@ -12,10 +12,11 @@ use approxeq::ApproxEq; use length::Length; use scale_factor::ScaleFactor; use size::TypedSize2D; +use vector::{TypedVector2D, TypedVector3D}; use num::*; use num_traits::{Float, NumCast}; use std::fmt; -use std::ops::{Add, Neg, Mul, Sub, Div}; +use std::ops::{Add, Mul, Sub, Div, AddAssign, SubAssign, MulAssign, DivAssign}; use std::marker::PhantomData; define_matrix! { @@ -38,6 +39,12 @@ impl TypedPoint2D { pub fn zero() -> TypedPoint2D { TypedPoint2D::new(Zero::zero(), Zero::zero()) } + + /// Promotes this point to a 3d point. + #[inline] + pub fn to_3d(&self) -> TypedVector3D { + TypedVector3D::new(self.x, self.y, Zero::zero()) + } } impl fmt::Debug for TypedPoint2D { @@ -73,6 +80,14 @@ impl TypedPoint2D { #[inline] pub fn y_typed(&self) -> Length { Length::new(self.y) } + /// Casts this point into a vector. + /// + /// This is equivalent to *self - TypedPoint2D::zero(). + #[inline] + pub fn to_vector(&self) -> TypedVector2D { + TypedVector2D::new(self.x, self.y) + } + /// Drop the units, preserving only the numeric value. #[inline] pub fn to_untyped(&self) -> Point2D { @@ -91,24 +106,9 @@ impl TypedPoint2D { } } -impl TypedPoint2D -where T: Copy + Mul + Add + Sub { - /// Dot product. - #[inline] - pub fn dot(self, other: TypedPoint2D) -> T { - self.x * other.x + self.y * other.y - } - - /// Returns the norm of the cross product [self.x, self.y, 0] x [other.x, other.y, 0].. - #[inline] - pub fn cross(self, other: TypedPoint2D) -> T { - self.x * other.y - self.y * other.x - } -} - -impl, U> Add for TypedPoint2D { +impl, U> Add> for TypedPoint2D { type Output = TypedPoint2D; - fn add(self, other: TypedPoint2D) -> TypedPoint2D { + fn add(self, other: TypedVector2D) -> TypedPoint2D { TypedPoint2D::new(self.x + other.x, self.y + other.y) } } @@ -127,20 +127,41 @@ impl, U> TypedPoint2D { } impl, U> Sub for TypedPoint2D { - type Output = TypedPoint2D; - fn sub(self, other: TypedPoint2D) -> TypedPoint2D { - TypedPoint2D::new(self.x - other.x, self.y - other.y) + type Output = TypedVector2D; + fn sub(self, other: TypedPoint2D) -> TypedVector2D { + TypedVector2D::new(self.x - other.x, self.y - other.y) } } -impl , U> Neg for TypedPoint2D { - type Output = TypedPoint2D; - #[inline] - fn neg(self) -> TypedPoint2D { - TypedPoint2D::new(-self.x, -self.y) +impl AddAssign> for TypedPoint2D { + fn add_assign(&mut self, other: TypedVector2D) { + self.x += other.x; + self.y += other.y; } } +impl SubAssign> for TypedPoint2D { + fn sub_assign(&mut self, other: TypedVector2D) { + self.x -= other.x; + self.y -= other.y; + } +} + +impl MulAssign for TypedPoint2D { + fn mul_assign(&mut self, other: T) { + self.x *= other; + self.y *= other; + } +} + +impl DivAssign for TypedPoint2D { + fn div_assign(&mut self, other: T) { + self.x /= other; + self.y /= other; + } +} + + impl TypedPoint2D { pub fn min(self, other: TypedPoint2D) -> TypedPoint2D { TypedPoint2D::new(self.x.min(other.x), self.y.min(other.y)) @@ -341,6 +362,14 @@ impl TypedPoint3D { #[inline] pub fn to_array(&self) -> [T; 3] { [self.x, self.y, self.z] } + /// Casts this point into a vector. + /// + /// This is equivalent to *self - TypedPoint3D::zero(). + #[inline] + pub fn to_vector(&self) -> TypedVector3D { + TypedVector3D::new(self.x, self.y, self.z) + } + /// Drop the units, preserving only the numeric value. #[inline] pub fn to_untyped(&self) -> Point3D { @@ -354,51 +383,67 @@ impl TypedPoint3D { } } -impl + - Add + - Sub + - Copy, U> TypedPoint3D { - - // Dot product. +impl TypedPoint3D { #[inline] - pub fn dot(self, other: TypedPoint3D) -> T { - self.x * other.x + - self.y * other.y + - self.z * other.z - } - - // Cross product. - #[inline] - pub fn cross(self, other: TypedPoint3D) -> TypedPoint3D { - TypedPoint3D::new(self.y * other.z - self.z * other.y, - self.z * other.x - self.x * other.z, - self.x * other.y - self.y * other.x) - } + pub fn to_array4d(&self) -> [T; 4] { [self.x, self.y, self.z, One::one()] } } -impl, U> Add for TypedPoint3D { +impl, U> Add> for TypedPoint3D { type Output = TypedPoint3D; - fn add(self, other: TypedPoint3D) -> TypedPoint3D { + fn add(self, other: TypedVector3D) -> TypedPoint3D { TypedPoint3D::new(self.x + other.x, self.y + other.y, self.z + other.z) } } -impl, U> Sub for TypedPoint3D { +impl AddAssign> for TypedPoint3D { + fn add_assign(&mut self, other: TypedVector3D) { + self.x += other.x; + self.y += other.y; + self.z += other.z; + } +} + +impl SubAssign> for TypedPoint3D { + fn sub_assign(&mut self, other: TypedVector3D) { + self.x -= other.x; + self.y -= other.y; + self.z -= other.z; + } +} + +impl MulAssign for TypedPoint3D { + fn mul_assign(&mut self, other: T) { + self.x *= other; + self.y *= other; + self.z *= other; + } +} + +impl DivAssign for TypedPoint3D { + fn div_assign(&mut self, other: T) { + self.x /= other; + self.y /= other; + self.z /= other; + } +} + +impl, U> Sub> for TypedPoint3D { type Output = TypedPoint3D; - fn sub(self, other: TypedPoint3D) -> TypedPoint3D { + fn sub(self, other: TypedVector3D) -> TypedPoint3D { TypedPoint3D::new(self.x - other.x, self.y - other.y, self.z - other.z) } } -impl , U> Neg for TypedPoint3D { - type Output = TypedPoint3D; - #[inline] - fn neg(self) -> TypedPoint3D { - TypedPoint3D::new(-self.x, -self.y, -self.z) +impl, U> Sub for TypedPoint3D { + type Output = TypedVector3D; + fn sub(self, other: TypedPoint3D) -> TypedVector3D { + TypedVector3D::new(self.x - other.x, + self.y - other.y, + self.z - other.z) } } @@ -633,14 +678,6 @@ impl, U> Sub for TypedPoint4D { } } -impl , U> Neg for TypedPoint4D { - type Output = TypedPoint4D; - #[inline] - fn neg(self) -> TypedPoint4D { - TypedPoint4D::new(-self.x, -self.y, -self.z, -self.w) - } -} - impl TypedPoint4D { pub fn min(self, other: TypedPoint4D) -> TypedPoint4D { TypedPoint4D::new(self.x.min(other.x), self.y.min(other.y), @@ -761,21 +798,6 @@ mod point2d { assert_eq!(result, Point2D::new(15.0, 25.0)); } - #[test] - pub fn test_dot() { - let p1: Point2D = Point2D::new(2.0, 7.0); - let p2: Point2D = Point2D::new(13.0, 11.0); - assert_eq!(p1.dot(p2), 103.0); - } - - #[test] - pub fn test_cross() { - let p1: Point2D = Point2D::new(4.0, 7.0); - let p2: Point2D = Point2D::new(13.0, 8.0); - let r = p1.cross(p2); - assert_eq!(r, -59.0); - } - #[test] pub fn test_min() { let p1 = Point2D::new(1.0, 3.0); @@ -800,20 +822,22 @@ mod point2d { #[cfg(test)] mod typedpoint2d { use super::TypedPoint2D; + use vector::TypedVector2D; use scale_factor::ScaleFactor; pub enum Mm {} pub enum Cm {} pub type Point2DMm = TypedPoint2D; + pub type Vec2DMm = TypedVector2D; pub type Point2DCm = TypedPoint2D; #[test] pub fn test_add() { - let p1 = Point2DMm::new(1.0, 2.0); - let p2 = Point2DMm::new(3.0, 4.0); + let p = Point2DMm::new(1.0, 2.0); + let v = Vec2DMm::new(3.0, 4.0); - let result = p1 + p2; + let result = p + v; assert_eq!(result, Point2DMm::new(4.0, 6.0)); } @@ -833,21 +857,6 @@ mod typedpoint2d { mod point3d { use super::Point3D; - #[test] - pub fn test_dot() { - let p1 = Point3D::new(7.0, 21.0, 32.0); - let p2 = Point3D::new(43.0, 5.0, 16.0); - assert_eq!(p1.dot(p2), 918.0); - } - - #[test] - pub fn test_cross() { - let p1 = Point3D::new(4.0, 7.0, 9.0); - let p2 = Point3D::new(13.0, 8.0, 3.0); - let p3 = p1.cross(p2); - assert_eq!(p3, Point3D::new(-51.0, 105.0, -59.0)); - } - #[test] pub fn test_min() { let p1 = Point3D::new(1.0, 3.0, 5.0); @@ -873,26 +882,6 @@ mod point3d { mod point4d { use super::Point4D; - #[test] - pub fn test_add() { - let p1 = Point4D::new(7.0, 21.0, 32.0, 1.0); - let p2 = Point4D::new(43.0, 5.0, 16.0, 2.0); - - let result = p1 + p2; - - assert_eq!(result, Point4D::new(50.0, 26.0, 48.0, 3.0)); - } - - #[test] - pub fn test_sub() { - let p1 = Point4D::new(7.0, 21.0, 32.0, 1.0); - let p2 = Point4D::new(43.0, 5.0, 16.0, 2.0); - - let result = p1 - p2; - - assert_eq!(result, Point4D::new(-36.0, 16.0, 16.0, -1.0)); - } - #[test] pub fn test_min() { let p1 = Point4D::new(1.0, 3.0, 5.0, 7.0); diff --git a/src/rect.rs b/src/rect.rs index 094729f7..12506e4e 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -13,6 +13,7 @@ use scale_factor::ScaleFactor; use num::*; use point::TypedPoint2D; use size::TypedSize2D; +use vector::TypedVector2D; use heapsize::HeapSizeOf; use num_traits::NumCast; @@ -157,9 +158,9 @@ where T: Copy + Clone + Zero + PartialOrd + PartialEq + Add + Sub) -> TypedRect { + pub fn translated(&self, other: &TypedVector2D) -> TypedRect { TypedRect::new( - TypedPoint2D::new(self.origin.x + other.x, self.origin.y + other.y), + self.origin + *other, self.size ) } @@ -212,8 +213,8 @@ where T: Copy + Clone + Zero + PartialOrd + PartialEq + Add + Sub) -> TypedRect { - self.translate(&TypedPoint2D::new(size.width, size.height)) + pub fn translated_by_size(&self, size: &TypedSize2D) -> TypedRect { + self.translated(&size.to_vector()) } } @@ -406,6 +407,7 @@ impl TypedRect { #[cfg(test)] mod tests { use point::Point2D; + use vector::Vector2D; use size::Size2D; use super::*; @@ -421,7 +423,7 @@ mod tests { #[test] fn test_translate() { let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - let pp = p.translate(&Point2D::new(10,15)); + let pp = p.translated(&Vector2D::new(10,15)); assert!(pp.size.width == 50); assert!(pp.size.height == 40); @@ -430,7 +432,7 @@ mod tests { let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - let rr = r.translate(&Point2D::new(0,-10)); + let rr = r.translated(&Vector2D::new(0,-10)); assert!(rr.size.width == 50); assert!(rr.size.height == 40); @@ -441,7 +443,7 @@ mod tests { #[test] fn test_translate_by_size() { let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - let pp = p.translate_by_size(&Size2D::new(10,15)); + let pp = p.translated_by_size(&Size2D::new(10,15)); assert!(pp.size.width == 50); assert!(pp.size.height == 40); @@ -450,7 +452,7 @@ mod tests { let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - let rr = r.translate_by_size(&Size2D::new(0,-10)); + let rr = r.translated_by_size(&Size2D::new(0,-10)); assert!(rr.size.width == 50); assert!(rr.size.height == 40); @@ -533,10 +535,10 @@ mod tests { let r = Rect::new(Point2D::new(-20.0, 15.0), Size2D::new(100.0, 200.0)); assert!(r.contains_rect(&r)); - assert!(!r.contains_rect(&r.translate(&Point2D::new( 0.1, 0.0)))); - assert!(!r.contains_rect(&r.translate(&Point2D::new(-0.1, 0.0)))); - assert!(!r.contains_rect(&r.translate(&Point2D::new( 0.0, 0.1)))); - assert!(!r.contains_rect(&r.translate(&Point2D::new( 0.0, -0.1)))); + assert!(!r.contains_rect(&r.translated(&Vector2D::new( 0.1, 0.0)))); + assert!(!r.contains_rect(&r.translated(&Vector2D::new(-0.1, 0.0)))); + assert!(!r.contains_rect(&r.translated(&Vector2D::new( 0.0, 0.1)))); + assert!(!r.contains_rect(&r.translated(&Vector2D::new( 0.0, -0.1)))); // Empty rectangles are always considered as contained in other rectangles, // even if their origin is not. let p = Point2D::new(1.0, 1.0); diff --git a/src/size.rs b/src/size.rs index 7693267e..368fd19c 100644 --- a/src/size.rs +++ b/src/size.rs @@ -10,6 +10,7 @@ use super::UnknownUnit; use length::Length; use scale_factor::ScaleFactor; +use vector::TypedVector2D; use num::*; use num_traits::NumCast; @@ -168,6 +169,9 @@ impl TypedSize2D { #[inline] pub fn to_array(&self) -> [T; 2] { [self.width, self.height] } + #[inline] + pub fn to_vector(&self) -> TypedVector2D { TypedVector2D::new(self.width, self.height) } + /// Drop the units, preserving only the numeric value. pub fn to_untyped(&self) -> Size2D { TypedSize2D::new(self.width, self.height)