Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More conversions #874

Merged
merged 6 commits into from Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,16 @@ documented here.

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]
Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`.

Expand Down
83 changes: 30 additions & 53 deletions src/base/conversion.rs
Expand Up @@ -3,7 +3,6 @@ use alloc::vec::Vec;
use simba::scalar::{SubsetOf, SupersetOf};
use std::convert::{AsMut, AsRef, From, Into};
use std::mem;
use std::ptr;

use simba::simd::{PrimitiveSimdValue, SimdValue};

Expand All @@ -24,6 +23,7 @@ use crate::base::{
use crate::base::{DVector, VecStorage};
use crate::base::{SliceStorage, SliceStorageMut};
use crate::constraint::DimEq;
use crate::{SMatrix, SVector};

// 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>
Expand Down Expand Up @@ -103,35 +103,23 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator
}
}

macro_rules! impl_from_into_asref_1D(
($(($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) };
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])) }
}
}

unsafe { res.assume_init() }
}
}
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(
($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$(
impl<T, S> AsRef<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
where T: Scalar,
S: ContiguousStorage<T, $NRows, $NCols> {
Expand Down Expand Up @@ -171,33 +159,22 @@ impl_from_into_asref_1D!(
(U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16;
);

macro_rules! impl_from_into_asref_2D(
($(($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) };
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)) }
}
}

unsafe { res.assume_init() }
}
}
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(
($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
impl<T: Scalar, S> AsRef<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
where S: ContiguousStorage<T, $NRows, $NCols> {
#[inline]
Expand Down
30 changes: 30 additions & 0 deletions src/geometry/isometry_conversion.rs
Expand Up @@ -9,6 +9,7 @@ use crate::geometry::{
AbstractRotation, Isometry, Isometry3, Similarity, SuperTCategoryOf, TAffine, Transform,
Translation, UnitDualQuaternion, UnitQuaternion,
};
use crate::{Point, SVector};

/*
* This file provides the following conversions:
Expand Down Expand Up @@ -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>
From<[Isometry<T::Element, R::Element, D>; 2]> for Isometry<T, R, D>
where
Expand Down
14 changes: 0 additions & 14 deletions src/geometry/point_construction.rs
Expand Up @@ -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);";
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);
16 changes: 16 additions & 0 deletions src/geometry/point_conversion.rs
Expand Up @@ -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> {
#[inline]
fn from(coords: OVector<T, Const<D>>) -> Self {
Expand Down
26 changes: 26 additions & 0 deletions src/geometry/translation_conversion.rs
Expand Up @@ -11,6 +11,7 @@ use crate::geometry::{
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
Translation3, UnitDualQuaternion, UnitQuaternion,
};
use crate::Point;

/*
* This file provides the following conversions:
Expand Down Expand Up @@ -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]>
for Translation<T, D>
where
Expand Down
68 changes: 66 additions & 2 deletions src/third_party/glam/glam_isometry.rs
@@ -1,5 +1,5 @@
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 {
fn from(iso: Isometry2<f32>) -> Mat3 {
Expand All @@ -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")]
mod unchecked {
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> {
fn from(mat3: Mat3) -> Isometry2<f32> {
Expand Down