Add "cast" methods to cast the type of the components of most nalgebra types.

This commit is contained in:
Crozet Sébastien 2021-03-05 17:08:46 +01:00
parent f282d02db1
commit f2c49aecb0
10 changed files with 298 additions and 26 deletions

View File

@ -16,7 +16,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation; use abomonation::Abomonation;
use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field}; use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field, SupersetOf};
use simba::simd::SimdPartialOrd; use simba::simd::SimdPartialOrd;
use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
@ -610,6 +610,23 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
res res
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Vector3;
/// let q = Vector3::new(1.0f64, 2.0, 3.0);
/// let q2 = q.cast::<f32>();
/// assert_eq!(q2, Vector3::new(1.0f32, 2.0, 3.0));
/// ```
pub fn cast<N2: Scalar>(self) -> MatrixMN<N2, R, C>
where
MatrixMN<N2, R, C>: SupersetOf<Self>,
DefaultAllocator: Allocator<N2, R, C>,
{
crate::convert(self)
}
/// Similar to `self.iter().fold(init, f)` except that `init` is replaced by a closure. /// Similar to `self.iter().fold(init, f)` except that `init` is replaced by a closure.
/// ///
/// The initialization closure is given the first component of this matrix: /// The initialization closure is given the first component of this matrix:

View File

