Merge pull request #874 from dimforge/more_conversions

More conversions
This commit is contained in:
Sébastien Crozet 2021-04-27 13:40:24 +02:00 committed by GitHub
commit fb2147673b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 244 additions and 69 deletions

View File

@ -4,6 +4,16 @@ documented here.
This project adheres to [Semantic Versioning](https://semver.org/). This project adheres to [Semantic Versioning](https://semver.org/).
## [0.26.2]
###Added
- Conversion from an array `[T; D]` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion from a static vector `SVector<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion from a point `Point<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion of an array `[T; D]` from/to a translation `Translation<T, D>`.
- Conversion of a point `Point<T, D>` to a translation `Translation<T, D>`.
- Conversion of the tuple of glam types `(Vec3, Quat)` from/to an `Isometry2` or `Isometry3`.
- Conversion of a glam type `Vec2/3/4` from/to a `Translation2/3/4`.
## [0.26.1] ## [0.26.1]
Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`. Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`.

View File

@ -3,7 +3,6 @@ use alloc::vec::Vec;
use simba::scalar::{SubsetOf, SupersetOf}; use simba::scalar::{SubsetOf, SupersetOf};
use std::convert::{AsMut, AsRef, From, Into}; use std::convert::{AsMut, AsRef, From, Into};
use std::mem; use std::mem;
use std::ptr;
use simba::simd::{PrimitiveSimdValue, SimdValue}; use simba::simd::{PrimitiveSimdValue, SimdValue};
@ -24,6 +23,7 @@ use crate::base::{
use crate::base::{DVector, VecStorage}; use crate::base::{DVector, VecStorage};
use crate::base::{SliceStorage, SliceStorageMut}; use crate::base::{SliceStorage, SliceStorageMut};
use crate::constraint::DimEq; use crate::constraint::DimEq;
use crate::{SMatrix, SVector};
// TODO: too bad this won't work allo slice conversions. // TODO: too bad this won't work allo slice conversions.
impl<T1, T2, R1, C1, R2, C2> SubsetOf<OMatrix<T2, R2, C2>> for OMatrix<T1, R1, C1> impl<T1, T2, R1, C1, R2, C2> SubsetOf<OMatrix<T2, R2, C2>> for OMatrix<T1, R1, C1>
@ -103,35 +103,23 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator
} }
} }
impl<T: Scalar, const D: usize> From<[T; D]> for SVector<T, D> {
#[inline]
fn from(arr: [T; D]) -> Self {
unsafe { Self::from_data_statically_unchecked(ArrayStorage([arr; 1])) }
}
}
impl<T: Scalar, const D: usize> Into<[T; D]> for SVector<T, D> {
#[inline]
fn into(self) -> [T; D] {
// TODO: unfortunately, we must clone because we can move out of an array.
self.data.0[0].clone()
}
}
macro_rules! impl_from_into_asref_1D( macro_rules! impl_from_into_asref_1D(
($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$( ($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$(
impl<T> From<[T; $SZ]> for OMatrix<T, $NRows, $NCols>
where T: Scalar,
DefaultAllocator: Allocator<T, $NRows, $NCols> {
#[inline]
fn from(arr: [T; $SZ]) -> Self {
unsafe {
let mut res = Self::new_uninitialized();
ptr::copy_nonoverlapping(&arr[0], (*res.as_mut_ptr()).data.ptr_mut(), $SZ);
res.assume_init()
}
}
}
impl<T, S> Into<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
where T: Scalar,
S: ContiguousStorage<T, $NRows, $NCols> {
#[inline]
fn into(self) -> [T; $SZ] {
let mut res = mem::MaybeUninit::<[T; $SZ]>::uninit();
unsafe { ptr::copy_nonoverlapping(self.data.ptr(), res.as_mut_ptr() as *mut T, $SZ) };
unsafe { res.assume_init() }
}
}
impl<T, S> AsRef<[T; $SZ]> for Matrix<T, $NRows, $NCols, S> impl<T, S> AsRef<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
where T: Scalar, where T: Scalar,
S: ContiguousStorage<T, $NRows, $NCols> { S: ContiguousStorage<T, $NRows, $NCols> {
@ -171,33 +159,22 @@ impl_from_into_asref_1D!(
(U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16; (U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16;
); );
impl<T: Scalar, const R: usize, const C: usize> From<[[T; R]; C]> for SMatrix<T, R, C> {
#[inline]
fn from(arr: [[T; R]; C]) -> Self {
unsafe { Self::from_data_statically_unchecked(ArrayStorage(arr)) }
}
}
impl<T: Scalar, const R: usize, const C: usize> Into<[[T; R]; C]> for SMatrix<T, R, C> {
#[inline]
fn into(self) -> [[T; R]; C] {
self.data.0
}
}
macro_rules! impl_from_into_asref_2D( macro_rules! impl_from_into_asref_2D(
($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$( ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
impl<T: Scalar> From<[[T; $SZRows]; $SZCols]> for OMatrix<T, $NRows, $NCols>
where DefaultAllocator: Allocator<T, $NRows, $NCols> {
#[inline]
fn from(arr: [[T; $SZRows]; $SZCols]) -> Self {
unsafe {
let mut res = Self::new_uninitialized();
ptr::copy_nonoverlapping(&arr[0][0], (*res.as_mut_ptr()).data.ptr_mut(), $SZRows * $SZCols);
res.assume_init()
}
}
}
impl<T: Scalar, S> Into<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
where S: ContiguousStorage<T, $NRows, $NCols> {
#[inline]
fn into(self) -> [[T; $SZRows]; $SZCols] {
let mut res = mem::MaybeUninit::<[[T; $SZRows]; $SZCols]>::uninit();
unsafe { ptr::copy_nonoverlapping(self.data.ptr(), res.as_mut_ptr() as *mut T, $SZRows * $SZCols) };
unsafe { res.assume_init() }
}
}
impl<T: Scalar, S> AsRef<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S> impl<T: Scalar, S> AsRef<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
where S: ContiguousStorage<T, $NRows, $NCols> { where S: ContiguousStorage<T, $NRows, $NCols> {
#[inline] #[inline]

View File

@ -9,6 +9,7 @@ use crate::geometry::{
AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform, AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform,
Translation, UnitDualQuaternion, UnitQuaternion, Translation, UnitDualQuaternion, UnitQuaternion,
}; };
use crate::{Point, SVector};
/* /*
* This file provides the following conversions: * This file provides the following conversions:
@ -198,6 +199,35 @@ where
} }
} }
impl<T: SimdRealField, R, const D: usize> From<[T; D]> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: [T; D]) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}
impl<T: SimdRealField, R, const D: usize> From<SVector<T, D>> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: SVector<T, D>) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}
impl<T: SimdRealField, R, const D: usize> From<Point<T, D>> for Isometry<T, R, D>
where
R: AbstractRotation<T, D>,
{
#[inline]
fn from(coords: Point<T, D>) -> Self {
Self::from_parts(coords.into(), R::identity())
}
}
impl<T: Scalar + PrimitiveSimdValue, R, const D: usize> impl<T: Scalar + PrimitiveSimdValue, R, const D: usize>
From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D> From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D>
where where

View File

@ -225,17 +225,3 @@ componentwise_constructors_impl!(
"# use nalgebra::Point6;\nlet p = Point6::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0 && p.b == 6.0);"; "# use nalgebra::Point6;\nlet p = Point6::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0 && p.b == 6.0);";
Point6, Vector6, x:0, y:1, z:2, w:3, a:4, b:5; Point6, Vector6, x:0, y:1, z:2, w:3, a:4, b:5;
); );
macro_rules! from_array_impl(
($($Point: ident, $len: expr);*) => {$(
impl <T: Scalar> From<[T; $len]> for $Point<T> {
fn from(coords: [T; $len]) -> Self {
Self {
coords: coords.into()
}
}
}
)*}
);
from_array_impl!(Point1, 1; Point2, 2; Point3, 3; Point4, 4; Point5, 5; Point6, 6);

View File

@ -81,6 +81,22 @@ where
} }
} }
impl<T: Scalar, const D: usize> From<[T; D]> for Point<T, D> {
#[inline]
fn from(coords: [T; D]) -> Self {
Point {
coords: coords.into(),
}
}
}
impl<T: Scalar, const D: usize> Into<[T; D]> for Point<T, D> {
#[inline]
fn into(self) -> [T; D] {
self.coords.into()
}
}
impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Point<T, D> { impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Point<T, D> {
#[inline] #[inline]
fn from(coords: OVector<T, Const<D>>) -> Self { fn from(coords: OVector<T, Const<D>>) -> Self {

View File

@ -11,6 +11,7 @@ use crate::geometry::{
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
Translation3, UnitDualQuaternion, UnitQuaternion, Translation3, UnitDualQuaternion, UnitQuaternion,
}; };
use crate::Point;
/* /*
* This file provides the following conversions: * This file provides the following conversions:
@ -199,6 +200,31 @@ impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Translation<T, D>
} }
} }
impl<T: Scalar, const D: usize> From<[T; D]> for Translation<T, D> {
#[inline]
fn from(coords: [T; D]) -> Self {
Translation {
vector: coords.into(),
}
}
}
impl<T: Scalar, const D: usize> From<Point<T, D>> for Translation<T, D> {
#[inline]
fn from(pt: Point<T, D>) -> Self {
Translation {
vector: pt.coords.into(),
}
}
}
impl<T: Scalar, const D: usize> Into<[T; D]> for Translation<T, D> {
#[inline]
fn into(self) -> [T; D] {
self.vector.into()
}
}
impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Translation<T::Element, D>; 2]> impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Translation<T::Element, D>; 2]>
for Translation<T, D> for Translation<T, D>
where where

View File

@ -1,5 +1,5 @@
use crate::{Isometry2, Isometry3}; use crate::{Isometry2, Isometry3};
use glam::{DMat3, DMat4, Mat3, Mat4}; use glam::{DMat3, DMat4, DQuat, DVec3, Mat3, Mat4, Quat, Vec3};
impl From<Isometry2<f32>> for Mat3 { impl From<Isometry2<f32>> for Mat3 {
fn from(iso: Isometry2<f32>) -> Mat3 { fn from(iso: Isometry2<f32>) -> Mat3 {
@ -23,10 +23,74 @@ impl From<Isometry3<f64>> for DMat4 {
} }
} }
impl From<Isometry3<f32>> for (Vec3, Quat) {
fn from(iso: Isometry3<f32>) -> (Vec3, Quat) {
(iso.translation.into(), iso.rotation.into())
}
}
impl From<Isometry3<f64>> for (DVec3, DQuat) {
fn from(iso: Isometry3<f64>) -> (DVec3, DQuat) {
(iso.translation.into(), iso.rotation.into())
}
}
impl From<Isometry2<f32>> for (Vec3, Quat) {
fn from(iso: Isometry2<f32>) -> (Vec3, Quat) {
let tra = Vec3::new(iso.translation.x, iso.translation.y, 0.0);
let rot = Quat::from_axis_angle(Vec3::new(0.0, 0.0, 1.0), iso.rotation.angle());
(tra, rot)
}
}
impl From<Isometry2<f64>> for (DVec3, DQuat) {
fn from(iso: Isometry2<f64>) -> (DVec3, DQuat) {
let tra = DVec3::new(iso.translation.x, iso.translation.y, 0.0);
let rot = DQuat::from_axis_angle(DVec3::new(0.0, 0.0, 1.0), iso.rotation.angle());
(tra, rot)
}
}
#[cfg(feature = "convert-glam-unchecked")] #[cfg(feature = "convert-glam-unchecked")]
mod unchecked { mod unchecked {
use crate::{Isometry2, Isometry3, Matrix3, Matrix4}; use crate::{Isometry2, Isometry3, Matrix3, Matrix4};
use glam::{DMat3, DMat4, Mat3, Mat4}; use glam::{DMat3, DMat4, DQuat, DVec2, DVec3, Mat3, Mat4, Quat, Vec2, Vec3};
impl From<(Vec3, Quat)> for Isometry3<f32> {
fn from((tra, rot): (Vec3, Quat)) -> Self {
Isometry3::from_parts(tra.into(), rot.into())
}
}
impl From<(DVec3, DQuat)> for Isometry3<f64> {
fn from((tra, rot): (DVec3, DQuat)) -> Self {
Isometry3::from_parts(tra.into(), rot.into())
}
}
impl From<(Vec3, Quat)> for Isometry2<f32> {
fn from((tra, rot): (Vec3, Quat)) -> Self {
Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1)
}
}
impl From<(DVec3, DQuat)> for Isometry2<f64> {
fn from((tra, rot): (DVec3, DQuat)) -> Self {
Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1)
}
}
impl From<(Vec2, Quat)> for Isometry2<f32> {
fn from((tra, rot): (Vec2, Quat)) -> Self {
Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1)
}
}
impl From<(DVec2, DQuat)> for Isometry2<f64> {
fn from((tra, rot): (DVec2, DQuat)) -> Self {
Isometry2::new([tra.x, tra.y].into(), rot.to_axis_angle().1)
}
}
impl From<Mat3> for Isometry2<f32> { impl From<Mat3> for Isometry2<f32> {
fn from(mat3: Mat3) -> Isometry2<f32> { fn from(mat3: Mat3) -> Isometry2<f32> {

View File

@ -0,0 +1,65 @@
use crate::{Translation2, Translation3, Translation4};
use glam::{DVec2, DVec3, DVec4, Vec2, Vec3, Vec3A, Vec4};
macro_rules! impl_translation_conversion(
($N: ty, $Vec2: ty, $Vec3: ty, $Vec4: ty) => {
impl From<$Vec2> for Translation2<$N> {
#[inline]
fn from(e: $Vec2) -> Translation2<$N> {
(*e.as_ref()).into()
}
}
impl From<Translation2<$N>> for $Vec2 {
#[inline]
fn from(e: Translation2<$N>) -> $Vec2 {
e.vector.into()
}
}
impl From<$Vec3> for Translation3<$N> {
#[inline]
fn from(e: $Vec3) -> Translation3<$N> {
(*e.as_ref()).into()
}
}
impl From<Translation3<$N>> for $Vec3 {
#[inline]
fn from(e: Translation3<$N>) -> $Vec3 {
e.vector.into()
}
}
impl From<$Vec4> for Translation4<$N> {
#[inline]
fn from(e: $Vec4) -> Translation4<$N> {
(*e.as_ref()).into()
}
}
impl From<Translation4<$N>> for $Vec4 {
#[inline]
fn from(e: Translation4<$N>) -> $Vec4 {
e.vector.into()
}
}
}
);
impl_translation_conversion!(f32, Vec2, Vec3, Vec4);
impl_translation_conversion!(f64, DVec2, DVec3, DVec4);
impl From<Vec3A> for Translation3<f32> {
#[inline]
fn from(e: Vec3A) -> Translation3<f32> {
(*e.as_ref()).into()
}
}
impl From<Translation3<f32>> for Vec3A {
#[inline]
fn from(e: Translation3<f32>) -> Vec3A {
e.vector.into()
}
}

View File

@ -4,4 +4,5 @@ mod glam_point;
mod glam_quaternion; mod glam_quaternion;
mod glam_rotation; mod glam_rotation;
mod glam_similarity; mod glam_similarity;
mod glam_translation;
mod glam_unit_complex; mod glam_unit_complex;