Make point into standalone struct as opposed to a newtype struct
This commit is contained in:
parent
5b5d1f38b3
commit
a5d4fc1ed4
5 changed files with 83 additions and 36 deletions
|
@ -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;
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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)) }
|
||||||
|
|
Loading…
Reference in a new issue