2014-05-26 17:10:04 +00:00
|
|
|
// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
|
2015-03-14 02:49:46 +00:00
|
|
|
// refer to the Cargo.toml file at the top-level directory of this distribution.
|
2013-08-26 05:08:25 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
//! Points are fixed positions in affine space with no length or direction. This
|
|
|
|
//! disinguishes them from vectors, which have a length and direction, but do
|
|
|
|
//! not have a fixed position.
|
|
|
|
|
2013-10-19 14:00:44 +00:00
|
|
|
use std::fmt;
|
2014-05-28 01:59:03 +00:00
|
|
|
use std::mem;
|
2015-01-03 21:29:26 +00:00
|
|
|
use std::ops::*;
|
2013-09-03 03:54:03 +00:00
|
|
|
|
2015-04-05 01:19:11 +00:00
|
|
|
use rust_num::{one, zero};
|
|
|
|
|
2014-05-28 01:59:03 +00:00
|
|
|
use approx::ApproxEq;
|
2015-09-20 15:32:53 +00:00
|
|
|
use array::Array1;
|
2015-03-13 08:32:23 +00:00
|
|
|
use bound::*;
|
2015-03-14 20:41:15 +00:00
|
|
|
use matrix::{Matrix, Matrix4};
|
2015-04-05 01:19:11 +00:00
|
|
|
use num::{BaseNum, BaseFloat};
|
2015-03-13 08:32:23 +00:00
|
|
|
use plane::Plane;
|
2013-09-03 03:54:03 +00:00
|
|
|
use vector::*;
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2013-09-03 06:37:06 +00:00
|
|
|
/// A point in 2-dimensional space.
|
2015-02-21 19:50:00 +00:00
|
|
|
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
|
2014-04-01 11:00:17 +00:00
|
|
|
pub struct Point2<S> { pub x: S, pub y: S }
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2013-11-07 02:08:37 +00:00
|
|
|
/// A point in 3-dimensional space.
|
2015-02-21 19:50:00 +00:00
|
|
|
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
|
2014-04-01 11:00:17 +00:00
|
|
|
pub struct Point3<S> { pub x: S, pub y: S, pub z: S }
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2013-09-03 13:36:03 +00:00
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseNum> Point2<S> {
|
2013-08-26 05:08:25 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn new(x: S, y: S) -> Point2<S> {
|
|
|
|
Point2 { x: x, y: y }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseNum> Point3<S> {
|
2013-08-26 05:08:25 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn new(x: S, y: S, z: S) -> Point3<S> {
|
|
|
|
Point3 { x: x, y: y, z: z }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-26 17:10:04 +00:00
|
|
|
impl<S: BaseNum> Point3<S> {
|
2013-11-01 14:32:29 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
pub fn from_homogeneous(v: &Vector4<S>) -> Point3<S> {
|
2013-11-09 01:15:51 +00:00
|
|
|
let e = v.truncate().mul_s(one::<S>() / v.w);
|
2014-07-29 18:06:31 +00:00
|
|
|
Point3::new(e.x, e.y, e.z) //FIXME
|
2013-11-01 14:32:29 +00:00
|
|
|
}
|
2013-11-02 13:11:13 +00:00
|
|
|
|
2013-11-01 14:32:29 +00:00
|
|
|
#[inline]
|
2014-04-14 01:30:24 +00:00
|
|
|
pub fn to_homogeneous(&self) -> Vector4<S> {
|
2014-07-29 18:06:31 +00:00
|
|
|
Vector4::new(self.x, self.y, self.z, one())
|
2013-11-01 14:32:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-03 06:37:06 +00:00
|
|
|
/// Specifies the numeric operations for point types.
|
2014-05-28 01:59:03 +00:00
|
|
|
pub trait Point<S: BaseNum, V: Vector<S>>: Array1<S> + Clone {
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Create a point at the origin.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn origin() -> Self;
|
2014-01-25 15:54:54 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Create a point from a vector.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn from_vec(v: &V) -> Self;
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Convert a point to a vector.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn to_vec(&self) -> V;
|
2013-11-02 13:11:13 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Multiply each component by a scalar, returning the new point.
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn mul_s(&self, s: S) -> Self;
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Divide each component by a scalar, returning the new point.
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn div_s(&self, s: S) -> Self;
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Subtract a scalar from each component, returning the new point.
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn rem_s(&self, s: S) -> Self;
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Add a vector to this point, returning the new point.
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn add_v(&self, v: &V) -> Self;
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Subtract another point from this one, returning a new vector.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn sub_p(&self, p: &Self) -> V;
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Multiply each component by a scalar, in-place.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn mul_self_s(&mut self, s: S);
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Divide each component by a scalar, in-place.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn div_self_s(&mut self, s: S);
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Take the remainder of each component by a scalar, in-place.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn rem_self_s(&mut self, s: S);
|
2013-08-28 00:19:47 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// Add a vector to this point, in-place.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn add_self_v(&mut self, v: &V);
|
2013-09-18 01:36:41 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// This is a weird one, but its useful for plane calculations.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn dot(&self, v: &V) -> S;
|
|
|
|
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn min(&self, p: &Self) -> Self;
|
|
|
|
|
2015-02-22 21:33:16 +00:00
|
|
|
#[must_use]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn max(&self, p: &Self) -> Self;
|
|
|
|
}
|
|
|
|
|
2014-08-11 11:10:38 +00:00
|
|
|
impl<S: BaseNum> Array1<S> for Point2<S> {
|
|
|
|
#[inline]
|
2015-01-07 22:34:42 +00:00
|
|
|
fn map<F>(&mut self, mut op: F) -> Point2<S> where F: FnMut(S) -> S {
|
2014-08-11 11:10:38 +00:00
|
|
|
self.x = op(self.x);
|
|
|
|
self.y = op(self.y);
|
|
|
|
*self
|
2014-07-03 04:34:26 +00:00
|
|
|
}
|
2014-05-28 01:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: BaseNum> Point<S, Vector2<S>> for Point2<S> {
|
|
|
|
#[inline]
|
|
|
|
fn origin() -> Point2<S> {
|
|
|
|
Point2::new(zero(), zero())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn from_vec(v: &Vector2<S>) -> Point2<S> {
|
|
|
|
Point2::new(v.x, v.y)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_vec(&self) -> Vector2<S> {
|
|
|
|
Vector2::new(self.x,
|
|
|
|
self.y)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul_s(&self, s: S) -> Point2<S> {
|
|
|
|
Point2::new(self.x * s,
|
|
|
|
self.y * s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn div_s(&self, s: S) -> Point2<S> {
|
|
|
|
Point2::new(self.x / s,
|
|
|
|
self.y / s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rem_s(&self, s: S) -> Point2<S> {
|
|
|
|
Point2::new(self.x % s,
|
|
|
|
self.y % s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add_v(&self, v: &Vector2<S>) -> Point2<S> {
|
|
|
|
Point2::new(self.x + v.x,
|
|
|
|
self.y + v.y)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub_p(&self, p: &Point2<S>) -> Vector2<S> {
|
|
|
|
Vector2::new(self.x - p.x,
|
|
|
|
self.y - p.y)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x * s;
|
|
|
|
self.y = self.y * s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn div_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x / s;
|
|
|
|
self.y = self.y / s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rem_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x % s;
|
|
|
|
self.y = self.y % s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add_self_v(&mut self, v: &Vector2<S>) {
|
|
|
|
self.x = self.x + v.x;
|
|
|
|
self.y = self.y + v.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn dot(&self, v: &Vector2<S>) -> S {
|
|
|
|
self.x * v.x +
|
|
|
|
self.y * v.y
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn min(&self, p: &Point2<S>) -> Point2<S> {
|
|
|
|
Point2::new(self.x.partial_min(p.x),
|
|
|
|
self.y.partial_min(p.y))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn max(&self, p: &Point2<S>) -> Point2<S> {
|
|
|
|
Point2::new(self.x.partial_max(p.x),
|
|
|
|
self.y.partial_max(p.y))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: BaseFloat> ApproxEq<S> for Point2<S> {
|
2013-09-18 01:36:41 +00:00
|
|
|
#[inline]
|
2014-05-28 01:59:03 +00:00
|
|
|
fn approx_eq_eps(&self, other: &Point2<S>, epsilon: &S) -> bool {
|
|
|
|
self.x.approx_eq_eps(&other.x, epsilon) &&
|
|
|
|
self.y.approx_eq_eps(&other.y, epsilon)
|
2013-09-18 01:36:41 +00:00
|
|
|
}
|
2013-09-03 03:54:03 +00:00
|
|
|
}
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2014-08-11 11:10:38 +00:00
|
|
|
impl<S: BaseNum> Array1<S> for Point3<S> {
|
|
|
|
#[inline]
|
2015-01-07 22:34:42 +00:00
|
|
|
fn map<F>(&mut self, mut op: F) -> Point3<S> where F: FnMut(S) -> S {
|
2014-08-11 11:10:38 +00:00
|
|
|
self.x = op(self.x);
|
|
|
|
self.y = op(self.y);
|
|
|
|
self.z = op(self.z);
|
|
|
|
*self
|
2014-07-03 04:34:26 +00:00
|
|
|
}
|
2014-05-28 01:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: BaseNum> Point<S, Vector3<S>> for Point3<S> {
|
|
|
|
#[inline]
|
|
|
|
fn origin() -> Point3<S> {
|
|
|
|
Point3::new(zero(), zero(), zero())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn from_vec(v: &Vector3<S>) -> Point3<S> {
|
|
|
|
Point3::new(v.x, v.y, v.z)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_vec(&self) -> Vector3<S> {
|
|
|
|
Vector3::new(self.x,
|
|
|
|
self.y,
|
|
|
|
self.z)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul_s(&self, s: S) -> Point3<S> {
|
|
|
|
Point3::new(self.x * s,
|
|
|
|
self.y * s,
|
|
|
|
self.z * s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn div_s(&self, s: S) -> Point3<S> {
|
|
|
|
Point3::new(self.x / s,
|
|
|
|
self.y / s,
|
|
|
|
self.z / s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rem_s(&self, s: S) -> Point3<S> {
|
|
|
|
Point3::new(self.x % s,
|
|
|
|
self.y % s,
|
|
|
|
self.z % s)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add_v(&self, v: &Vector3<S>) -> Point3<S> {
|
|
|
|
Point3::new(self.x + v.x,
|
|
|
|
self.y + v.y,
|
|
|
|
self.z + v.z)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub_p(&self, p: &Point3<S>) -> Vector3<S> {
|
|
|
|
Vector3::new(self.x - p.x,
|
|
|
|
self.y - p.y,
|
|
|
|
self.z - p.z)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x * s;
|
|
|
|
self.y = self.y * s;
|
|
|
|
self.z = self.z * s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn div_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x / s;
|
|
|
|
self.y = self.y / s;
|
|
|
|
self.z = self.z / s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rem_self_s(&mut self, s: S) {
|
|
|
|
self.x = self.x % s;
|
|
|
|
self.y = self.y % s;
|
|
|
|
self.z = self.z % s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add_self_v(&mut self, v: &Vector3<S>) {
|
|
|
|
self.x = self.x + v.x;
|
|
|
|
self.y = self.y + v.y;
|
|
|
|
self.z = self.z + v.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn dot(&self, v: &Vector3<S>) -> S {
|
|
|
|
self.x * v.x +
|
|
|
|
self.y * v.y +
|
|
|
|
self.z * v.z
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn min(&self, p: &Point3<S>) -> Point3<S> {
|
|
|
|
Point3::new(self.x.partial_min(p.x),
|
|
|
|
self.y.partial_min(p.y),
|
|
|
|
self.z.partial_min(p.z))
|
|
|
|
}
|
2013-08-28 00:19:47 +00:00
|
|
|
|
2014-05-28 01:59:03 +00:00
|
|
|
#[inline]
|
|
|
|
fn max(&self, p: &Point3<S>) -> Point3<S> {
|
|
|
|
Point3::new(self.x.partial_max(p.x),
|
|
|
|
self.y.partial_max(p.y),
|
|
|
|
self.z.partial_max(p.z))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: BaseFloat> ApproxEq<S> for Point3<S> {
|
|
|
|
#[inline]
|
|
|
|
fn approx_eq_eps(&self, other: &Point3<S>, epsilon: &S) -> bool {
|
|
|
|
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-09-03 07:33:33 +00:00
|
|
|
|
2015-09-20 15:32:53 +00:00
|
|
|
macro_rules! fixed_array_conversions {
|
|
|
|
($PointN:ident <$S:ident> { $($field:ident : $index:expr),+ }, $n:expr) => {
|
|
|
|
impl<$S> Into<[$S; $n]> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn into(self) -> [$S; $n] {
|
|
|
|
match self { $PointN { $($field),+ } => [$($field),+] }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S> AsRef<[$S; $n]> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn as_ref(&self) -> &[$S; $n] {
|
|
|
|
unsafe { mem::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S> AsMut<[$S; $n]> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn as_mut(&mut self) -> &mut [$S; $n] {
|
|
|
|
unsafe { mem::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S: Clone> From<[$S; $n]> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: [$S; $n]) -> $PointN<$S> {
|
|
|
|
// We need to use a clone here because we can't pattern match on arrays yet
|
|
|
|
$PointN { $($field: v[$index].clone()),+ }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, $S> From<&'a [$S; $n]> for &'a $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: &'a [$S; $n]) -> &'a $PointN<$S> {
|
|
|
|
unsafe { mem::transmute(v) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, $S> From<&'a mut [$S; $n]> for &'a mut $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: &'a mut [$S; $n]) -> &'a mut $PointN<$S> {
|
|
|
|
unsafe { mem::transmute(v) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fixed_array_conversions!(Point2<S> { x:0, y:1 }, 2);
|
|
|
|
fixed_array_conversions!(Point3<S> { x:0, y:1, z:2 }, 3);
|
|
|
|
|
|
|
|
macro_rules! tuple_conversions {
|
|
|
|
($PointN:ident <$S:ident> { $($field:ident),+ }, $Tuple:ty) => {
|
|
|
|
impl<$S> Into<$Tuple> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn into(self) -> $Tuple {
|
|
|
|
match self { $PointN { $($field),+ } => ($($field),+) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S> AsRef<$Tuple> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn as_ref(&self) -> &$Tuple {
|
|
|
|
unsafe { mem::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S> AsMut<$Tuple> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn as_mut(&mut self) -> &mut $Tuple {
|
|
|
|
unsafe { mem::transmute(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<$S> From<$Tuple> for $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: $Tuple) -> $PointN<$S> {
|
|
|
|
// We need to use a clone here because we can't pattern match on arrays yet
|
|
|
|
match v { ($($field),+) => $PointN { $($field: $field),+ } }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, $S> From<&'a $Tuple> for &'a $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: &'a $Tuple) -> &'a $PointN<$S> {
|
|
|
|
unsafe { mem::transmute(v) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, $S> From<&'a mut $Tuple> for &'a mut $PointN<$S> {
|
|
|
|
#[inline]
|
|
|
|
fn from(v: &'a mut $Tuple) -> &'a mut $PointN<$S> {
|
|
|
|
unsafe { mem::transmute(v) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tuple_conversions!(Point2<S> { x, y }, (S, S));
|
|
|
|
tuple_conversions!(Point3<S> { x, y, z }, (S, S, S));
|
|
|
|
|
|
|
|
macro_rules! index_operators {
|
2015-09-20 21:56:03 +00:00
|
|
|
($PointN:ident<$S:ident>, $n:expr, $Output:ty, $I:ty) => {
|
|
|
|
impl<$S> Index<$I> for $PointN<$S> {
|
|
|
|
type Output = $Output;
|
2015-09-20 15:32:53 +00:00
|
|
|
|
|
|
|
#[inline]
|
2015-09-20 21:56:03 +00:00
|
|
|
fn index<'a>(&'a self, i: $I) -> &'a $Output {
|
2015-09-20 15:32:53 +00:00
|
|
|
let v: &[$S; $n] = self.as_ref(); &v[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-20 21:56:03 +00:00
|
|
|
impl<$S> IndexMut<$I> for $PointN<$S> {
|
2015-09-20 15:32:53 +00:00
|
|
|
#[inline]
|
2015-09-20 21:56:03 +00:00
|
|
|
fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
|
2015-09-20 15:32:53 +00:00
|
|
|
let v: &mut [$S; $n] = self.as_mut(); &mut v[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-20 21:56:03 +00:00
|
|
|
index_operators!(Point2<S>, 2, S, usize);
|
|
|
|
index_operators!(Point3<S>, 3, S, usize);
|
|
|
|
index_operators!(Point2<S>, 2, [S], Range<usize>);
|
|
|
|
index_operators!(Point3<S>, 3, [S], Range<usize>);
|
|
|
|
index_operators!(Point2<S>, 2, [S], RangeTo<usize>);
|
|
|
|
index_operators!(Point3<S>, 3, [S], RangeTo<usize>);
|
|
|
|
index_operators!(Point2<S>, 2, [S], RangeFrom<usize>);
|
|
|
|
index_operators!(Point3<S>, 3, [S], RangeFrom<usize>);
|
|
|
|
index_operators!(Point2<S>, 2, [S], RangeFull);
|
|
|
|
index_operators!(Point3<S>, 3, [S], RangeFull);
|
2015-09-20 15:32:53 +00:00
|
|
|
|
2015-02-08 18:19:32 +00:00
|
|
|
impl<S: BaseNum> fmt::Debug for Point2<S> {
|
2014-02-25 08:56:22 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2015-01-09 22:06:45 +00:00
|
|
|
write!(f, "[{:?}, {:?}]", self.x, self.y)
|
2013-09-03 07:33:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-08 18:19:32 +00:00
|
|
|
impl<S: BaseNum> fmt::Debug for Point3<S> {
|
2014-02-25 08:56:22 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2015-01-09 22:06:45 +00:00
|
|
|
write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z)
|
2013-09-03 07:33:33 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-13 08:32:23 +00:00
|
|
|
|
2015-03-14 20:41:15 +00:00
|
|
|
impl<S: BaseFloat + 'static> Bound<S> for Point3<S> {
|
|
|
|
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
2015-03-13 08:32:23 +00:00
|
|
|
let dist = self.dot(&plane.n);
|
|
|
|
if dist > plane.d {
|
|
|
|
Relation::In
|
|
|
|
}else if dist < plane.d {
|
|
|
|
Relation::Out
|
|
|
|
}else {
|
|
|
|
Relation::Cross
|
|
|
|
}
|
|
|
|
}
|
2015-03-14 20:41:15 +00:00
|
|
|
|
|
|
|
fn relate_clip_space(&self, projection: &Matrix4<S>) -> Relation {
|
|
|
|
use std::cmp::Ordering::*;
|
|
|
|
let p = projection.mul_v(&self.to_homogeneous());
|
|
|
|
match (p.x.abs().partial_cmp(&p.w), p.y.abs().partial_cmp(&p.w), p.z.abs().partial_cmp(&p.w)) {
|
|
|
|
(Some(Less), Some(Less), Some(Less)) => Relation::In,
|
|
|
|
(Some(Greater), _, _) | (_, Some(Greater), _) | (_, _, Some(Greater)) => Relation::Out,
|
|
|
|
_ => Relation::Cross,
|
|
|
|
}
|
|
|
|
}
|
2015-03-13 08:32:23 +00:00
|
|
|
}
|
2015-09-27 03:01:14 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
mod point2 {
|
|
|
|
use point::*;
|
|
|
|
|
|
|
|
const POINT2: Point2<i32> = Point2 { x: 1, y: 2 };
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index() {
|
|
|
|
assert_eq!(POINT2[0], POINT2.x);
|
|
|
|
assert_eq!(POINT2[1], POINT2.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index_mut() {
|
|
|
|
let mut p = POINT2;
|
|
|
|
*&mut p[0] = 0;
|
|
|
|
assert_eq!(p, [0, 2].into());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn test_index_out_of_bounds() {
|
|
|
|
POINT2[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index_range() {
|
|
|
|
assert_eq!(&POINT2[..0], &[]);
|
|
|
|
assert_eq!(&POINT2[..1], &[1]);
|
|
|
|
assert_eq!(POINT2[..0].len(), 0);
|
|
|
|
assert_eq!(POINT2[..1].len(), 1);
|
|
|
|
assert_eq!(&POINT2[2..], &[]);
|
|
|
|
assert_eq!(&POINT2[1..], &[2]);
|
|
|
|
assert_eq!(POINT2[2..].len(), 0);
|
|
|
|
assert_eq!(POINT2[1..].len(), 1);
|
|
|
|
assert_eq!(&POINT2[..], &[1, 2]);
|
|
|
|
assert_eq!(POINT2[..].len(), 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod point3 {
|
|
|
|
use point::*;
|
|
|
|
|
|
|
|
const POINT3: Point3<i32> = Point3 { x: 1, y: 2, z: 3 };
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index() {
|
|
|
|
assert_eq!(POINT3[0], POINT3.x);
|
|
|
|
assert_eq!(POINT3[1], POINT3.y);
|
|
|
|
assert_eq!(POINT3[2], POINT3.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index_mut() {
|
|
|
|
let mut p = POINT3;
|
|
|
|
*&mut p[1] = 0;
|
|
|
|
assert_eq!(p, [1, 0, 3].into());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn test_index_out_of_bounds() {
|
|
|
|
POINT3[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_index_range() {
|
|
|
|
assert_eq!(&POINT3[..1], &[1]);
|
|
|
|
assert_eq!(&POINT3[..2], &[1, 2]);
|
|
|
|
assert_eq!(POINT3[..1].len(), 1);
|
|
|
|
assert_eq!(POINT3[..2].len(), 2);
|
|
|
|
assert_eq!(&POINT3[2..], &[3]);
|
|
|
|
assert_eq!(&POINT3[1..], &[2, 3]);
|
|
|
|
assert_eq!(POINT3[2..].len(), 1);
|
|
|
|
assert_eq!(POINT3[1..].len(), 2);
|
|
|
|
assert_eq!(&POINT3[..], &[1, 2, 3]);
|
|
|
|
assert_eq!(POINT3[..].len(), 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|