Make point into standalone struct as opposed to a newtype struct

This commit is contained in:
Brendan Zabarauskas 2013-07-08 18:17:36 +10:00
parent 5b5d1f38b3
commit a5d4fc1ed4
5 changed files with 83 additions and 36 deletions

View file

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
pub use self::plane::Plane; pub use self::plane::Plane;
pub use self::point::{Point2, Point3}; pub use self::point::{Point, Point2, Point3};
pub use self::ray::Ray3; pub use self::ray::Ray3;
pub mod plane; pub mod plane;

View file

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
use core::{Vec3, Vec4, Mat3}; use core::{Vec3, Vec4, Mat3};
use geom::{Point3, Ray3}; use geom::{Point, Point3, Ray3};
#[path = "../num_macros.rs"] #[path = "../num_macros.rs"]
mod num_macros; mod num_macros;
@ -34,7 +34,7 @@ pub struct Plane<T> {
dist: T, dist: T,
} }
impl<T:Clone + Real> Plane<T> { impl<T:Clone + Float> Plane<T> {
/// # Arguments /// # Arguments
/// ///
/// - `a`: the `x` component of the normal /// - `a`: the `x` component of the normal
@ -60,7 +60,7 @@ impl<T:Clone + Real> Plane<T> {
/// Compute the distance from the plane to the point /// Compute the distance from the plane to the point
pub fn distance(&self, pos: &Point3<T>) -> T { pub fn distance(&self, pos: &Point3<T>) -> T {
self.norm.dot(&**pos) + self.dist self.norm.dot(pos.as_vec()) + self.dist
} }
/// Computes the point at which `ray` intersects the plane /// Computes the point at which `ray` intersects the plane
@ -79,14 +79,14 @@ impl<T:Clone + Real> Plane<T> {
} }
} }
impl<T:Clone + Real + ApproxEq<T>> Plane<T> { impl<T:Clone + Float> Plane<T> {
/// Constructs a plane that passes through the the three points `a`, `b` and `c` /// Constructs a plane that passes through the the three points `a`, `b` and `c`
pub fn from_3p(a: Point3<T>, pub fn from_3p(a: Point3<T>,
b: Point3<T>, b: Point3<T>,
c: Point3<T>) -> Option<Plane<T>> { c: Point3<T>) -> Option<Plane<T>> {
// create two vectors that run parallel to the plane // create two vectors that run parallel to the plane
let v0 = (*b).sub_v(&*a); let v0 = b.as_vec().sub_v(a.as_vec());
let v1 = (*c).sub_v(&*a); let v1 = c.as_vec().sub_v(a.as_vec());
// find the vector that is perpendicular to v1 and v2 // find the vector that is perpendicular to v1 and v2
let mut norm = v0.cross(&v1); let mut norm = v0.cross(&v1);
@ -95,7 +95,7 @@ impl<T:Clone + Real + ApproxEq<T>> Plane<T> {
} else { } else {
// compute the normal and the distance to the plane // compute the normal and the distance to the plane
norm.normalize_self(); norm.normalize_self();
let dist = -a.dot(&norm); let dist = -a.as_vec().dot(&norm);
Some(Plane::from_nd(norm, dist)) Some(Plane::from_nd(norm, dist))
} }
@ -115,7 +115,7 @@ impl<T:Clone + Real + ApproxEq<T>> Plane<T> {
} else { } else {
// The end-point of the ray is at the three-plane intersection between // The end-point of the ray is at the three-plane intersection between
// `self`, `other`, and a tempory plane positioned at the origin // `self`, `other`, and a tempory plane positioned at the origin
do Plane::from_nd(ray_dir.clone(), zero!(T)).intersection_3pl(self, other).map |ray_pos| { do Plane::from_nd(ray_dir.clone(), zero!(T)).intersection_3pl(self, other).map |&ray_pos| {
Ray3 { Ray3 {
pos: ray_pos.clone(), pos: ray_pos.clone(),
dir: ray_dir.clone(), dir: ray_dir.clone(),
@ -136,9 +136,11 @@ impl<T:Clone + Real + ApproxEq<T>> Plane<T> {
self.norm.y.clone(), other_a.norm.y.clone(), other_b.norm.y.clone(), self.norm.y.clone(), other_a.norm.y.clone(), other_b.norm.y.clone(),
self.norm.z.clone(), other_a.norm.z.clone(), other_b.norm.z.clone()); self.norm.z.clone(), other_a.norm.z.clone(), other_b.norm.z.clone());
do mx.inverse().map |m| { do mx.inverse().map |m| {
Point3(m.mul_v(&Vec3::new(self.dist.clone(), Point::from_vec(
m.mul_v(&Vec3::new(self.dist.clone(),
other_a.dist.clone(), other_a.dist.clone(),
other_b.dist.clone()))) other_b.dist.clone()))
)
} }
} }
} }
@ -189,7 +191,7 @@ mod tests {
let p1 = Plane::from_abcd(0.0, -1.0, 0.0, 2.0); let p1 = Plane::from_abcd(0.0, -1.0, 0.0, 2.0);
let p2 = Plane::from_abcd(0.0, 0.0, 1.0, 1.0); let p2 = Plane::from_abcd(0.0, 0.0, 1.0, 1.0);
assert_eq!(p0.intersection_3pl(&p1, &p2).unwrap(), Point3::new(1.0, -2.0, 1.0)); assert_eq!(p0.intersection_3pl(&p1, &p2), Some(Point3::new(1.0, -2.0, 1.0)));
} }
#[test] #[test]

View file

@ -13,31 +13,55 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::cast;
use core::{Vec2, Vec3}; use core::{Vec2, Vec3};
/// A geometric point /// A geometric point
pub trait Point<T,V>: Eq + ApproxEq<T> + ToStr { pub trait Point<T,V>: Eq + ApproxEq<T> + ToStr {
pub fn from_vec(vec: V) -> Self;
pub fn as_vec<'a>(&'a self) -> &'a V;
pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut V;
pub fn translate(&self, offset: &V) -> Self; pub fn translate(&self, offset: &V) -> Self;
pub fn distance(&self, other: &Self) -> T; pub fn distance(&self, other: &Self) -> T;
} }
/// A two-dimensional point /// A two-dimensional point
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Point2<T>(Vec2<T>); pub struct Point2<T> { x: T, y: T }
impl<T> Point2<T> { impl<T> Point2<T> {
#[inline]
pub fn new(x: T, y: T) -> Point2<T> { pub fn new(x: T, y: T) -> Point2<T> {
Point2(Vec2::new(x, y)) Point2 { x: x, y: y }
} }
} }
impl<T:Clone + Real> Point<T,Vec2<T>> for Point2<T> { impl<T:Clone + Float> Point<T,Vec2<T>> for Point2<T> {
pub fn translate(&self, offset: &Vec2<T>) -> Point2<T> { #[inline]
Point2(self.add_v(offset)) pub fn from_vec(vec: Vec2<T>) -> Point2<T> {
unsafe { cast::transmute(vec) }
} }
#[inline]
pub fn as_vec<'a>(&'a self) -> &'a Vec2<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec2<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn translate(&self, offset: &Vec2<T>) -> Point2<T> {
Point::from_vec(self.as_vec().add_v(offset))
}
#[inline]
pub fn distance(&self, other: &Point2<T>) -> T { pub fn distance(&self, other: &Point2<T>) -> T {
(**self).distance(&**other) self.as_vec().distance(other.as_vec())
} }
} }
@ -54,7 +78,8 @@ impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point2<T> {
#[inline] #[inline]
pub fn approx_eq_eps(&self, other: &Point2<T>, epsilon: &T) -> bool { pub fn approx_eq_eps(&self, other: &Point2<T>, epsilon: &T) -> bool {
(**self).approx_eq_eps(&**other, epsilon) self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon)
} }
} }
@ -76,21 +101,39 @@ mod test_point2 {
/// A three-dimensional point /// A three-dimensional point
#[deriving(Clone, Eq)] #[deriving(Clone, Eq)]
pub struct Point3<T>(Vec3<T>); pub struct Point3<T> { x: T, y: T, z: T }
impl<T> Point3<T> { impl<T> Point3<T> {
#[inline]
pub fn new(x: T, y: T, z: T) -> Point3<T> { pub fn new(x: T, y: T, z: T) -> Point3<T> {
Point3(Vec3::new(x, y, z)) Point3 { x: x, y: y, z: z }
} }
} }
impl<T:Clone + Real> Point<T,Vec3<T>> for Point3<T> { impl<T:Clone + Float> Point<T,Vec3<T>> for Point3<T> {
pub fn translate(&self, offset: &Vec3<T>) -> Point3<T> { #[inline]
Point3(self.add_v(offset)) pub fn from_vec(vec: Vec3<T>) -> Point3<T> {
unsafe { cast::transmute(vec) }
} }
#[inline]
pub fn as_vec<'a>(&'a self) -> &'a Vec3<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec3<T> {
unsafe { cast::transmute(self) }
}
#[inline]
pub fn translate(&self, offset: &Vec3<T>) -> Point3<T> {
Point::from_vec(self.as_vec().add_v(offset))
}
#[inline]
pub fn distance(&self, other: &Point3<T>) -> T { pub fn distance(&self, other: &Point3<T>) -> T {
(**self).distance(&**other) self.as_vec().distance(other.as_vec())
} }
} }
@ -107,7 +150,9 @@ impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point3<T> {
#[inline] #[inline]
pub fn approx_eq_eps(&self, other: &Point3<T>, epsilon: &T) -> bool { pub fn approx_eq_eps(&self, other: &Point3<T>, epsilon: &T) -> bool {
(**self).approx_eq_eps(&**other, epsilon) self.x.approx_eq_eps(&other.x, epsilon) &&
self.y.approx_eq_eps(&other.y, epsilon) &&
self.z.approx_eq_eps(&other.z, epsilon)
} }
} }

