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-09-29 11:36:57 +00:00
|
|
|
use rust_num::{One, Zero};
|
2015-04-05 01:19:11 +00:00
|
|
|
|
2014-05-28 01:59:03 +00:00
|
|
|
use approx::ApproxEq;
|
2015-11-14 10:58:11 +00:00
|
|
|
use array::Array;
|
2015-11-01 02:42:58 +00:00
|
|
|
use matrix::Matrix;
|
2015-04-05 01:19:11 +00:00
|
|
|
use num::{BaseNum, BaseFloat};
|
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.
|
2016-03-25 01:34:12 +00:00
|
|
|
///
|
|
|
|
/// This type is marked as `#[repr(C, packed)]`.
|
|
|
|
#[repr(C, packed)]
|
2015-02-21 19:50:00 +00:00
|
|
|
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
|
2016-03-25 01:34:12 +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.
|
2016-03-25 01:34:12 +00:00
|
|
|
///
|
|
|
|
/// This type is marked as `#[repr(C, packed)]`.
|
|
|
|
#[repr(C, packed)]
|
2015-02-21 19:50:00 +00:00
|
|
|
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
|
2016-03-25 01:34:12 +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]
|
2015-11-09 09:12:04 +00:00
|
|
|
pub fn from_homogeneous(v: Vector4<S>) -> Point3<S> {
|
2015-11-08 06:41:57 +00:00
|
|
|
let e = v.truncate() * (S::one() / 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]
|
2015-11-09 09:12:04 +00:00
|
|
|
pub fn to_homogeneous(self) -> Vector4<S> {
|
2015-09-29 11:36:57 +00:00
|
|
|
Vector4::new(self.x, self.y, self.z, S::one())
|
2013-11-01 14:32:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-24 11:50:23 +00:00
|
|
|
/// Points in a [Euclidean space](https://en.wikipedia.org/wiki/Euclidean_space)
|
|
|
|
/// with an associated vector space, `Self::Vector`.
|
|
|
|
///
|
|
|
|
/// # Point-Vector distinction
|
|
|
|
///
|
|
|
|
/// `cgmath` distinguishes between points and vectors in the following way:
|
|
|
|
///
|
|
|
|
/// - Points are _locations_ relative to an origin
|
|
|
|
/// - Vectors are _displacements_ between those points
|
|
|
|
///
|
|
|
|
/// For example, to find the midpoint between two points, you can write the
|
|
|
|
/// following:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use cgmath::Point3;
|
|
|
|
///
|
|
|
|
/// let p0 = Point3::new(1.0, 2.0, 3.0);
|
|
|
|
/// let p1 = Point3::new(-3.0, 1.0, 2.0);
|
|
|
|
/// let midpoint: Point3<f32> = p0 + (p1 - p0) * 0.5;
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Breaking the expression up, and adding explicit types makes it clearer
|
|
|
|
/// to see what is going on:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// # use cgmath::{Point3, Vector3};
|
|
|
|
/// #
|
|
|
|
/// # let p0 = Point3::new(1.0, 2.0, 3.0);
|
|
|
|
/// # let p1 = Point3::new(-3.0, 1.0, 2.0);
|
|
|
|
/// #
|
|
|
|
/// let dv: Vector3<f32> = p1 - p0;
|
|
|
|
/// let half_dv: Vector3<f32> = dv * 0.5;
|
|
|
|
/// let midpoint: Point3<f32> = p0 + half_dv;
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// ## Converting between points and vectors
|
|
|
|
///
|
|
|
|
/// Points can be converted to and from displacement vectors using the
|
|
|
|
/// `Point::{from_vec, to_vec}` methods. Note that under the hood these are
|
|
|
|
/// implemented as inlined a type conversion, so should not have any performance
|
|
|
|
/// implications.
|
|
|
|
///
|
|
|
|
/// ## References
|
|
|
|
///
|
|
|
|
/// - [CGAL 4.7 - 2D and 3D Linear Geometry Kernel: 3.1 Points and Vectors](http://doc.cgal.org/latest/Kernel_23/index.html#Kernel_23PointsandVectors)
|
|
|
|
/// - [What is the difference between a point and a vector](http://math.stackexchange.com/q/645827)
|
|
|
|
///
|
2015-11-09 09:12:04 +00:00
|
|
|
pub trait Point: Copy + Clone where
|
2015-11-03 04:40:52 +00:00
|
|
|
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
|
2015-11-14 10:58:11 +00:00
|
|
|
Self: Array<Element = <Self as Point>::Scalar>,
|
2015-12-12 11:31:10 +00:00
|
|
|
|
|
|
|
Self: Add<<Self as Point>::Vector, Output = Self>,
|
|
|
|
Self: Sub<Self, Output = <Self as Point>::Vector>,
|
|
|
|
|
|
|
|
Self: Mul<<Self as Point>::Scalar, Output = Self>,
|
|
|
|
Self: Div<<Self as Point>::Scalar, Output = Self>,
|
|
|
|
Self: Rem<<Self as Point>::Scalar, Output = Self>,
|
2015-09-30 08:23:01 +00:00
|
|
|
{
|
2015-11-03 04:50:07 +00:00
|
|
|
/// The associated scalar.
|
|
|
|
///
|
|
|
|
/// Due to the equality constraints demanded by `Self::Vector`, this is effectively just an
|
|
|
|
/// alias to `Self::Vector::Scalar`.
|
|
|
|
type Scalar: BaseNum;
|
2016-03-24 11:50:23 +00:00
|
|
|
|
|
|
|
/// The associated space of displacement vectors.
|
2015-11-03 04:50:07 +00:00
|
|
|
type Vector: Vector<Scalar = Self::Scalar>;
|
2015-10-03 05:17:09 +00:00
|
|
|
|
2016-03-24 11:50:23 +00:00
|
|
|
/// The point at the origin of the Euclidean space.
|
2014-05-28 01:59:03 +00:00
|
|
|
fn origin() -> Self;
|
2014-01-25 15:54:54 +00:00
|
|
|
|
2016-03-24 11:50:23 +00:00
|
|
|
/// Convert a displacement vector to a point.
|
|
|
|
///
|
|
|
|
/// This can be considered equivalent to the addition of the displacement
|
|
|
|
/// vector `v` to to `Self::origin()`.
|
2015-11-09 09:12:04 +00:00
|
|
|
fn from_vec(v: Self::Vector) -> Self;
|
2016-03-24 11:50:23 +00:00
|
|
|
|
|
|
|
/// Convert a point to a displacement vector.
|
|
|
|
///
|
|
|
|
/// This can be seen as equivalent to the displacement vector from
|
|
|
|
/// `Self::origin()` to `self`.
|
2015-11-09 09:12:04 +00:00
|
|
|
fn to_vec(self) -> Self::Vector;
|
2013-11-02 13:11:13 +00:00
|
|
|
|
2014-05-25 10:09:33 +00:00
|
|
|
/// This is a weird one, but its useful for plane calculations.
|
2015-11-09 09:12:04 +00:00
|
|
|
fn dot(self, v: Self::Vector) -> Self::Scalar;
|
2013-09-03 03:54:03 +00:00
|
|
|
}
|
2013-08-26 05:08:25 +00:00
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
macro_rules! impl_point {
|
|
|
|
($PointN:ident { $($field:ident),+ }, $VectorN:ident, $n:expr) => {
|
|
|
|
impl<S: BaseNum> Array for $PointN<S> {
|
|
|
|
type Element = S;
|
2015-09-30 08:23:01 +00:00
|
|
|
|
2016-04-04 09:53:55 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_value(scalar: S) -> $PointN<S> {
|
|
|
|
$PointN { $($field: scalar),+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sum(self) -> S where S: Add<Output = S> {
|
|
|
|
fold_array!(add, { $(self.$field),+ })
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn product(self) -> S where S: Mul<Output = S> {
|
|
|
|
fold_array!(mul, { $(self.$field),+ })
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn min(self) -> S where S: PartialOrd {
|
|
|
|
fold_array!(partial_min, { $(self.$field),+ })
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn max(self) -> S where S: PartialOrd {
|
|
|
|
fold_array!(partial_max, { $(self.$field),+ })
|
|
|
|
}
|
2015-09-30 08:23:01 +00:00
|
|
|
}
|
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl<S: BaseNum> Point for $PointN<S> {
|
|
|
|
type Scalar = S;
|
|
|
|
type Vector = $VectorN<S>;
|
2015-09-30 08:23:01 +00:00
|
|
|
|
|
|
|
#[inline]
|
2015-12-12 11:17:03 +00:00
|
|
|
fn origin() -> $PointN<S> {
|
|
|
|
$PointN { $($field: S::zero()),+ }
|
2015-09-30 08:23:01 +00:00
|
|
|
}
|
2015-11-08 06:41:57 +00:00
|
|
|
|
|
|
|
#[inline]
|
2015-12-12 11:17:03 +00:00
|
|
|
fn from_vec(v: $VectorN<S>) -> $PointN<S> {
|
|
|
|
$PointN::new($(v.$field),+)
|
2015-11-08 06:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-12-12 11:17:03 +00:00
|
|
|
fn to_vec(self) -> $VectorN<S> {
|
|
|
|
$VectorN::new($(self.$field),+)
|
2015-11-08 06:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-12-12 11:17:03 +00:00
|
|
|
fn dot(self, v: $VectorN<S>) -> S {
|
|
|
|
$VectorN::new($(self.$field * v.$field),+).sum()
|
2015-11-08 06:41:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl<S: BaseFloat> ApproxEq for $PointN<S> {
|
|
|
|
type Epsilon = S;
|
2015-11-08 06:41:57 +00:00
|
|
|
|
|
|
|
#[inline]
|
2015-12-12 11:17:03 +00:00
|
|
|
fn approx_eq_eps(&self, other: &$PointN<S>, epsilon: &S) -> bool {
|
|
|
|
$(self.$field.approx_eq_eps(&other.$field, epsilon))&&+
|
2015-11-08 06:41:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-21 13:43:15 +00:00
|
|
|
impl_operator!(<S: BaseNum> Add<$VectorN<S> > for $PointN<S> {
|
2015-12-12 11:17:03 +00:00
|
|
|
fn add(lhs, rhs) -> $PointN<S> { $PointN::new($(lhs.$field + rhs.$field),+) }
|
|
|
|
});
|
2015-12-20 20:24:56 +00:00
|
|
|
impl_assignment_operator!(<S: BaseNum> AddAssign<$VectorN<S> > for $PointN<S> {
|
|
|
|
fn add_assign(&mut self, vector) { $(self.$field += vector.$field);+ }
|
|
|
|
});
|
2015-11-08 06:41:57 +00:00
|
|
|
|
2015-12-21 13:43:15 +00:00
|
|
|
impl_operator!(<S: BaseNum> Sub<$PointN<S> > for $PointN<S> {
|
2015-12-12 11:17:03 +00:00
|
|
|
fn sub(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field - rhs.$field),+) }
|
|
|
|
});
|
2015-11-08 06:41:57 +00:00
|
|
|
|
2015-12-21 13:43:15 +00:00
|
|
|
impl_operator!(<S: BaseNum> Mul<S> for $PointN<S> {
|
2015-12-12 11:17:03 +00:00
|
|
|
fn mul(point, scalar) -> $PointN<S> { $PointN::new($(point.$field * scalar),+) }
|
|
|
|
});
|
2015-12-21 13:43:15 +00:00
|
|
|
impl_operator!(<S: BaseNum> Div<S> for $PointN<S> {
|
2015-12-12 11:17:03 +00:00
|
|
|
fn div(point, scalar) -> $PointN<S> { $PointN::new($(point.$field / scalar),+) }
|
|
|
|
});
|
2015-12-21 13:43:15 +00:00
|
|
|
impl_operator!(<S: BaseNum> Rem<S> for $PointN<S> {
|
2015-12-12 11:17:03 +00:00
|
|
|
fn rem(point, scalar) -> $PointN<S> { $PointN::new($(point.$field % scalar),+) }
|
|
|
|
});
|
2015-12-20 20:24:56 +00:00
|
|
|
impl_assignment_operator!(<S: BaseNum> MulAssign<S> for $PointN<S> {
|
|
|
|
fn mul_assign(&mut self, scalar) { $(self.$field *= scalar);+ }
|
|
|
|
});
|
|
|
|
impl_assignment_operator!(<S: BaseNum> DivAssign<S> for $PointN<S> {
|
|
|
|
fn div_assign(&mut self, scalar) { $(self.$field /= scalar);+ }
|
|
|
|
});
|
|
|
|
impl_assignment_operator!(<S: BaseNum> RemAssign<S> for $PointN<S> {
|
|
|
|
fn rem_assign(&mut self, scalar) { $(self.$field %= scalar);+ }
|
|
|
|
});
|
2015-09-30 08:23:01 +00:00
|
|
|
|
2016-01-01 23:14:47 +00:00
|
|
|
impl_scalar_ops!($PointN<usize> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<u8> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<u16> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<u32> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<u64> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<isize> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<i8> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<i16> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<i32> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<i64> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<f32> { $($field),+ });
|
|
|
|
impl_scalar_ops!($PointN<f64> { $($field),+ });
|
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl_index_operators!($PointN<S>, $n, S, usize);
|
|
|
|
impl_index_operators!($PointN<S>, $n, [S], Range<usize>);
|
|
|
|
impl_index_operators!($PointN<S>, $n, [S], RangeTo<usize>);
|
|
|
|
impl_index_operators!($PointN<S>, $n, [S], RangeFrom<usize>);
|
|
|
|
impl_index_operators!($PointN<S>, $n, [S], RangeFull);
|
2015-09-30 08:23:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-01 23:14:47 +00:00
|
|
|
macro_rules! impl_scalar_ops {
|
|
|
|
($PointN:ident<$S:ident> { $($field:ident),+ }) => {
|
|
|
|
impl_operator!(Mul<$PointN<$S>> for $S {
|
2016-01-02 05:10:35 +00:00
|
|
|
fn mul(scalar, point) -> $PointN<$S> { $PointN::new($(scalar * point.$field),+) }
|
2016-01-01 23:14:47 +00:00
|
|
|
});
|
|
|
|
impl_operator!(Div<$PointN<$S>> for $S {
|
2016-01-02 05:10:35 +00:00
|
|
|
fn div(scalar, point) -> $PointN<$S> { $PointN::new($(scalar / point.$field),+) }
|
2016-01-01 23:14:47 +00:00
|
|
|
});
|
|
|
|
impl_operator!(Rem<$PointN<$S>> for $S {
|
2016-01-02 05:10:35 +00:00
|
|
|
fn rem(scalar, point) -> $PointN<$S> { $PointN::new($(scalar % point.$field),+) }
|
2016-01-01 23:14:47 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl_point!(Point2 { x, y }, Vector2, 2);
|
|
|
|
impl_point!(Point3 { x, y, z }, Vector3, 3);
|
2015-09-30 08:23:01 +00:00
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl_fixed_array_conversions!(Point2<S> { x: 0, y: 1 }, 2);
|
|
|
|
impl_fixed_array_conversions!(Point3<S> { x: 0, y: 1, z: 2 }, 3);
|
2015-09-20 15:32:53 +00:00
|
|
|
|
2015-12-12 11:17:03 +00:00
|
|
|
impl_tuple_conversions!(Point2<S> { x, y }, (S, S));
|
|
|
|
impl_tuple_conversions!(Point3<S> { x, y, z }, (S, S, S));
|
2015-09-20 15:32:53 +00:00
|
|
|
|
2015-12-29 10:50:43 +00:00
|
|
|
impl<S: fmt::Debug> fmt::Debug for Point2<S> {
|
2014-02-25 08:56:22 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2015-12-29 10:50:43 +00:00
|
|
|
try!(write!(f, "Point2 "));
|
|
|
|
<[S; 2] as fmt::Debug>::fmt(self.as_ref(), f)
|
2013-09-03 07:33:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-29 10:50:43 +00:00
|
|
|
impl<S: fmt::Debug> fmt::Debug for Point3<S> {
|
2014-02-25 08:56:22 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2015-12-29 10:50:43 +00:00
|
|
|
try!(write!(f, "Point3 "));
|
|
|
|
<[S; 3] as fmt::Debug>::fmt(self.as_ref(), f)
|
2013-09-03 07:33:33 +00:00
|
|
|
}
|
|
|
|
}
|
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);
|
|
|
|
}
|
2015-09-27 07:20:02 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_into() {
|
|
|
|
let p = POINT2;
|
|
|
|
{
|
|
|
|
let p: [i32; 2] = p.into();
|
|
|
|
assert_eq!(p, [1, 2]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: (i32, i32) = p.into();
|
|
|
|
assert_eq!(p, (1, 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_ref() {
|
|
|
|
let p = POINT2;
|
|
|
|
{
|
|
|
|
let p: &[i32; 2] = p.as_ref();
|
|
|
|
assert_eq!(p, &[1, 2]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: &(i32, i32) = p.as_ref();
|
|
|
|
assert_eq!(p, &(1, 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_mut() {
|
|
|
|
let mut p = POINT2;
|
|
|
|
{
|
|
|
|
let p: &mut [i32; 2] = p.as_mut();
|
|
|
|
assert_eq!(p, &mut [1, 2]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: &mut (i32, i32) = p.as_mut();
|
|
|
|
assert_eq!(p, &mut (1, 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from() {
|
|
|
|
assert_eq!(Point2::from([1, 2]), POINT2);
|
|
|
|
{
|
|
|
|
let p = &[1, 2];
|
|
|
|
let p: &Point2<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT2);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p = &mut [1, 2];
|
|
|
|
let p: &mut Point2<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT2);
|
|
|
|
}
|
|
|
|
assert_eq!(Point2::from((1, 2)), POINT2);
|
|
|
|
{
|
|
|
|
let p = &(1, 2);
|
|
|
|
let p: &Point2<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT2);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p = &mut (1, 2);
|
|
|
|
let p: &mut Point2<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT2);
|
|
|
|
}
|
|
|
|
}
|
2015-09-27 03:01:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2015-09-27 07:20:02 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_into() {
|
|
|
|
let p = POINT3;
|
|
|
|
{
|
|
|
|
let p: [i32; 3] = p.into();
|
|
|
|
assert_eq!(p, [1, 2, 3]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: (i32, i32, i32) = p.into();
|
|
|
|
assert_eq!(p, (1, 2, 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_ref() {
|
|
|
|
let p = POINT3;
|
|
|
|
{
|
|
|
|
let p: &[i32; 3] = p.as_ref();
|
|
|
|
assert_eq!(p, &[1, 2, 3]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: &(i32, i32, i32) = p.as_ref();
|
|
|
|
assert_eq!(p, &(1, 2, 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_as_mut() {
|
|
|
|
let mut p = POINT3;
|
|
|
|
{
|
|
|
|
let p: &mut [i32; 3] = p.as_mut();
|
|
|
|
assert_eq!(p, &mut [1, 2, 3]);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p: &mut (i32, i32, i32) = p.as_mut();
|
|
|
|
assert_eq!(p, &mut (1, 2, 3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from() {
|
|
|
|
assert_eq!(Point3::from([1, 2, 3]), POINT3);
|
|
|
|
{
|
|
|
|
let p = &[1, 2, 3];
|
|
|
|
let p: &Point3<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT3);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p = &mut [1, 2, 3];
|
|
|
|
let p: &mut Point3<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT3);
|
|
|
|
}
|
|
|
|
assert_eq!(Point3::from((1, 2, 3)), POINT3);
|
|
|
|
{
|
|
|
|
let p = &(1, 2, 3);
|
|
|
|
let p: &Point3<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT3);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
let p = &mut (1, 2, 3);
|
|
|
|
let p: &mut Point3<_> = From::from(p);
|
|
|
|
assert_eq!(p, &POINT3);
|
|
|
|
}
|
|
|
|
}
|
2015-09-27 03:01:14 +00:00
|
|
|
}
|
|
|
|
}
|