use alga::general::{ClosedDiv, SubsetOf, SupersetOf}; use num::{One, Zero}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN}; #[cfg(feature = "mint")] use crate::base::dimension::{U2, U3}; #[cfg(feature = "mint")] use crate::base::storage::{Storage, StorageMut}; use crate::geometry::Point; #[cfg(feature = "mint")] use mint; #[cfg(feature = "mint")] use std::convert::{AsMut, AsRef, From, Into}; /* * 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(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 { Self::from(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 { crate::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 { coords: crate::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 { #[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 { &*(self.coords.data.ptr() as *const mint::$PT) } } } impl AsMut> for Point where N: Scalar { #[inline] fn as_mut(&mut self) -> &mut mint::$PT { unsafe { &mut *(self.coords.data.ptr_mut() as *mut mint::$PT) } } } )*} ); // Implement for points of dimension 2, 3. #[cfg(feature = "mint")] impl_from_into_mint_1D!( U2 => Point2, Vector2[2]; U3 => Point3, Vector3[3]; ); impl From> for VectorN> where D: DimNameAdd, DefaultAllocator: Allocator + Allocator>, { #[inline] fn from(t: Point) -> Self { t.to_homogeneous() } } impl From> for Point where DefaultAllocator: Allocator, { #[inline] fn from(coords: VectorN) -> Self { Point { coords } } }