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-08 08:17:36 +00:00
|
|
|
use std::cast;
|
|
|
|
|
2013-07-11 01:45:21 +00:00
|
|
|
use core::{Vec2, Vec3, Quat};
|
2013-06-16 07:34:09 +00:00
|
|
|
|
|
|
|
/// A geometric point
|
2013-07-11 02:19:29 +00:00
|
|
|
pub trait Point<T, Vec, Rot>: Eq
|
|
|
|
+ Add<Vec, Self>
|
|
|
|
+ Sub<Self, Vec>
|
|
|
|
+ Mul<Vec, Self>
|
|
|
|
+ ApproxEq<T>
|
|
|
|
+ ToStr {
|
2013-07-11 01:45:21 +00:00
|
|
|
pub fn as_vec<'a>(&'a self) -> &'a Vec;
|
|
|
|
pub fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec;
|
2013-07-08 08:17:36 +00:00
|
|
|
|
2013-07-11 01:45:21 +00:00
|
|
|
pub fn translate(&self, offset: &Vec) -> Self;
|
|
|
|
pub fn rotate(&self, rotation: &Rot) -> Self;
|
2013-07-11 02:19:29 +00:00
|
|
|
pub fn scale(&self, factor: &Vec) -> Self;
|
|
|
|
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-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A two-dimensional point
|
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
|
|
|
|
|
|
|
impl<T> Point2<T> {
|
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-08 08:17:36 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_vec(vec: Vec2<T>) -> Point2<T> {
|
|
|
|
unsafe { cast::transmute(vec) }
|
|
|
|
}
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
2013-07-08 08:17:36 +00:00
|
|
|
|
2013-07-11 02:19:29 +00:00
|
|
|
impl<T:Clone + Float> Point<T, Vec2<T>, T> for Point2<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
#[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]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn translate(&self, offset: &Vec2<T>) -> Point2<T> {
|
2013-07-11 02:19:29 +00:00
|
|
|
(*self) + (*offset)
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn rotate(&self, radians: &T) -> Point2<T> {
|
2013-07-11 02:19:29 +00:00
|
|
|
Point2::new((*self).x.cos() * (*radians),
|
|
|
|
(*self).y.sin() * (*radians))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn scale(&self, factor: &Vec2<T>) -> Point2<T> {
|
|
|
|
(*self) * (*factor)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn distance2(&self, other: &Point2<T>) -> T {
|
|
|
|
((*other) - (*self)).length2()
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn direction(&self, other: &Point2<T>) -> Vec2<T> {
|
|
|
|
((*other) - (*self)).normalize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Add<Vec2<T>, Point2<T>> for Point2<T> {
|
|
|
|
fn add(&self, other: &Vec2<T>) -> Point2<T> {
|
|
|
|
Point2::new((*self).x + (*other).x,
|
|
|
|
(*self).y + (*other).y)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Sub<Point2<T>, Vec2<T>> for Point2<T> {
|
|
|
|
fn sub(&self, other: &Point2<T>) -> Vec2<T> {
|
|
|
|
Vec2::new((*self).x - (*other).x,
|
|
|
|
(*self).y - (*other).y)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Mul<Vec2<T>, Point2<T>> for Point2<T> {
|
|
|
|
fn mul(&self, scale: &Vec2<T>) -> Point2<T> {
|
|
|
|
Point2::new((*self).x * (*scale).x,
|
|
|
|
(*self).y * (*scale).y)
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point2<T> {
|
|
|
|
#[inline]
|
|
|
|
pub fn approx_epsilon() -> T {
|
|
|
|
ApproxEq::approx_epsilon::<T,T>()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn approx_eq(&self, other: &Point2<T>) -> bool {
|
|
|
|
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn approx_eq_eps(&self, other: &Point2<T>, epsilon: &T) -> bool {
|
2013-07-08 08:17:36 +00:00
|
|
|
self.x.approx_eq_eps(&other.x, epsilon) &&
|
|
|
|
self.y.approx_eq_eps(&other.y, epsilon)
|
2013-07-08 07:00:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
use geom::point::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_to_str() {
|
|
|
|
assert_eq!(Point2::new(1, 2).to_str(), ~"[1, 2]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-16 07:34:09 +00:00
|
|
|
/// A three-dimensional point
|
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
|
|
|
|
|
|
|
impl<T> Point3<T> {
|
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-08 08:17:36 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_vec(vec: Vec3<T>) -> Point3<T> {
|
|
|
|
unsafe { cast::transmute(vec) }
|
|
|
|
}
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
2013-07-08 08:17:36 +00:00
|
|
|
|
2013-07-11 02:19:29 +00:00
|
|
|
impl<T:Clone + Float> Point<T, Vec3<T>, Quat<T>> for Point3<T> {
|
2013-07-08 08:17:36 +00:00
|
|
|
#[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]
|
2013-06-16 07:34:09 +00:00
|
|
|
pub fn translate(&self, offset: &Vec3<T>) -> Point3<T> {
|
2013-07-11 02:19:29 +00:00
|
|
|
(*self) + (*offset)
|
2013-07-11 01:45:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn rotate(&self, rotation: &Quat<T>) -> Point3<T> {
|
|
|
|
Point3::from_vec(rotation.mul_v(self.as_vec()))
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-11 02:19:29 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn scale(&self, factor: &Vec3<T>) -> Point3<T> {
|
|
|
|
(*self) * (*factor)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn distance2(&self, other: &Point3<T>) -> T {
|
|
|
|
((*other) - (*self)).length2()
|
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn direction(&self, other: &Point3<T>) -> Vec3<T> {
|
|
|
|
((*other) - (*self)).normalize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Add<Vec3<T>, Point3<T>> for Point3<T> {
|
|
|
|
fn add(&self, other: &Vec3<T>) -> Point3<T> {
|
|
|
|
Point3::new((*self).x + (*other).x,
|
|
|
|
(*self).y + (*other).y,
|
|
|
|
(*self).z + (*other).z)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Sub<Point3<T>, Vec3<T>> for Point3<T> {
|
|
|
|
fn sub(&self, other: &Point3<T>) -> Vec3<T> {
|
|
|
|
Vec3::new((*self).x - (*other).x,
|
|
|
|
(*self).y - (*other).y,
|
|
|
|
(*self).z - (*other).z)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Num> Mul<Vec3<T>, Point3<T>> for Point3<T> {
|
|
|
|
fn mul(&self, scale: &Vec3<T>) -> Point3<T> {
|
|
|
|
Point3::new((*self).x * (*scale).x,
|
|
|
|
(*self).y * (*scale).y,
|
|
|
|
(*self).z * (*scale).z)
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
impl<T:Clone + Eq + ApproxEq<T>> ApproxEq<T> for Point3<T> {
|
|
|
|
#[inline]
|
|
|
|
pub fn approx_epsilon() -> T {
|
|
|
|
ApproxEq::approx_epsilon::<T,T>()
|
2013-06-16 07:34:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn approx_eq(&self, other: &Point3<T>) -> bool {
|
|
|
|
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<T,T>())
|
|
|
|
}
|
2013-06-16 07:34:09 +00:00
|
|
|
|
2013-07-08 07:00:38 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn approx_eq_eps(&self, other: &Point3<T>, epsilon: &T) -> bool {
|
2013-07-08 08:17:36 +00:00
|
|
|
self.x.approx_eq_eps(&other.x, epsilon) &&
|
|
|
|
self.y.approx_eq_eps(&other.y, epsilon) &&
|
|
|
|
self.z.approx_eq_eps(&other.z, epsilon)
|
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-08 07:00:38 +00:00
|
|
|
use geom::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]");
|
|
|
|
}
|
|
|
|
}
|