2013-06-16 07:34:09 +00:00
|
|
|
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
|
|
|
|
// refer to the AUTHORS file at the top-level directory of this distribution.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2013-07-11 04:59:18 +00:00
|
|
|
//! Coordinate vectors for positional data
|
|
|
|
//!
|
|
|
|
//! These types differ from the vector types implemented in `core::vec` because
|
|
|
|
//! they describe coordinates in geometric space and not a magnitude and a
|
|
|
|
//! direction. All positional data throughout the library uses these point
|
|
|
|
//! types, which allows for a clear, self-documenting API.
|
|
|
|
|
2013-07-08 08:17:36 +00:00
|
|
|
use std::cast;
|
|
|
|
|
2013-07-14 03:22:45 +00:00
|
|
|
use math::{Dimensioned, SwapComponents};
|
2013-07-14 01:44:50 +00:00
|
|
|
use math::{Ray2, Ray3};
|
|
|
|
use math::{Vec2, ToVec2, AsVec2};
|
|
|
|
use math::{Vec3, ToVec3, AsVec3};
|
|
|
|
use math::{Vec4, ToVec4};
|
2013-07-11 04:49:14 +00:00
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// A coordinate vector
|
2013-07-12 04:07:21 +00:00
|
|
|
pub trait Point<T, Vec, Ray>: Eq
|
|
|
|
+ Add<Vec, Self>
|
|
|
|
+ Sub<Self, Vec>
|
|
|
|
+ Mul<Vec, Self>
|
|
|
|
+ ApproxEq<T>
|
|
|
|
+ ToStr {
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn translate_v(&self, offset: &Vec) -> Self;
|
|
|
|
pub fn scale_s(&self, factor: T) -> Self;
|
|
|
|
pub fn scale_v(&self, factor: &Vec) -> Self;
|
|
|
|
pub fn displacement(&self, other: &Self) -> Vec;
|
2013-07-11 02:19:29 +00:00
|
|
|
pub fn distance2(&self, other: &Self) -> T;
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn distance(&self, other: &Self) -> T;
|
2013-07-11 02:19:29 +00:00
|
|
|
pub fn direction(&self, other: &Self) -> Vec;
|
2013-07-12 04:07:21 +00:00
|
|
|
pub fn ray_to(&self, other: &Self) -> Ray;
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// A two-dimensional coordinate vector
|
2013-06-29 06:38:55 +00:00
|
|
|
#[deriving(Clone, Eq)]
|
2013-07-08 08:17:36 +00:00
|
|
|
pub struct Point2<T> { x: T, y: T }
|
2013-06-16 07:34:09 +00:00
|
|
|
|
2013-07-14 03:22:45 +00:00
|
|
|
impl_dimensioned!(Point2, T, 2)
|
2013-07-12 09:10:39 +00:00
|
|
|
impl_to_vec!(Point2, 2)
|
|
|
|
impl_as_vec!(Point2, 2)
|
2013-07-14 03:22:45 +00:00
|
|
|
impl_swap_components!(Point2)
|
2013-07-12 01:22:14 +00:00
|
|
|
impl_approx!(Point2 { x, y })
|
|
|
|
|
2013-07-12 06:36:36 +00:00
|
|
|
pub trait AsPoint2<T> {
|
|
|
|
pub fn as_point2<'a>(&'a self) -> &'a Point2<T>;
|
|
|
|
pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2<T>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Clone + Num> AsPoint2<T> for Vec2<T> {
|
|
|
|
#[inline]
|
|
|
|
pub fn as_point2<'a>(&'a self) -> &'a Point2<T> {
|
|
|
|
unsafe { cast::transmute(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn as_mut_point2<'a>(&'a mut self) -> &'a mut Point2<T> {
|
|
|
|
unsafe { cast::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 04:49:14 +00:00
|
|
|
impl<T:Num> Point2<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Creates a new point from three coordinates.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn new(x: T, y: T) -> Point2<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
Point2 { x: x, y: y }
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Converts a vector to a point.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-07-12 03:41:03 +00:00
|
|
|
pub fn from_vec2(vec: Vec2<T>) -> Point2<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
unsafe { cast::transmute(vec) }
|
|
|
|
}
|
2013-07-11 04:49:14 +00:00
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// The coordinate [0, 0].
|
2013-07-11 04:49:14 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn origin() -> Point2<T> {
|
|
|
|
Point2::new(zero!(T), zero!(T))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-12 03:41:03 +00:00
|
|
|
impl<T:Clone + Num> ToVec3<T> for Point2<T> {
|
2013-07-11 05:14:32 +00:00
|
|
|
/// Converts the point to a three-dimensional homogeneous vector:
|
|
|
|
/// `[x, y] -> [x, y, 1]`
|
|
|
|
#[inline]
|
|
|
|
pub fn to_vec3(&self) -> Vec3<T> {
|
2013-07-13 14:55:46 +00:00
|
|
|
Vec3::new(self.x.clone(),
|
|
|
|
self.y.clone(),
|
2013-07-11 05:14:32 +00:00
|
|
|
one!(T))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Point<T, Vec2<T>, Ray2<T>> for Point2<T> {
|
|
|
|
/// Applies a displacement vector to the point.
|
2013-07-11 04:49:14 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn translate_v(&self, offset: &Vec2<T>) -> Point2<T> {
|
|
|
|
Point2::new(self.x + offset.x,
|
|
|
|
self.y + offset.y)
|
2013-07-11 04:49:14 +00:00
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
/// Scales the distance from the point to the origin by a scalar value.
|
2013-07-11 04:49:14 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn scale_s(&self, factor: T) -> Point2<T> {
|
|
|
|
Point2::new(self.x * factor,
|
|
|
|
self.y * factor)
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Scales the distance from the point to the origin using the components
|
|
|
|
/// of a vector.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn scale_v(&self, factor: &Vec2<T>) -> Point2<T> {
|
|
|
|
Point2::new(self.x * factor.x,
|
|
|
|
self.y * factor.y)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculates the displacement required to move the point to `other`.
|
|
|
|
pub fn displacement(&self, other: &Point2<T>) -> Vec2<T> {
|
|
|
|
Vec2::new(self.x - other.x,
|
|
|
|
self.y - other.y)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns the squared distance from the point to `other`. This does not
|
|
|
|
/// perform a square root operation like in the `distance` method and can
|
|
|
|
/// therefore be more efficient for distance comparisons where the actual
|
|
|
|
/// distance is not needed.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn distance2(&self, other: &Point2<T>) -> T {
|
2013-07-12 03:42:28 +00:00
|
|
|
((*other) - (*self)).magnitude2()
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns the scalar distance to the other point.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn distance(&self, other: &Point2<T>) -> T {
|
2013-07-11 02:19:29 +00:00
|
|
|
other.distance2(self).sqrt()
|
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns a normalized direction vector pointing to the other point.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn direction(&self, other: &Point2<T>) -> Vec2<T> {
|
|
|
|
((*other) - (*self)).normalize()
|
|
|
|
}
|
2013-07-12 04:07:21 +00:00
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Projects a normalized ray towards the other point.
|
2013-07-12 04:07:21 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn ray_to(&self, other: &Point2<T>) -> Ray2<T> {
|
|
|
|
Ray2::new(self.clone(), self.direction(other))
|
|
|
|
}
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Add<Vec2<T>, Point2<T>> for Point2<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Applies a displacement vector to the point.
|
|
|
|
fn add(&self, offset: &Vec2<T>) -> Point2<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.translate_v(offset)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Sub<Point2<T>, Vec2<T>> for Point2<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Calculates the displacement vector from the point to `other`.
|
2013-07-11 02:19:29 +00:00
|
|
|
fn sub(&self, other: &Point2<T>) -> Vec2<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.displacement(other)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Mul<Vec2<T>, Point2<T>> for Point2<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Scales the distance from the point to the origin using the components
|
|
|
|
/// of a vector.
|
|
|
|
fn mul(&self, factor: &Vec2<T>) -> Point2<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.scale_v(factor)
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ToStr for Point2<T> {
|
|
|
|
pub fn to_str(&self) -> ~str {
|
|
|
|
fmt!("[%?, %?]", self.x, self.y)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test_point2 {
|
2013-07-14 01:44:50 +00:00
|
|
|
use math::point::*;
|
2013-07-08 07:00:38 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_to_str() {
|
|
|
|
assert_eq!(Point2::new(1, 2).to_str(), ~"[1, 2]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// A three-dimensional coordinate vector
|
2013-06-29 06:38:55 +00:00
|
|
|
#[deriving(Clone, Eq)]
|
2013-07-08 08:17:36 +00:00
|
|
|
pub struct Point3<T> { x: T, y: T, z: T }
|
2013-06-16 07:34:09 +00:00
|
|
|
|
2013-07-14 03:22:45 +00:00
|
|
|
impl_dimensioned!(Point3, T, 3)
|
2013-07-12 09:10:39 +00:00
|
|
|
impl_to_vec!(Point3, 3)
|
|
|
|
impl_as_vec!(Point3, 3)
|
2013-07-14 03:22:45 +00:00
|
|
|
impl_swap_components!(Point3)
|
2013-07-12 01:22:14 +00:00
|
|
|
impl_approx!(Point3 { x, y, z })
|
|
|
|
|
2013-07-12 06:36:36 +00:00
|
|
|
pub trait AsPoint3<T> {
|
|
|
|
pub fn as_point3<'a>(&'a self) -> &'a Point3<T>;
|
|
|
|
pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3<T>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Clone + Num> AsPoint3<T> for Vec3<T> {
|
|
|
|
#[inline]
|
|
|
|
pub fn as_point3<'a>(&'a self) -> &'a Point3<T> {
|
|
|
|
unsafe { cast::transmute(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn as_mut_point3<'a>(&'a mut self) -> &'a mut Point3<T> {
|
|
|
|
unsafe { cast::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 04:49:14 +00:00
|
|
|
impl<T:Num> Point3<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Creates a new point from three coordinates.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn new(x: T, y: T, z: T) -> Point3<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
Point3 { x: x, y: y, z: z }
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Converts a vector to a point.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-07-12 03:41:03 +00:00
|
|
|
pub fn from_vec3(vec: Vec3<T>) -> Point3<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
unsafe { cast::transmute(vec) }
|
|
|
|
}
|
2013-07-11 04:49:14 +00:00
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// The coordinate [0, 0, 0].
|
2013-07-11 04:49:14 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn origin() -> Point3<T> {
|
|
|
|
Point3::new(zero!(T), zero!(T), zero!(T))
|
|
|
|
}
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
2013-07-08 08:17:36 +00:00
|
|
|
|
2013-07-12 03:41:03 +00:00
|
|
|
impl<T:Clone + Num> ToVec4<T> for Point3<T> {
|
2013-07-11 05:14:32 +00:00
|
|
|
/// Converts the point to a four-dimensional homogeneous vector:
|
|
|
|
/// `[x, y, z] -> [x, y, z, 1]`
|
|
|
|
#[inline]
|
|
|
|
pub fn to_vec4(&self) -> Vec4<T> {
|
2013-07-13 14:55:46 +00:00
|
|
|
Vec4::new(self.x.clone(),
|
|
|
|
self.y.clone(),
|
|
|
|
self.z.clone(),
|
2013-07-11 05:14:32 +00:00
|
|
|
one!(T))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Point<T, Vec3<T>, Ray3<T>> for Point3<T> {
|
|
|
|
/// Applies a displacement vector to the point.
|
2013-07-11 04:49:14 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn translate_v(&self, offset: &Vec3<T>) -> Point3<T> {
|
|
|
|
Point3::new(self.x + offset.x,
|
|
|
|
self.y + offset.y,
|
|
|
|
self.z + offset.z)
|
2013-07-11 04:49:14 +00:00
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
/// Scales the distance from the point to the origin by a scalar value.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn scale_s(&self, factor: T) -> Point3<T> {
|
|
|
|
Point3::new(self.x * factor,
|
|
|
|
self.y * factor,
|
|
|
|
self.z * factor)
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Scales the distance from the point to the origin using the components
|
|
|
|
/// of a vector.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
2013-07-21 05:11:25 +00:00
|
|
|
pub fn scale_v(&self, factor: &Vec3<T>) -> Point3<T> {
|
|
|
|
Point3::new(self.x * factor.x,
|
|
|
|
self.y * factor.y,
|
|
|
|
self.z * factor.z)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculates the displacement required to move the point to `other`.
|
|
|
|
pub fn displacement(&self, other: &Point3<T>) -> Vec3<T> {
|
|
|
|
Vec3::new(self.x - other.x,
|
|
|
|
self.y - other.y,
|
|
|
|
self.z - other.z)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns the squared distance from the point to `other`. This does not
|
|
|
|
/// perform a square root operation like in the `distance` method and can
|
|
|
|
/// therefore be more efficient for distance comparisons where the actual
|
|
|
|
/// distance is not needed.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn distance2(&self, other: &Point3<T>) -> T {
|
2013-07-12 03:42:28 +00:00
|
|
|
((*other) - (*self)).magnitude2()
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns the scalar distance to the other point.
|
2013-07-08 08:17:36 +00:00
|
|
|
#[inline]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn distance(&self, other: &Point3<T>) -> T {
|
2013-07-11 02:19:29 +00:00
|
|
|
other.distance2(self).sqrt()
|
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Returns a normalized direction vector pointing to the other point.
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn direction(&self, other: &Point3<T>) -> Vec3<T> {
|
|
|
|
((*other) - (*self)).normalize()
|
2013-07-12 04:07:21 +00:00
|
|
|
}
|
|
|
|
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Projects a normalized ray towards the other point.
|
2013-07-12 04:07:21 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn ray_to(&self, other: &Point3<T>) -> Ray3<T> {
|
|
|
|
Ray3::new(self.clone(), self.direction(other))
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Add<Vec3<T>, Point3<T>> for Point3<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Applies a displacement vector to the point
|
|
|
|
fn add(&self, offset: &Vec3<T>) -> Point3<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.translate_v(offset)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Sub<Point3<T>, Vec3<T>> for Point3<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Calculates the displacement required to move the point to `other`.
|
2013-07-11 02:19:29 +00:00
|
|
|
fn sub(&self, other: &Point3<T>) -> Vec3<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.displacement(other)
|
2013-07-11 02:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-21 05:11:25 +00:00
|
|
|
impl<T:Clone + Float> Mul<Vec3<T>, Point3<T>> for Point3<T> {
|
2013-07-14 04:43:29 +00:00
|
|
|
/// Scales the distance from the point to the origin using the components
|
|
|
|
/// of a vector.
|
|
|
|
fn mul(&self, factor: &Vec3<T>) -> Point3<T> {
|
2013-07-21 05:11:25 +00:00
|
|
|
self.scale_v(factor)
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
impl<T> ToStr for Point3<T> {
|
|
|
|
pub fn to_str(&self) -> ~str {
|
|
|
|
fmt!("[%?, %?, %?]", self.x, self.y, self.z)
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test_point3 {
|
2013-07-14 01:44:50 +00:00
|
|
|
use math::point::*;
|
2013-06-16 07:34:09 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_to_str() {
|
|
|
|
assert_eq!(Point3::new(1, 2, 3).to_str(), ~"[1, 2, 3]");
|
|
|
|
}
|
|
|
|
}
|