use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use num::One; use std::cmp::Ordering; use std::fmt; use std::hash; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; use base::allocator::Allocator; use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use base::iter::{MatrixIter, MatrixIterMut}; use base::{DefaultAllocator, Scalar, VectorN}; /// A point in a n-dimensional euclidean space. #[repr(C)] #[derive(Debug, Clone)] pub struct Point where DefaultAllocator: Allocator { /// The coordinates of this point, i.e., the shift from the origin. pub coords: VectorN, } impl hash::Hash for Point where DefaultAllocator: Allocator, >::Buffer: hash::Hash, { fn hash(&self, state: &mut H) { self.coords.hash(state) } } impl Copy for Point where DefaultAllocator: Allocator, >::Buffer: Copy, { } #[cfg(feature = "serde-serialize")] impl Serialize for Point where DefaultAllocator: Allocator, >::Buffer: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer { self.coords.serialize(serializer) } } #[cfg(feature = "serde-serialize")] impl<'a, N: Scalar, D: DimName> Deserialize<'a> for Point where DefaultAllocator: Allocator, >::Buffer: Deserialize<'a>, { fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a> { let coords = VectorN::::deserialize(deserializer)?; Ok(Self::from(coords)) } } #[cfg(feature = "abomonation-serialize")] impl Abomonation for Point where N: Scalar, D: DimName, VectorN: Abomonation, DefaultAllocator: Allocator, { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { self.coords.entomb(writer) } fn extent(&self) -> usize { self.coords.extent() } unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { self.coords.exhume(bytes) } } impl Point where DefaultAllocator: Allocator { /// Converts this point into a vector in homogeneous coordinates, i.e., appends a `1` at the /// end of it. /// /// This is the same as `.into()`. /// /// # Example /// ``` /// # use nalgebra::{Point2, Point3, Vector3, Vector4}; /// let p = Point2::new(10.0, 20.0); /// assert_eq!(p.to_homogeneous(), Vector3::new(10.0, 20.0, 1.0)); /// /// // This works in any dimension. /// let p = Point3::new(10.0, 20.0, 30.0); /// assert_eq!(p.to_homogeneous(), Vector4::new(10.0, 20.0, 30.0, 1.0)); /// ``` #[inline] pub fn to_homogeneous(&self) -> VectorN> where N: One, D: DimNameAdd, DefaultAllocator: Allocator>, { let mut res = unsafe { VectorN::<_, DimNameSum>::new_uninitialized() }; res.fixed_slice_mut::(0, 0).copy_from(&self.coords); res[(D::dim(), 0)] = N::one(); res } /// Creates a new point with the given coordinates. #[deprecated(note = "Use Point::from(vector) instead.")] #[inline] pub fn from_coordinates(coords: VectorN) -> Self { Self { coords: coords } } /// The dimension of this point. /// /// # Example /// ``` /// # use nalgebra::{Point2, Point3}; /// let p = Point2::new(1.0, 2.0); /// assert_eq!(p.len(), 2); /// /// // This works in any dimension. /// let p = Point3::new(10.0, 20.0, 30.0); /// assert_eq!(p.len(), 3); /// ``` #[inline] pub fn len(&self) -> usize { self.coords.len() } /// The stride of this point. This is the number of buffer element separating each component of /// this point. #[inline] #[deprecated(note = "This methods is no longer significant and will always return 1.")] pub fn stride(&self) -> usize { self.coords.strides().0 } /// Iterates through this point coordinates. /// /// # Example /// ``` /// # use nalgebra::Point3; /// let p = Point3::new(1.0, 2.0, 3.0); /// let mut it = p.iter().cloned(); /// /// assert_eq!(it.next(), Some(1.0)); /// assert_eq!(it.next(), Some(2.0)); /// assert_eq!(it.next(), Some(3.0)); /// assert_eq!(it.next(), None); #[inline] pub fn iter(&self) -> MatrixIter>::Buffer> { self.coords.iter() } /// Gets a reference to i-th element of this point without bound-checking. #[inline] pub unsafe fn get_unchecked(&self, i: usize) -> &N { self.coords.vget_unchecked(i) } /// Mutably iterates through this point coordinates. /// /// # Example /// ``` /// # use nalgebra::Point3; /// let mut p = Point3::new(1.0, 2.0, 3.0); /// /// for e in p.iter_mut() { /// *e *= 10.0; /// } /// /// assert_eq!(p, Point3::new(10.0, 20.0, 30.0)); #[inline] pub fn iter_mut( &mut self, ) -> MatrixIterMut>::Buffer> { self.coords.iter_mut() } /// Gets a mutable reference to i-th element of this point without bound-checking. #[inline] pub unsafe fn get_unchecked_mut(&mut self, i: usize) -> &mut N { self.coords.vget_unchecked_mut(i) } /// Swaps two entries without bound-checking. #[inline] pub unsafe fn swap_unchecked(&mut self, i1: usize, i2: usize) { self.coords.swap_unchecked((i1, 0), (i2, 0)) } } impl AbsDiffEq for Point where DefaultAllocator: Allocator, N::Epsilon: Copy, { type Epsilon = N::Epsilon; #[inline] fn default_epsilon() -> Self::Epsilon { N::default_epsilon() } #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { self.coords.abs_diff_eq(&other.coords, epsilon) } } impl RelativeEq for Point where DefaultAllocator: Allocator, N::Epsilon: Copy, { #[inline] fn default_max_relative() -> Self::Epsilon { N::default_max_relative() } #[inline] fn relative_eq( &self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { self.coords .relative_eq(&other.coords, epsilon, max_relative) } } impl UlpsEq for Point where DefaultAllocator: Allocator, N::Epsilon: Copy, { #[inline] fn default_max_ulps() -> u32 { N::default_max_ulps() } #[inline] fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { self.coords.ulps_eq(&other.coords, epsilon, max_ulps) } } impl Eq for Point where DefaultAllocator: Allocator {} impl PartialEq for Point where DefaultAllocator: Allocator { #[inline] fn eq(&self, right: &Self) -> bool { self.coords == right.coords } } impl PartialOrd for Point where DefaultAllocator: Allocator { #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.coords.partial_cmp(&other.coords) } #[inline] fn lt(&self, right: &Self) -> bool { self.coords.lt(&right.coords) } #[inline] fn le(&self, right: &Self) -> bool { self.coords.le(&right.coords) } #[inline] fn gt(&self, right: &Self) -> bool { self.coords.gt(&right.coords) } #[inline] fn ge(&self, right: &Self) -> bool { self.coords.ge(&right.coords) } } /* * * Display * */ impl fmt::Display for Point where DefaultAllocator: Allocator { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); let mut it = self.coords.iter(); try!(write!(f, "{}", *it.next().unwrap())); for comp in it { try!(write!(f, ", {}", *comp)); } write!(f, "}}") } }