Merge pull request #943 from dimforge/point_dim_name

Add a OPoint type that takes type-level integers instead of const-generics
This commit is contained in:
Sébastien Crozet 2021-07-10 11:40:31 +02:00 committed by GitHub
commit 7bcb54641d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 271 additions and 182 deletions

View File

@ -4,6 +4,11 @@ documented here.
This project adheres to [Semantic Versioning](https://semver.org/). This project adheres to [Semantic Versioning](https://semver.org/).
## [0.28.0]
### Modified
- The `Point::new` constructors are no longer const-fn. This is due to some limitations in const-fn
not allowing custom trait-bounds. Use the `point!` macro instead to build points in const environments.
## [0.27.1] ## [0.27.1]
### Fixed ### Fixed
- Fixed a bug in the conversion from `glam::Vec2` or `glam::DVec2` to `Isometry2`. - Fixed a bug in the conversion from `glam::Vec2` or `glam::DVec2` to `Isometry2`.

View File

@ -17,7 +17,7 @@ use simba::simd::SimdPartialOrd;
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use crate::base::iter::{MatrixIter, MatrixIterMut}; use crate::base::iter::{MatrixIter, MatrixIterMut};
use crate::base::{Const, DefaultAllocator, OVector, SVector, Scalar}; use crate::base::{Const, DefaultAllocator, OVector, Scalar};
/// A point in an euclidean space. /// A point in an euclidean space.
/// ///
@ -40,35 +40,53 @@ use crate::base::{Const, DefaultAllocator, OVector, SVector, Scalar};
/// of said transformations for details. /// of said transformations for details.
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Point<T, const D: usize> { pub struct OPoint<T: Scalar, D: DimName>
where
DefaultAllocator: Allocator<T, D>,
{
/// The coordinates of this point, i.e., the shift from the origin. /// The coordinates of this point, i.e., the shift from the origin.
pub coords: SVector<T, D>, pub coords: OVector<T, D>,
} }
impl<T: Scalar + hash::Hash, const D: usize> hash::Hash for Point<T, D> { impl<T: Scalar + hash::Hash, D: DimName> hash::Hash for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) { fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.coords.hash(state) self.coords.hash(state)
} }
} }
impl<T: Scalar + Copy, const D: usize> Copy for Point<T, D> {} impl<T: Scalar + Copy, D: DimName> Copy for OPoint<T, D>
where
#[cfg(feature = "bytemuck")] DefaultAllocator: Allocator<T, D>,
unsafe impl<T: Scalar, const D: usize> bytemuck::Zeroable for Point<T, D> where OVector<T, D>: Copy,
SVector<T, D>: bytemuck::Zeroable
{ {
} }
#[cfg(feature = "bytemuck")] #[cfg(feature = "bytemuck")]
unsafe impl<T: Scalar, const D: usize> bytemuck::Pod for Point<T, D> unsafe impl<T: Scalar, D: DimName> bytemuck::Zeroable for OPoint<T, D>
where
OVector<T, D>: bytemuck::Zeroable,
DefaultAllocator: Allocator<T, D>,
{
}
#[cfg(feature = "bytemuck")]
unsafe impl<T: Scalar, D: DimName> bytemuck::Pod for OPoint<T, D>
where where
T: Copy, T: Copy,
SVector<T, D>: bytemuck::Pod, OVector<T, D>: bytemuck::Pod,
DefaultAllocator: Allocator<T, D>,
{ {
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<T: Scalar + Serialize, const D: usize> Serialize for Point<T, D> { impl<T: Scalar + Serialize, D: DimName> Serialize for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
<DefaultAllocator as Allocator<T, D>>::Buffer: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
@ -78,22 +96,27 @@ impl<T: Scalar + Serialize, const D: usize> Serialize for Point<T, D> {
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<'a, T: Scalar + Deserialize<'a>, const D: usize> Deserialize<'a> for Point<T, D> { impl<'a, T: Scalar + Deserialize<'a>, D: DimName> Deserialize<'a> for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
<DefaultAllocator as Allocator<T, D>>::Buffer: Deserialize<'a>,
{
fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error> fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
where where
Des: Deserializer<'a>, Des: Deserializer<'a>,
{ {
let coords = SVector::<T, D>::deserialize(deserializer)?; let coords = OVector::<T, D>::deserialize(deserializer)?;
Ok(Self::from(coords)) Ok(Self::from(coords))
} }
} }
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
impl<T, const D: usize> Abomonation for Point<T, D> impl<T, D: DimName> Abomonation for OPoint<T, D>
where where
T: Scalar, T: Scalar,
SVector<T, D>: Abomonation, OVector<T, D>: Abomonation,
DefaultAllocator: Allocator<T, D>,
{ {
unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> { unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
self.coords.entomb(writer) self.coords.entomb(writer)
@ -108,7 +131,10 @@ where
} }
} }
impl<T: Scalar, const D: usize> Point<T, D> { impl<T: Scalar, D: DimName> OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
/// Returns a point containing the result of `f` applied to each of its entries. /// Returns a point containing the result of `f` applied to each of its entries.
/// ///
/// # Example /// # Example
@ -123,7 +149,10 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]
pub fn map<T2: Scalar, F: FnMut(T) -> T2>(&self, f: F) -> Point<T2, D> { pub fn map<T2: Scalar, F: FnMut(T) -> T2>(&self, f: F) -> OPoint<T2, D>
where
DefaultAllocator: Allocator<T2, D>,
{
self.coords.map(f).into() self.coords.map(f).into()
} }
@ -163,20 +192,21 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_homogeneous(&self) -> OVector<T, DimNameSum<Const<D>, U1>> pub fn to_homogeneous(&self) -> OVector<T, DimNameSum<D, U1>>
where where
T: One, T: One,
Const<D>: DimNameAdd<U1>, D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
{ {
let mut res = unsafe { let mut res = unsafe {
crate::unimplemented_or_uninitialized_generic!( crate::unimplemented_or_uninitialized_generic!(
<DimNameSum<Const<D>, U1> as DimName>::name(), <DimNameSum<D, U1> as DimName>::name(),
Const::<1> Const::<1>
) )
}; };
res.fixed_slice_mut::<D, 1>(0, 0).copy_from(&self.coords); res.generic_slice_mut((0, 0), (D::name(), Const::<1>))
res[(D, 0)] = T::one(); .copy_from(&self.coords);
res[(D::dim(), 0)] = T::one();
res res
} }
@ -184,7 +214,7 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// Creates a new point with the given coordinates. /// Creates a new point with the given coordinates.
#[deprecated(note = "Use Point::from(vector) instead.")] #[deprecated(note = "Use Point::from(vector) instead.")]
#[inline] #[inline]
pub fn from_coordinates(coords: SVector<T, D>) -> Self { pub fn from_coordinates(coords: OVector<T, D>) -> Self {
Self { coords } Self { coords }
} }
@ -243,8 +273,7 @@ impl<T: Scalar, const D: usize> Point<T, D> {
#[inline] #[inline]
pub fn iter( pub fn iter(
&self, &self,
) -> MatrixIter<T, Const<D>, Const<1>, <DefaultAllocator as Allocator<T, Const<D>>>::Buffer> ) -> MatrixIter<T, D, Const<1>, <DefaultAllocator as Allocator<T, D>>::Buffer> {
{
self.coords.iter() self.coords.iter()
} }
@ -270,8 +299,7 @@ impl<T: Scalar, const D: usize> Point<T, D> {
#[inline] #[inline]
pub fn iter_mut( pub fn iter_mut(
&mut self, &mut self,
) -> MatrixIterMut<T, Const<D>, Const<1>, <DefaultAllocator as Allocator<T, Const<D>>>::Buffer> ) -> MatrixIterMut<T, D, Const<1>, <DefaultAllocator as Allocator<T, D>>::Buffer> {
{
self.coords.iter_mut() self.coords.iter_mut()
} }
@ -289,9 +317,10 @@ impl<T: Scalar, const D: usize> Point<T, D> {
} }
} }
impl<T: Scalar + AbsDiffEq, const D: usize> AbsDiffEq for Point<T, D> impl<T: Scalar + AbsDiffEq, D: DimName> AbsDiffEq for OPoint<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
DefaultAllocator: Allocator<T, D>,
{ {
type Epsilon = T::Epsilon; type Epsilon = T::Epsilon;
@ -306,9 +335,10 @@ where
} }
} }
impl<T: Scalar + RelativeEq, const D: usize> RelativeEq for Point<T, D> impl<T: Scalar + RelativeEq, D: DimName> RelativeEq for OPoint<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
DefaultAllocator: Allocator<T, D>,
{ {
#[inline] #[inline]
fn default_max_relative() -> Self::Epsilon { fn default_max_relative() -> Self::Epsilon {
@ -327,9 +357,10 @@ where
} }
} }
impl<T: Scalar + UlpsEq, const D: usize> UlpsEq for Point<T, D> impl<T: Scalar + UlpsEq, D: DimName> UlpsEq for OPoint<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
DefaultAllocator: Allocator<T, D>,
{ {
#[inline] #[inline]
fn default_max_ulps() -> u32 { fn default_max_ulps() -> u32 {
@ -342,16 +373,22 @@ where
} }
} }
impl<T: Scalar + Eq, const D: usize> Eq for Point<T, D> {} impl<T: Scalar + Eq, D: DimName> Eq for OPoint<T, D> where DefaultAllocator: Allocator<T, D> {}
impl<T: Scalar, const D: usize> PartialEq for Point<T, D> { impl<T: Scalar, D: DimName> PartialEq for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
#[inline] #[inline]
fn eq(&self, right: &Self) -> bool { fn eq(&self, right: &Self) -> bool {
self.coords == right.coords self.coords == right.coords
} }
} }
impl<T: Scalar + PartialOrd, const D: usize> PartialOrd for Point<T, D> { impl<T: Scalar + PartialOrd, D: DimName> PartialOrd for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
#[inline] #[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.coords.partial_cmp(&other.coords) self.coords.partial_cmp(&other.coords)
@ -381,25 +418,28 @@ impl<T: Scalar + PartialOrd, const D: usize> PartialOrd for Point<T, D> {
/* /*
* inf/sup * inf/sup
*/ */
impl<T: Scalar + SimdPartialOrd, const D: usize> Point<T, D> { impl<T: Scalar + SimdPartialOrd, D: DimName> OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
/// Computes the infimum (aka. componentwise min) of two points. /// Computes the infimum (aka. componentwise min) of two points.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn inf(&self, other: &Self) -> Point<T, D> { pub fn inf(&self, other: &Self) -> OPoint<T, D> {
self.coords.inf(&other.coords).into() self.coords.inf(&other.coords).into()
} }
/// Computes the supremum (aka. componentwise max) of two points. /// Computes the supremum (aka. componentwise max) of two points.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn sup(&self, other: &Self) -> Point<T, D> { pub fn sup(&self, other: &Self) -> OPoint<T, D> {
self.coords.sup(&other.coords).into() self.coords.sup(&other.coords).into()
} }
/// Computes the (infimum, supremum) of two points. /// Computes the (infimum, supremum) of two points.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn inf_sup(&self, other: &Self) -> (Point<T, D>, Point<T, D>) { pub fn inf_sup(&self, other: &Self) -> (OPoint<T, D>, OPoint<T, D>) {
let (inf, sup) = self.coords.inf_sup(&other.coords); let (inf, sup) = self.coords.inf_sup(&other.coords);
(inf.into(), sup.into()) (inf.into(), sup.into())
} }
@ -410,7 +450,10 @@ impl<T: Scalar + SimdPartialOrd, const D: usize> Point<T, D> {
* Display * Display
* *
*/ */
impl<T: Scalar + fmt::Display, const D: usize> fmt::Display for Point<T, D> { impl<T: Scalar + fmt::Display, D: DimName> fmt::Display for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{")?; write!(f, "{{")?;

View File

@ -1,4 +1,8 @@
use crate::geometry::Point; use crate::geometry::OPoint;
use crate::Const;
/// A point with `D` elements.
pub type Point<T, const D: usize> = OPoint<T, Const<D>>;
/// A statically sized 1-dimensional column point. /// A statically sized 1-dimensional column point.
/// ///

View File

@ -10,22 +10,26 @@ use rand::{
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
use crate::base::{DefaultAllocator, SVector, Scalar}; use crate::base::{DefaultAllocator, Scalar};
use crate::{ use crate::{
Const, OVector, Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, Const, DimName, OPoint, OVector, Point1, Point2, Point3, Point4, Point5, Point6, Vector1,
Vector4, Vector5, Vector6, Vector2, Vector3, Vector4, Vector5, Vector6,
}; };
use simba::scalar::{ClosedDiv, SupersetOf}; use simba::scalar::{ClosedDiv, SupersetOf};
use crate::geometry::Point; use crate::geometry::Point;
/// # Other construction methods /// # Other construction methods
impl<T: Scalar, const D: usize> Point<T, D> { impl<T: Scalar, D: DimName> OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
/// Creates a new point with uninitialized coordinates. /// Creates a new point with uninitialized coordinates.
#[inline] #[inline]
pub unsafe fn new_uninitialized() -> Self { pub unsafe fn new_uninitialized() -> Self {
Self::from(crate::unimplemented_or_uninitialized_generic!( Self::from(crate::unimplemented_or_uninitialized_generic!(
Const::<D>, Const::<1> D::name(),
Const::<1>
)) ))
} }
@ -49,7 +53,7 @@ impl<T: Scalar, const D: usize> Point<T, D> {
where where
T: Zero, T: Zero,
{ {
Self::from(SVector::from_element(T::zero())) Self::from(OVector::from_element(T::zero()))
} }
/// Creates a new point from a slice. /// Creates a new point from a slice.
@ -68,7 +72,7 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// ``` /// ```
#[inline] #[inline]
pub fn from_slice(components: &[T]) -> Self { pub fn from_slice(components: &[T]) -> Self {
Self::from(SVector::from_row_slice(components)) Self::from(OVector::from_row_slice(components))
} }
/// Creates a new point from its homogeneous vector representation. /// Creates a new point from its homogeneous vector representation.
@ -102,14 +106,15 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// assert_eq!(pt, Some(Point2::new(1.0, 2.0))); /// assert_eq!(pt, Some(Point2::new(1.0, 2.0)));
/// ``` /// ```
#[inline] #[inline]
pub fn from_homogeneous(v: OVector<T, DimNameSum<Const<D>, U1>>) -> Option<Self> pub fn from_homogeneous(v: OVector<T, DimNameSum<D, U1>>) -> Option<Self>
where where
T: Scalar + Zero + One + ClosedDiv, T: Scalar + Zero + One + ClosedDiv,
Const<D>: DimNameAdd<U1>, D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
{ {
if !v[D].is_zero() { if !v[D::dim()].is_zero() {
let coords = v.fixed_slice::<D, 1>(0, 0) / v[D].inlined_clone(); let coords =
v.generic_slice((0, 0), (D::name(), Const::<1>)) / v[D::dim()].inlined_clone();
Some(Self::from(coords)) Some(Self::from(coords))
} else { } else {
None None
@ -125,9 +130,10 @@ impl<T: Scalar, const D: usize> Point<T, D> {
/// let pt2 = pt.cast::<f32>(); /// let pt2 = pt.cast::<f32>();
/// assert_eq!(pt2, Point2::new(1.0f32, 2.0)); /// assert_eq!(pt2, Point2::new(1.0f32, 2.0));
/// ``` /// ```
pub fn cast<To: Scalar>(self) -> Point<To, D> pub fn cast<To: Scalar>(self) -> OPoint<To, D>
where where
Point<To, D>: SupersetOf<Self>, OPoint<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D>,
{ {
crate::convert(self) crate::convert(self)
} }
@ -138,38 +144,43 @@ impl<T: Scalar, const D: usize> Point<T, D> {
* Traits that build points. * Traits that build points.
* *
*/ */
impl<T: Scalar + Bounded, const D: usize> Bounded for Point<T, D> { impl<T: Scalar + Bounded, D: DimName> Bounded for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
#[inline] #[inline]
fn max_value() -> Self { fn max_value() -> Self {
Self::from(SVector::max_value()) Self::from(OVector::max_value())
} }
#[inline] #[inline]
fn min_value() -> Self { fn min_value() -> Self {
Self::from(SVector::min_value()) Self::from(OVector::min_value())
} }
} }
#[cfg(feature = "rand-no-std")] #[cfg(feature = "rand-no-std")]
impl<T: Scalar, const D: usize> Distribution<Point<T, D>> for Standard impl<T: Scalar, D: DimName> Distribution<OPoint<T, D>> for Standard
where where
Standard: Distribution<T>, Standard: Distribution<T>,
DefaultAllocator: Allocator<T, D>,
{ {
/// Generate a `Point` where each coordinate is an independent variate from `[0, 1)`. /// Generate a `Point` where each coordinate is an independent variate from `[0, 1)`.
#[inline] #[inline]
fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> Point<T, D> { fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> OPoint<T, D> {
Point::from(rng.gen::<SVector<T, D>>()) OPoint::from(rng.gen::<OVector<T, D>>())
} }
} }
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]
impl<T: Scalar + Arbitrary + Send, const D: usize> Arbitrary for Point<T, D> impl<T: Scalar + Arbitrary + Send, D: DimName> Arbitrary for OPoint<T, D>
where where
<DefaultAllocator as Allocator<T, Const<D>>>::Buffer: Send, <DefaultAllocator as Allocator<T, D>>::Buffer: Send,
DefaultAllocator: Allocator<T, D>,
{ {
#[inline] #[inline]
fn arbitrary(g: &mut Gen) -> Self { fn arbitrary(g: &mut Gen) -> Self {
Self::from(SVector::arbitrary(g)) Self::from(OVector::arbitrary(g))
} }
} }
@ -181,7 +192,7 @@ where
// NOTE: the impl for Point1 is not with the others so that we // NOTE: the impl for Point1 is not with the others so that we
// can add a section with the impl block comment. // can add a section with the impl block comment.
/// # Construction from individual components /// # Construction from individual components
impl<T> Point1<T> { impl<T: Scalar> Point1<T> {
/// Initializes this point from its components. /// Initializes this point from its components.
/// ///
/// # Example /// # Example
@ -192,7 +203,7 @@ impl<T> Point1<T> {
/// assert_eq!(p.x, 1.0); /// assert_eq!(p.x, 1.0);
/// ``` /// ```
#[inline] #[inline]
pub const fn new(x: T) -> Self { pub fn new(x: T) -> Self {
Point { Point {
coords: Vector1::new(x), coords: Vector1::new(x),
} }
@ -200,13 +211,13 @@ impl<T> Point1<T> {
} }
macro_rules! componentwise_constructors_impl( macro_rules! componentwise_constructors_impl(
($($doc: expr; $Point: ident, $Vector: ident, $($args: ident:$irow: expr),*);* $(;)*) => {$( ($($doc: expr; $Point: ident, $Vector: ident, $($args: ident:$irow: expr),*);* $(;)*) => {$(
impl<T> $Point<T> { impl<T: Scalar> $Point<T> {
#[doc = "Initializes this point from its components."] #[doc = "Initializes this point from its components."]
#[doc = "# Example\n```"] #[doc = "# Example\n```"]
#[doc = $doc] #[doc = $doc]
#[doc = "```"] #[doc = "```"]
#[inline] #[inline]
pub const fn new($($args: T),*) -> Self { pub fn new($($args: T),*) -> Self {
Point { coords: $Vector::new($($args),*) } Point { coords: $Vector::new($($args),*) }
} }
} }

View File

@ -7,6 +7,7 @@ use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar}; use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar};
use crate::geometry::Point; use crate::geometry::Point;
use crate::{DimName, OPoint};
/* /*
* This file provides the following conversions: * This file provides the following conversions:
@ -16,67 +17,69 @@ use crate::geometry::Point;
* Point -> Vector (homogeneous) * Point -> Vector (homogeneous)
*/ */
impl<T1, T2, const D: usize> SubsetOf<Point<T2, D>> for Point<T1, D> impl<T1, T2, D: DimName> SubsetOf<OPoint<T2, D>> for OPoint<T1, D>
where where
T1: Scalar, T1: Scalar,
T2: Scalar + SupersetOf<T1>, T2: Scalar + SupersetOf<T1>,
DefaultAllocator: Allocator<T1, D> + Allocator<T2, D>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Point<T2, D> { fn to_superset(&self) -> OPoint<T2, D> {
Point::from(self.coords.to_superset()) OPoint::from(self.coords.to_superset())
} }
#[inline] #[inline]
fn is_in_subset(m: &Point<T2, D>) -> bool { fn is_in_subset(m: &OPoint<T2, D>) -> bool {
// TODO: is there a way to reuse the `.is_in_subset` from the matrix implementation of // TODO: is there a way to reuse the `.is_in_subset` from the matrix implementation of
// SubsetOf? // SubsetOf?
m.iter().all(|e| e.is_in_subset()) m.iter().all(|e| e.is_in_subset())
} }
#[inline] #[inline]
fn from_superset_unchecked(m: &Point<T2, D>) -> Self { fn from_superset_unchecked(m: &OPoint<T2, D>) -> Self {
Self::from(Matrix::from_superset_unchecked(&m.coords)) Self::from(Matrix::from_superset_unchecked(&m.coords))
} }
} }
impl<T1, T2, const D: usize> SubsetOf<OVector<T2, DimNameSum<Const<D>, U1>>> for Point<T1, D> impl<T1, T2, D> SubsetOf<OVector<T2, DimNameSum<D, U1>>> for OPoint<T1, D>
where where
Const<D>: DimNameAdd<U1>, D: DimNameAdd<U1>,
T1: Scalar, T1: Scalar,
T2: Scalar + Zero + One + ClosedDiv + SupersetOf<T1>, T2: Scalar + Zero + One + ClosedDiv + SupersetOf<T1>,
DefaultAllocator: DefaultAllocator: Allocator<T1, D>
Allocator<T1, DimNameSum<Const<D>, U1>> + Allocator<T2, DimNameSum<Const<D>, U1>>, + Allocator<T2, D>
+ Allocator<T1, DimNameSum<D, U1>>
+ Allocator<T2, DimNameSum<D, U1>>,
// + Allocator<T1, D> // + Allocator<T1, D>
// + Allocator<T2, D>, // + Allocator<T2, D>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> OVector<T2, DimNameSum<Const<D>, U1>> { fn to_superset(&self) -> OVector<T2, DimNameSum<D, U1>> {
let p: Point<T2, D> = self.to_superset(); let p: OPoint<T2, D> = self.to_superset();
p.to_homogeneous() p.to_homogeneous()
} }
#[inline] #[inline]
fn is_in_subset(v: &OVector<T2, DimNameSum<Const<D>, U1>>) -> bool { fn is_in_subset(v: &OVector<T2, DimNameSum<D, U1>>) -> bool {
crate::is_convertible::<_, OVector<T1, DimNameSum<Const<D>, U1>>>(v) && !v[D].is_zero() crate::is_convertible::<_, OVector<T1, DimNameSum<D, U1>>>(v) && !v[D::dim()].is_zero()
} }
#[inline] #[inline]
fn from_superset_unchecked(v: &OVector<T2, DimNameSum<Const<D>, U1>>) -> Self { fn from_superset_unchecked(v: &OVector<T2, DimNameSum<D, U1>>) -> Self {
let coords = v.fixed_slice::<D, 1>(0, 0) / v[D].inlined_clone(); let coords = v.generic_slice((0, 0), (D::name(), Const::<1>)) / v[D::dim()].inlined_clone();
Self { Self {
coords: crate::convert_unchecked(coords), coords: crate::convert_unchecked(coords),
} }
} }
} }
impl<T: Scalar + Zero + One, const D: usize> From<Point<T, D>> impl<T: Scalar + Zero + One, D: DimName> From<OPoint<T, D>> for OVector<T, DimNameSum<D, U1>>
for OVector<T, DimNameSum<Const<D>, U1>>
where where
Const<D>: DimNameAdd<U1>, D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<D, U1>> + Allocator<T, D>,
{ {
#[inline] #[inline]
fn from(t: Point<T, D>) -> Self { fn from(t: OPoint<T, D>) -> Self {
t.to_homogeneous() t.to_homogeneous()
} }
} }
@ -97,10 +100,13 @@ impl<T: Scalar, const D: usize> From<Point<T, D>> for [T; D] {
} }
} }
impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Point<T, D> { impl<T: Scalar, D: DimName> From<OVector<T, D>> for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
#[inline] #[inline]
fn from(coords: OVector<T, Const<D>>) -> Self { fn from(coords: OVector<T, D>) -> Self {
Point { coords } OPoint { coords }
} }
} }

View File

@ -1,9 +1,9 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB};
use crate::base::Scalar; use crate::base::{Scalar, U1, U2, U3, U4, U5, U6};
use crate::geometry::Point; use crate::geometry::OPoint;
/* /*
* *
@ -12,8 +12,8 @@ use crate::geometry::Point;
*/ */
macro_rules! deref_impl( macro_rules! deref_impl(
($D: expr, $Target: ident $(, $comps: ident)*) => { ($D: ty, $Target: ident $(, $comps: ident)*) => {
impl<T: Scalar> Deref for Point<T, $D> impl<T: Scalar> Deref for OPoint<T, $D>
{ {
type Target = $Target<T>; type Target = $Target<T>;
@ -23,7 +23,7 @@ macro_rules! deref_impl(
} }
} }
impl<T: Scalar> DerefMut for Point<T, $D> impl<T: Scalar> DerefMut for OPoint<T, $D>
{ {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
@ -33,9 +33,9 @@ macro_rules! deref_impl(
} }
); );
deref_impl!(1, X, x); deref_impl!(U1, X, x);
deref_impl!(2, XY, x, y); deref_impl!(U2, XY, x, y);
deref_impl!(3, XYZ, x, y, z); deref_impl!(U3, XYZ, x, y, z);
deref_impl!(4, XYZW, x, y, z, w); deref_impl!(U4, XYZW, x, y, z, w);
deref_impl!(5, XYZWA, x, y, z, w, a); deref_impl!(U5, XYZWA, x, y, z, w, a);
deref_impl!(6, XYZWAB, x, y, z, w, a, b); deref_impl!(U6, XYZWAB, x, y, z, w, a, b);

View File

@ -8,18 +8,23 @@ use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
use crate::base::constraint::{ use crate::base::constraint::{
AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
}; };
use crate::base::dimension::{Dim, U1}; use crate::base::dimension::{Dim, DimName, U1};
use crate::base::storage::Storage; use crate::base::storage::Storage;
use crate::base::{Const, Matrix, SVector, Scalar, Vector}; use crate::base::{Const, Matrix, OVector, Scalar, Vector};
use crate::geometry::Point; use crate::allocator::Allocator;
use crate::geometry::{OPoint, Point};
use crate::DefaultAllocator;
/* /*
* *
* Indexing. * Indexing.
* *
*/ */
impl<T: Scalar, const D: usize> Index<usize> for Point<T, D> { impl<T: Scalar, D: DimName> Index<usize> for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
type Output = T; type Output = T;
#[inline] #[inline]
@ -28,7 +33,10 @@ impl<T: Scalar, const D: usize> Index<usize> for Point<T, D> {
} }
} }
impl<T: Scalar, const D: usize> IndexMut<usize> for Point<T, D> { impl<T: Scalar, D: DimName> IndexMut<usize> for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
#[inline] #[inline]
fn index_mut(&mut self, i: usize) -> &mut Self::Output { fn index_mut(&mut self, i: usize) -> &mut Self::Output {
&mut self.coords[i] &mut self.coords[i]
@ -40,7 +48,10 @@ impl<T: Scalar, const D: usize> IndexMut<usize> for Point<T, D> {
* Neg. * Neg.
* *
*/ */
impl<T: Scalar + ClosedNeg, const D: usize> Neg for Point<T, D> { impl<T: Scalar + ClosedNeg, D: DimName> Neg for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{
type Output = Self; type Output = Self;
#[inline] #[inline]
@ -49,8 +60,11 @@ impl<T: Scalar + ClosedNeg, const D: usize> Neg for Point<T, D> {
} }
} }
impl<'a, T: Scalar + ClosedNeg, const D: usize> Neg for &'a Point<T, D> { impl<'a, T: Scalar + ClosedNeg, D: DimName> Neg for &'a OPoint<T, D>
type Output = Point<T, D>; where
DefaultAllocator: Allocator<T, D>,
{
type Output = OPoint<T, D>;
#[inline] #[inline]
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
@ -66,102 +80,103 @@ impl<'a, T: Scalar + ClosedNeg, const D: usize> Neg for &'a Point<T, D> {
// Point - Point // Point - Point
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D>, U1), (Const<D>, U1) -> (Const<D>, U1) (D, U1), (D, U1) -> (D, U1)
const D; for; where; const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
self: &'a Point<T, D>, right: &'b Point<T, D>, Output = SVector<T, D>; self: &'a OPoint<T, D>, right: &'b OPoint<T, D>, Output = OVector<T, D>;
&self.coords - &right.coords; 'a, 'b); &self.coords - &right.coords; 'a, 'b);
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D>, U1), (Const<D>, U1) -> (Const<D>, U1) (D, U1), (D, U1) -> (D, U1)
const D; for; where; const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
self: &'a Point<T, D>, right: Point<T, D>, Output = SVector<T, D>; self: &'a OPoint<T, D>, right: OPoint<T, D>, Output = OVector<T, D>;
&self.coords - right.coords; 'a); &self.coords - right.coords; 'a);
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D>, U1), (Const<D>, U1) -> (Const<D>, U1) (D, U1), (D, U1) -> (D, U1)
const D; for; where; const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
self: Point<T, D>, right: &'b Point<T, D>, Output = SVector<T, D>; self: OPoint<T, D>, right: &'b OPoint<T, D>, Output = OVector<T, D>;
self.coords - &right.coords; 'b); self.coords - &right.coords; 'b);
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D>, U1), (Const<D>, U1) -> (Const<D>, U1) (D, U1), (D, U1) -> (D, U1)
const D; for; where; const; for D; where D: DimName, DefaultAllocator: Allocator<T, D>;
self: Point<T, D>, right: Point<T, D>, Output = SVector<T, D>; self: OPoint<T, D>, right: OPoint<T, D>, Output = OVector<T, D>;
self.coords - right.coords; ); self.coords - right.coords; );
// Point - Vector // Point - Vector
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: &'a Point<T, D1>, right: &'b Vector<T, D2, SB>, Output = Point<T, D1>; self: &'a OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(&self.coords - right); 'a, 'b); Self::Output::from(&self.coords - right); 'a, 'b);
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: &'a Point<T, D1>, right: Vector<T, D2, SB>, Output = Point<T, D1>; self: &'a OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(&self.coords - &right); 'a); // TODO: should not be a ref to `right`. Self::Output::from(&self.coords - &right); 'a); // TODO: should not be a ref to `right`.
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: Point<T, D1>, right: &'b Vector<T, D2, SB>, Output = Point<T, D1>; self: OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(self.coords - right); 'b); Self::Output::from(self.coords - right); 'b);
add_sub_impl!(Sub, sub, ClosedSub; add_sub_impl!(Sub, sub, ClosedSub;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: Point<T, D1>, right: Vector<T, D2, SB>, Output = Point<T, D1>; self: OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(self.coords - right); ); Self::Output::from(self.coords - right); );
// Point + Vector // Point + Vector
add_sub_impl!(Add, add, ClosedAdd; add_sub_impl!(Add, add, ClosedAdd;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: &'a Point<T, D1>, right: &'b Vector<T, D2, SB>, Output = Point<T, D1>; self: &'a OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(&self.coords + right); 'a, 'b); Self::Output::from(&self.coords + right); 'a, 'b);
add_sub_impl!(Add, add, ClosedAdd; add_sub_impl!(Add, add, ClosedAdd;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: &'a Point<T, D1>, right: Vector<T, D2, SB>, Output = Point<T, D1>; self: &'a OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(&self.coords + &right); 'a); // TODO: should not be a ref to `right`. Self::Output::from(&self.coords + &right); 'a); // TODO: should not be a ref to `right`.
add_sub_impl!(Add, add, ClosedAdd; add_sub_impl!(Add, add, ClosedAdd;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: Point<T, D1>, right: &'b Vector<T, D2, SB>, Output = Point<T, D1>; self: OPoint<T, D1>, right: &'b Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(self.coords + right); 'b); Self::Output::from(self.coords + right); 'b);
add_sub_impl!(Add, add, ClosedAdd; add_sub_impl!(Add, add, ClosedAdd;
(Const<D1>, U1), (D2, U1) -> (Const<D1>, U1) (D1, U1), (D2, U1) -> (D1, U1)
const D1; const;
for D2, SB; for D1, D2, SB;
where D2: Dim, SB: Storage<T, D2>; where D1: DimName, D2: Dim, SB: Storage<T, D2>, DefaultAllocator: Allocator<T, D1>;
self: Point<T, D1>, right: Vector<T, D2, SB>, Output = Point<T, D1>; self: OPoint<T, D1>, right: Vector<T, D2, SB>, Output = OPoint<T, D1>;
Self::Output::from(self.coords + right); ); Self::Output::from(self.coords + right); );
// TODO: replace by the shared macro: add_sub_assign_impl? // TODO: replace by the shared macro: add_sub_assign_impl?
macro_rules! op_assign_impl( macro_rules! op_assign_impl(
($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$( ($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$(
impl<'b, T, D2: Dim, SB, const D1: usize> $TraitAssign<&'b Vector<T, D2, SB>> for Point<T, D1> impl<'b, T, D1: DimName, D2: Dim, SB> $TraitAssign<&'b Vector<T, D2, SB>> for OPoint<T, D1>
where T: Scalar + $bound, where T: Scalar + $bound,
SB: Storage<T, D2>, SB: Storage<T, D2>,
ShapeConstraint: SameNumberOfRows<Const<D1>, D2> { ShapeConstraint: SameNumberOfRows<D1, D2>,
DefaultAllocator: Allocator<T, D1> {
#[inline] #[inline]
fn $method_assign(&mut self, right: &'b Vector<T, D2, SB>) { fn $method_assign(&mut self, right: &'b Vector<T, D2, SB>) {
@ -169,10 +184,11 @@ macro_rules! op_assign_impl(
} }
} }
impl<T, D2: Dim, SB, const D1: usize> $TraitAssign<Vector<T, D2, SB>> for Point<T, D1> impl<T, D1: DimName, D2: Dim, SB> $TraitAssign<Vector<T, D2, SB>> for OPoint<T, D1>
where T: Scalar + $bound, where T: Scalar + $bound,
SB: Storage<T, D2>, SB: Storage<T, D2>,
ShapeConstraint: SameNumberOfRows<Const<D1>, D2> { ShapeConstraint: SameNumberOfRows<D1, D2>,
DefaultAllocator: Allocator<T, D1> {
#[inline] #[inline]
fn $method_assign(&mut self, right: Vector<T, D2, SB>) { fn $method_assign(&mut self, right: Vector<T, D2, SB>) {
@ -214,28 +230,30 @@ md_impl_all!(
macro_rules! componentwise_scalarop_impl( macro_rules! componentwise_scalarop_impl(
($Trait: ident, $method: ident, $bound: ident; ($Trait: ident, $method: ident, $bound: ident;
$TraitAssign: ident, $method_assign: ident) => { $TraitAssign: ident, $method_assign: ident) => {
impl<T: Scalar + $bound, const D: usize> $Trait<T> for Point<T, D> impl<T: Scalar + $bound, D: DimName> $Trait<T> for OPoint<T, D>
where DefaultAllocator: Allocator<T, D>
{ {
type Output = Point<T, D>; type Output = OPoint<T, D>;
#[inline] #[inline]
fn $method(self, right: T) -> Self::Output { fn $method(self, right: T) -> Self::Output {
Point::from(self.coords.$method(right)) OPoint::from(self.coords.$method(right))
} }
} }
impl<'a, T: Scalar + $bound, const D: usize> $Trait<T> for &'a Point<T, D> impl<'a, T: Scalar + $bound, D: DimName> $Trait<T> for &'a OPoint<T, D>
where DefaultAllocator: Allocator<T, D>
{ {
type Output = Point<T, D>; type Output = OPoint<T, D>;
#[inline] #[inline]
fn $method(self, right: T) -> Self::Output { fn $method(self, right: T) -> Self::Output {
Point::from((&self.coords).$method(right)) OPoint::from((&self.coords).$method(right))
} }
} }
impl<T: Scalar + $bound, const D: usize> $TraitAssign<T> for Point<T, D> impl<T: Scalar + $bound, D: DimName> $TraitAssign<T> for OPoint<T, D>
/* where DefaultAllocator: Allocator<T, D> */ where DefaultAllocator: Allocator<T, D>
{ {
#[inline] #[inline]
fn $method_assign(&mut self, right: T) { fn $method_assign(&mut self, right: T) {
@ -250,23 +268,25 @@ componentwise_scalarop_impl!(Div, div, ClosedDiv; DivAssign, div_assign);
macro_rules! left_scalar_mul_impl( macro_rules! left_scalar_mul_impl(
($($T: ty),* $(,)*) => {$( ($($T: ty),* $(,)*) => {$(
impl<const D: usize> Mul<Point<$T, D>> for $T impl<D: DimName> Mul<OPoint<$T, D>> for $T
where DefaultAllocator: Allocator<$T, D>
{ {
type Output = Point<$T, D>; type Output = OPoint<$T, D>;
#[inline] #[inline]
fn mul(self, right: Point<$T, D>) -> Self::Output { fn mul(self, right: OPoint<$T, D>) -> Self::Output {
Point::from(self * right.coords) OPoint::from(self * right.coords)
} }
} }
impl<'b, const D: usize> Mul<&'b Point<$T, D>> for $T impl<'b, D: DimName> Mul<&'b OPoint<$T, D>> for $T
where DefaultAllocator: Allocator<$T, D>
{ {
type Output = Point<$T, D>; type Output = OPoint<$T, D>;
#[inline] #[inline]
fn mul(self, right: &'b Point<$T, D>) -> Self::Output { fn mul(self, right: &'b OPoint<$T, D>) -> Self::Output {
Point::from(self * &right.coords) OPoint::from(self * &right.coords)
} }
} }
)*} )*}