use num::{One, Zero}; use alga::general::{ClosedDiv, SubsetOf, SupersetOf}; use base::{DefaultAllocator, Matrix, Scalar, VectorN}; use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use base::allocator::Allocator; use geometry::Point; #[cfg(feature = "mint")] use mint; #[cfg(feature = "mint")] use base::dimension::{U2, U3}; #[cfg(feature = "mint")] use std::convert::{AsMut, AsRef, From, Into}; #[cfg(feature = "mint")] use base::storage::{Storage, StorageMut}; #[cfg(feature = "mint")] use std::mem; /* * This file provides the following conversions: * ============================================= * * Point -> Point * Point -> Vector (homogeneous) * * mint::Point <-> Point */ impl SubsetOf> for Point where D: DimName, N1: Scalar, N2: Scalar + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] fn to_superset(&self) -> Point { Point::from_coordinates(self.coords.to_superset()) } #[inline] fn is_in_subset(m: &Point) -> bool { // FIXME: is there a way to reuse the `.is_in_subset` from the matrix implementation of // SubsetOf? m.iter().all(|e| e.is_in_subset()) } #[inline] unsafe fn from_superset_unchecked(m: &Point) -> Self { Point::from_coordinates(Matrix::from_superset_unchecked(&m.coords)) } } impl SubsetOf>> for Point where D: DimNameAdd, N1: Scalar, N2: Scalar + Zero + One + ClosedDiv + SupersetOf, DefaultAllocator: Allocator + Allocator> + Allocator> + Allocator, { #[inline] fn to_superset(&self) -> VectorN> { let p: Point = self.to_superset(); p.to_homogeneous() } #[inline] fn is_in_subset(v: &VectorN>) -> bool { ::is_convertible::<_, VectorN>>(v) && !v[D::dim()].is_zero() } #[inline] unsafe fn from_superset_unchecked(v: &VectorN>) -> Self { let coords = v.fixed_slice::(0, 0) / v[D::dim()]; Self::from_coordinates(::convert_unchecked(coords)) } } #[cfg(feature = "mint")] macro_rules! impl_from_into_mint_1D( ($($NRows: ident => $PT:ident, $VT:ident [$SZ: expr]);* $(;)*) => {$( impl From> for Point where N: Scalar, DefaultAllocator: Allocator { #[inline] fn from(p: mint::$PT) -> Self { Self { coords: VectorN::from(mint::$VT::from(p)), } } } impl Into> for Point where N: Scalar { #[inline] fn into(self) -> mint::$PT { let mint_vec: mint::$VT = self.coords.into(); mint::$PT::from(mint_vec) } } impl AsRef> for Point where N: Scalar { #[inline] fn as_ref(&self) -> &mint::$PT { unsafe { mem::transmute(self.coords.data.ptr()) } } } impl AsMut> for Point where N: Scalar { #[inline] fn as_mut(&mut self) -> &mut mint::$PT { unsafe { mem::transmute(self.coords.data.ptr_mut()) } } } )*} ); // Implement for points of dimension 2, 3. #[cfg(feature = "mint")] impl_from_into_mint_1D!( U2 => Point2, Vector2[2]; U3 => Point3, Vector3[3]; );