View file

@ -41,7 +41,7 @@ pub struct FrustumPoints<T> {
far_bottom_right: Point3<T>, far_bottom_right: Point3<T>,
} }
impl<T:Clone + Real> Frustum<T> { impl<T:Clone + Float> Frustum<T> {
/// Constructs a frustum /// Constructs a frustum
pub fn from_planes(left: Plane<T>, right: Plane<T>, pub fn from_planes(left: Plane<T>, right: Plane<T>,
bottom: Plane<T>, top: Plane<T>, bottom: Plane<T>, top: Plane<T>,
@ -80,7 +80,7 @@ impl<T:Clone + Real> Frustum<T> {
} }
} }
impl<T:Clone + Real + ApproxEq<T>> Frustum<T> { impl<T:Clone + Float> Frustum<T> {
/// Computes where the frustum planes intersect to form corners and returns /// Computes where the frustum planes intersect to form corners and returns
/// a struct containing the eight resulting position vectors. /// a struct containing the eight resulting position vectors.
pub fn to_points(&self) -> FrustumPoints<T> { pub fn to_points(&self) -> FrustumPoints<T> {

View file

@ -28,7 +28,7 @@ mod num_macros;
/// This is the equivalent of the gluPerspective function, the algorithm of which /// This is the equivalent of the gluPerspective function, the algorithm of which
/// can be found [here](http://www.opengl.org/wiki/GluPerspective_code). /// can be found [here](http://www.opengl.org/wiki/GluPerspective_code).
/// ///
pub fn perspective<T:Clone + Real>(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4<T> { pub fn perspective<T:Clone + Float>(fovy: T, aspectRatio: T, near: T, far: T) -> Mat4<T> {
let ymax = near * (fovy / two!(T)).to_radians().tan(); let ymax = near * (fovy / two!(T)).to_radians().tan();
let xmax = ymax * aspectRatio; let xmax = ymax * aspectRatio;
@ -41,7 +41,7 @@ pub fn perspective<T:Clone + Real>(fovy: T, aspectRatio: T, near: T, far: T) ->
/// This is the equivalent of the now deprecated [glFrustrum] /// This is the equivalent of the now deprecated [glFrustrum]
/// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function. /// (http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) function.
/// ///
pub fn frustum<T:Clone + Real>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> { pub fn frustum<T:Clone + Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
let c0r0 = (two!(T) * near) / (right - left); let c0r0 = (two!(T) * near) / (right - left);
let c0r1 = zero!(T); let c0r1 = zero!(T);
let c0r2 = zero!(T); let c0r2 = zero!(T);
@ -74,7 +74,7 @@ pub fn frustum<T:Clone + Real>(left: T, right: T, bottom: T, top: T, near: T, fa
/// This is the equivalent of the now deprecated [glOrtho] /// This is the equivalent of the now deprecated [glOrtho]
/// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function. /// (http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) function.
/// ///
pub fn ortho<T:Clone + Real>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> { pub fn ortho<T:Clone + Float>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
let c0r0 = two!(T) / (right - left); let c0r0 = two!(T) / (right - left);
let c0r1 = zero!(T); let c0r1 = zero!(T);
let c0r2 = zero!(T); let c0r2 = zero!(T);
@ -116,7 +116,7 @@ pub struct PerspectiveFOV<T> {
far: T, far: T,
} }
impl<T:Clone + Real> PerspectiveFOV<T> { impl<T:Clone + Float> PerspectiveFOV<T> {
pub fn to_perspective(&self) -> Result<Perspective<T>, ~str> { pub fn to_perspective(&self) -> Result<Perspective<T>, ~str> {
do self.if_valid { do self.if_valid {
let angle = self.fovy / two!(T); let angle = self.fovy / two!(T);
@ -135,7 +135,7 @@ impl<T:Clone + Real> PerspectiveFOV<T> {
} }
} }
impl<T:Clone + Real> Projection<T> for PerspectiveFOV<T> { impl<T:Clone + Float> Projection<T> for PerspectiveFOV<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> { pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
let frac_pi_2: T = Real::frac_pi_2(); let frac_pi_2: T = Real::frac_pi_2();
cond! ( cond! (
@ -169,7 +169,7 @@ pub struct Perspective<T> {
far: T, far: T,
} }
impl<T:Clone + Real> Projection<T> for Perspective<T> { impl<T:Clone + Float> Projection<T> for Perspective<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> { pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
cond! ( cond! (
(self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) } (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) }
@ -275,7 +275,7 @@ pub struct Ortho<T> {
far: T, far: T,
} }
impl<T:Clone + Real> Projection<T> for Ortho<T> { impl<T:Clone + Float> Projection<T> for Ortho<T> {
pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> { pub fn if_valid<U:Clone>(&self, f: &fn() -> U) -> Result<U, ~str> {
cond! ( cond! (
(self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) } (self.left > self.right) { Err(fmt!("`left` cannot be greater than `right`, found: left: %? right: %?", self.left, self.right)) }