@ -5,6 +5,7 @@ use crate::{
use num::{One, Zero}; use num::{One, Zero};
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen}; use quickcheck::{Arbitrary, Gen};
use simba::scalar::SupersetOf;
impl<N: Scalar> DualQuaternion<N> { impl<N: Scalar> DualQuaternion<N> {
/// Creates a dual quaternion from its rotation and translation components. /// Creates a dual quaternion from its rotation and translation components.
@ -49,6 +50,22 @@ impl<N: Scalar> DualQuaternion<N> {
Quaternion::from_real(N::zero()), Quaternion::from_real(N::zero()),
) )
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::{Quaternion, DualQuaternion};
/// let q = DualQuaternion::from_real(Quaternion::new(1.0f64, 2.0, 3.0, 4.0));
/// let q2 = q.cast::<f32>();
/// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0)));
/// ```
pub fn cast<To: Scalar>(self) -> DualQuaternion<To>
where
DualQuaternion<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> DualQuaternion<N> impl<N: SimdRealField> DualQuaternion<N>
@ -129,6 +146,22 @@ impl<N: SimdRealField> UnitDualQuaternion<N> {
pub fn identity() -> Self { pub fn identity() -> Self {
Self::new_unchecked(DualQuaternion::identity()) Self::new_unchecked(DualQuaternion::identity())
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::UnitDualQuaternion;
/// let q = UnitDualQuaternion::<f64>::identity();
/// let q2 = q.cast::<f32>();
/// assert_eq!(q2, UnitDualQuaternion::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> UnitDualQuaternion<To>
where
UnitDualQuaternion<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> UnitDualQuaternion<N> impl<N: SimdRealField> UnitDualQuaternion<N>

View File

@ -10,15 +10,16 @@ use rand::{
Rng, Rng,
}; };
use simba::scalar::SupersetOf;
use simba::simd::SimdRealField; use simba::simd::SimdRealField;
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, U2}; use crate::base::dimension::{DimName, U2};
use crate::base::{DefaultAllocator, Vector2, Vector3}; use crate::base::{DefaultAllocator, Vector2, Vector3};
use crate::geometry::{ use crate::{
AbstractRotation, Isometry, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Point, AbstractRotation, Isometry, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Point,
Point3, Rotation, Rotation3, Translation, Translation2, Translation3, UnitComplex, Point3, Rotation, Rotation3, Scalar, Translation, Translation2, Translation3, UnitComplex,
UnitQuaternion, UnitQuaternion,
}; };
@ -153,6 +154,22 @@ where
pub fn rotation(angle: N) -> Self { pub fn rotation(angle: N) -> Self {
Self::new(Vector2::zeros(), angle) Self::new(Vector2::zeros(), angle)
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::IsometryMatrix2;
/// let iso = IsometryMatrix2::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, IsometryMatrix2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> IsometryMatrix2<To>
where
IsometryMatrix2<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> Isometry2<N> impl<N: SimdRealField> Isometry2<N>
@ -191,6 +208,22 @@ where
pub fn rotation(angle: N) -> Self { pub fn rotation(angle: N) -> Self {
Self::new(Vector2::zeros(), angle) Self::new(Vector2::zeros(), angle)
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Isometry2;
/// let iso = Isometry2::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, Isometry2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Isometry2<To>
where
Isometry2<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
// 3D rotation. // 3D rotation.
@ -387,6 +420,22 @@ where
N::Element: SimdRealField, N::Element: SimdRealField,
{ {
basic_isometry_construction_impl!(UnitQuaternion<N>); basic_isometry_construction_impl!(UnitQuaternion<N>);
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Isometry3;
/// let iso = Isometry3::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, Isometry3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Isometry3<To>
where
Isometry3<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> IsometryMatrix3<N> impl<N: SimdRealField> IsometryMatrix3<N>
@ -394,6 +443,22 @@ where
N::Element: SimdRealField, N::Element: SimdRealField,
{ {
basic_isometry_construction_impl!(Rotation3<N>); basic_isometry_construction_impl!(Rotation3<N>);
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::IsometryMatrix3;
/// let iso = IsometryMatrix3::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, IsometryMatrix3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> IsometryMatrix3<To>
where
IsometryMatrix3<To>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
/// # Construction from a 3D eye position and target point /// # Construction from a 3D eye position and target point

View File

@ -15,7 +15,7 @@ use crate::{
Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, Vector4, Vector5, Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, Vector4, Vector5,
Vector6, Vector6,
}; };
use simba::scalar::ClosedDiv; use simba::scalar::{ClosedDiv, SupersetOf};
use crate::geometry::Point; use crate::geometry::Point;
@ -119,6 +119,23 @@ where
None None
} }
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Point2;
/// let pt = Point2::new(1.0f64, 2.0);
/// let pt2 = pt.cast::<f32>();
/// assert_eq!(pt2, Point2::new(1.0f32, 2.0));
/// ```
pub fn cast<To: Scalar>(self) -> Point<To, D>
where
Point<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D>,
{
crate::convert(self)
}
} }
/* /*

View File

@ -13,7 +13,7 @@ use rand::{
use num::{One, Zero}; use num::{One, Zero};
use simba::scalar::RealField; use simba::scalar::{RealField, SupersetOf};
use simba::simd::SimdBool; use simba::simd::SimdBool;
use crate::base::dimension::U3; use crate::base::dimension::U3;
@ -49,6 +49,22 @@ impl<N: Scalar> Quaternion<N> {
pub fn new(w: N, i: N, j: N, k: N) -> Self { pub fn new(w: N, i: N, j: N, k: N) -> Self {
Self::from(Vector4::new(i, j, k, w)) Self::from(Vector4::new(i, j, k, w))
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Quaternion;
/// let q = Quaternion::new(1.0f64, 2.0, 3.0, 4.0);
/// let q2 = q.cast::<f32>();
/// assert_eq!(q2, Quaternion::new(1.0f32, 2.0, 3.0, 4.0));
/// ```
pub fn cast<To: Scalar>(self) -> Quaternion<To>
where
To: SupersetOf<N>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> Quaternion<N> { impl<N: SimdRealField> Quaternion<N> {
@ -199,6 +215,23 @@ where
Self::new_unchecked(Quaternion::identity()) Self::new_unchecked(Quaternion::identity())
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::UnitQuaternion;
/// # use approx::assert_relative_eq;
/// let q = UnitQuaternion::from_euler_angles(1.0f64, 2.0, 3.0);
/// let q2 = q.cast::<f32>();
/// assert_relative_eq!(q2, UnitQuaternion::from_euler_angles(1.0f32, 2.0, 3.0), epsilon = 1.0e-6);
/// ```
pub fn cast<To: Scalar>(self) -> UnitQuaternion<To>
where
To: SupersetOf<N>,
{
crate::convert(self)
}
/// Creates a new quaternion from a unit vector (the rotation axis) and an angle /// Creates a new quaternion from a unit vector (the rotation axis) and an angle
/// (the rotation angle). /// (the rotation angle).
/// ///

View File

@ -35,8 +35,8 @@ use crate::geometry::{
impl<N1, N2> SubsetOf<Quaternion<N2>> for Quaternion<N1> impl<N1, N2> SubsetOf<Quaternion<N2>> for Quaternion<N1>
where where
N1: SimdRealField, N1: Scalar,
N2: SimdRealField + SupersetOf<N1>, N2: Scalar + SupersetOf<N1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Quaternion<N2> { fn to_superset(&self) -> Quaternion<N2> {
@ -58,8 +58,8 @@ where
impl<N1, N2> SubsetOf<UnitQuaternion<N2>> for UnitQuaternion<N1> impl<N1, N2> SubsetOf<UnitQuaternion<N2>> for UnitQuaternion<N1>
where where
N1: SimdRealField, N1: Scalar,
N2: SimdRealField + SupersetOf<N1>, N2: Scalar + SupersetOf<N1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> UnitQuaternion<N2> { fn to_superset(&self) -> UnitQuaternion<N2> {

View File

@ -1,6 +1,6 @@
use num::{One, Zero}; use num::{One, Zero};
use simba::scalar::{ClosedAdd, ClosedMul}; use simba::scalar::{ClosedAdd, ClosedMul, SupersetOf};
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::DimName; use crate::base::dimension::DimName;
@ -31,6 +31,28 @@ where
} }
} }
impl<N: Scalar, D: DimName> Rotation<N, D>
where
DefaultAllocator: Allocator<N, D, D>,
{
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Rotation2;
/// let rot = Rotation2::<f64>::identity();
/// let rot2 = rot.cast::<f32>();
/// assert_eq!(rot2, Rotation2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Rotation<To, D>
where
Rotation<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D, D>,
{
crate::convert(self)
}
}
impl<N, D: DimName> One for Rotation<N, D> impl<N, D: DimName> One for Rotation<N, D>
where where
N: Scalar + Zero + One + ClosedAdd + ClosedMul, N: Scalar + Zero + One + ClosedAdd + ClosedMul,

View File

@ -10,15 +10,16 @@ use rand::{
Rng, Rng,
}; };
use simba::scalar::SupersetOf;
use simba::simd::SimdRealField; use simba::simd::SimdRealField;
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, U2, U3}; use crate::base::dimension::{DimName, U2, U3};
use crate::base::{DefaultAllocator, Vector2, Vector3}; use crate::base::{DefaultAllocator, Vector2, Vector3};
use crate::geometry::{ use crate::{
AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Scalar, Similarity,
UnitComplex, UnitQuaternion, Translation, UnitComplex, UnitQuaternion,
}; };
impl<N: SimdRealField, D: DimName, R> Similarity<N, D, R> impl<N: SimdRealField, D: DimName, R> Similarity<N, D, R>
@ -158,6 +159,22 @@ where
scaling, scaling,
) )
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::SimilarityMatrix2;
/// let sim = SimilarityMatrix2::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, SimilarityMatrix2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U2, Rotation2<To>>
where
Similarity<To, U2, Rotation2<To>>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
impl<N: SimdRealField> Similarity<N, U2, UnitComplex<N>> impl<N: SimdRealField> Similarity<N, U2, UnitComplex<N>>
@ -184,12 +201,28 @@ where
scaling, scaling,
) )
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Similarity2;
/// let sim = Similarity2::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, Similarity2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U2, UnitComplex<To>>
where
Similarity<To, U2, UnitComplex<To>>: SupersetOf<Self>,
{
crate::convert(self)
}
} }
// 3D rotation. // 3D rotation.
macro_rules! similarity_construction_impl( macro_rules! similarity_construction_impl(
($Rot: ty) => { ($Rot: ident) => {
impl<N: SimdRealField> Similarity<N, U3, $Rot> impl<N: SimdRealField> Similarity<N, U3, $Rot<N>>
where N::Element: SimdRealField { where N::Element: SimdRealField {
/// Creates a new similarity from a translation, rotation axis-angle, and scaling /// Creates a new similarity from a translation, rotation axis-angle, and scaling
/// factor. /// factor.
@ -219,7 +252,23 @@ macro_rules! similarity_construction_impl(
#[inline] #[inline]
pub fn new(translation: Vector3<N>, axisangle: Vector3<N>, scaling: N) -> Self pub fn new(translation: Vector3<N>, axisangle: Vector3<N>, scaling: N) -> Self
{ {
Self::from_isometry(Isometry::<_, U3, $Rot>::new(translation, axisangle), scaling) Self::from_isometry(Isometry::<_, U3, $Rot<N>>::new(translation, axisangle), scaling)
}
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Similarity3;
/// let sim = Similarity3::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, Similarity3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U3, $Rot<To>>
where
Similarity<To, U3, $Rot<To>>: SupersetOf<Self>,
{
crate::convert(self)
} }
/// Creates an similarity that corresponds to a scaling factor and a local frame of /// Creates an similarity that corresponds to a scaling factor and a local frame of
@ -260,7 +309,7 @@ macro_rules! similarity_construction_impl(
up: &Vector3<N>, up: &Vector3<N>,
scaling: N) scaling: N)
-> Self { -> Self {
Self::from_isometry(Isometry::<_, U3, $Rot>::face_towards(eye, target, up), scaling) Self::from_isometry(Isometry::<_, U3, $Rot<N>>::face_towards(eye, target, up), scaling)
} }
/// Deprecated: Use [SimilarityMatrix3::face_towards] instead. /// Deprecated: Use [SimilarityMatrix3::face_towards] instead.
@ -308,7 +357,7 @@ macro_rules! similarity_construction_impl(
up: &Vector3<N>, up: &Vector3<N>,
scaling: N) scaling: N)
-> Self { -> Self {
Self::from_isometry(Isometry::<_, U3, $Rot>::look_at_rh(eye, target, up), scaling) Self::from_isometry(Isometry::<_, U3, $Rot<N>>::look_at_rh(eye, target, up), scaling)
} }
/// Builds a left-handed look-at view matrix including a scaling factor. /// Builds a left-handed look-at view matrix including a scaling factor.
@ -346,11 +395,11 @@ macro_rules! similarity_construction_impl(
up: &Vector3<N>, up: &Vector3<N>,
scaling: N) scaling: N)
-> Self { -> Self {
Self::from_isometry(Isometry::<_, _, $Rot>::look_at_lh(eye, target, up), scaling) Self::from_isometry(Isometry::<_, _, $Rot<N>>::look_at_lh(eye, target, up), scaling)
} }
} }
} }
); );
similarity_construction_impl!(Rotation3<N>); similarity_construction_impl!(Rotation3);
similarity_construction_impl!(UnitQuaternion<N>); similarity_construction_impl!(UnitQuaternion);

View File

@ -10,7 +10,7 @@ use rand::{
Rng, Rng,
}; };
use simba::scalar::ClosedAdd; use simba::scalar::{ClosedAdd, SupersetOf};
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6}; use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6};
@ -18,7 +18,7 @@ use crate::base::{DefaultAllocator, Scalar, VectorN};
use crate::geometry::Translation; use crate::geometry::Translation;
impl<N: Scalar + Zero, D: DimName> Translation<N, D> impl<N: Scalar, D: DimName> Translation<N, D>
where where
DefaultAllocator: Allocator<N, D>, DefaultAllocator: Allocator<N, D>,
{ {
@ -37,9 +37,29 @@ where
/// assert_eq!(t * p, p); /// assert_eq!(t * p, p);
/// ``` /// ```
#[inline] #[inline]
pub fn identity() -> Translation<N, D> { pub fn identity() -> Translation<N, D>
where
N: Zero,
{
Self::from(VectorN::<N, D>::from_element(N::zero())) Self::from(VectorN::<N, D>::from_element(N::zero()))
} }
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Translation2;
/// let tra = Translation2::new(1.0f64, 2.0);
/// let tra2 = tra.cast::<f32>();
/// assert_eq!(tra2, Translation2::new(1.0f32, 2.0));
/// ```
pub fn cast<To: Scalar>(self) -> Translation<To, D>
where
Translation<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D>,
{
crate::convert(self)
}
} }
impl<N: Scalar + Zero + ClosedAdd, D: DimName> One for Translation<N, D> impl<N: Scalar + Zero + ClosedAdd, D: DimName> One for Translation<N, D>

View File

@ -12,9 +12,9 @@ use num_complex::Complex;
use crate::base::dimension::{U1, U2}; use crate::base::dimension::{U1, U2};
use crate::base::storage::Storage; use crate::base::storage::Storage;
use crate::base::{Matrix2, Unit, Vector, Vector2}; use crate::base::{Matrix2, Scalar, Unit, Vector, Vector2};
use crate::geometry::{Rotation2, UnitComplex}; use crate::geometry::{Rotation2, UnitComplex};
use simba::scalar::RealField; use simba::scalar::{RealField, SupersetOf};
use simba::simd::SimdRealField; use simba::simd::SimdRealField;
/// # Identity /// # Identity
@ -118,6 +118,22 @@ impl<N: SimdRealField> UnitComplex<N>
where where
N::Element: SimdRealField, N::Element: SimdRealField,
{ {
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::UnitComplex;
/// let c = UnitComplex::new(1.0f64);
/// let c2 = c.cast::<f32>();
/// assert_eq!(c2, UnitComplex::new(1.0f32));
/// ```
pub fn cast<To: Scalar>(self) -> UnitComplex<To>
where
UnitComplex<To>: SupersetOf<Self>,
{
crate::convert(self)
}
/// The underlying complex number. /// The underlying complex number.
/// ///
/// Same as `self.as_ref()`. /// Same as `self.as_ref()`.