From 3d82c4335e1802290ce2b845dbc2ce3147f22aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:23:34 +0100 Subject: [PATCH 01/12] Add inverse_transform_unit_vector to rotations and isometries. --- src/geometry/abstract_rotation.rs | 17 ++++++++++++++++- src/geometry/isometry.rs | 25 ++++++++++++++++++++++++- src/geometry/quaternion.rs | 20 ++++++++++++++++++++ src/geometry/rotation.rs | 21 ++++++++++++++++++++- src/geometry/unit_complex.rs | 16 ++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/geometry/abstract_rotation.rs b/src/geometry/abstract_rotation.rs index ff057a09..52471851 100644 --- a/src/geometry/abstract_rotation.rs +++ b/src/geometry/abstract_rotation.rs @@ -1,6 +1,6 @@ use crate::allocator::Allocator; use crate::geometry::{Rotation, UnitComplex, UnitQuaternion}; -use crate::{DefaultAllocator, DimName, Point, Scalar, SimdRealField, VectorN, U2, U3}; +use crate::{DefaultAllocator, DimName, Point, Scalar, SimdRealField, Unit, VectorN, U2, U3}; use simba::scalar::ClosedMul; @@ -24,6 +24,13 @@ pub trait AbstractRotation: PartialEq + ClosedMul + Clone fn inverse_transform_vector(&self, v: &VectorN) -> VectorN where DefaultAllocator: Allocator; + /// Apply the inverse rotation to the given unit vector. + fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> + where + DefaultAllocator: Allocator, + { + Unit::new_unchecked(self.inverse_transform_vector(&**v)) + } /// Apply the inverse rotation to the given point. fn inverse_transform_point(&self, p: &Point) -> Point where @@ -74,6 +81,14 @@ where self.inverse_transform_vector(v) } + #[inline] + fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> + where + DefaultAllocator: Allocator, + { + self.inverse_transform_unit_vector(v) + } + #[inline] fn inverse_transform_point(&self, p: &Point) -> Point where diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index a4e16abe..b59c8b60 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -16,7 +16,7 @@ use simba::simd::SimdRealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::storage::Owned; -use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; +use crate::base::{DefaultAllocator, MatrixN, Scalar, Unit, VectorN}; use crate::geometry::{AbstractRotation, Point, Translation}; /// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group. @@ -350,6 +350,29 @@ where pub fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { self.rotation.inverse_transform_vector(v) } + + /// Transform the given unit vector by the inverse of this isometry, ignoring the + /// translation component of the isometry. This may be + /// less expensive than computing the entire isometry inverse and then + /// transforming the point. + /// + /// # Example + /// + /// ``` + /// # #[macro_use] extern crate approx; + /// # use std::f32; + /// # use nalgebra::{Isometry3, Translation3, UnitQuaternion, Vector3}; + /// let tra = Translation3::new(0.0, 0.0, 3.0); + /// let rot = UnitQuaternion::from_scaled_axis(Vector3::z() * f32::consts::FRAC_PI_2); + /// let iso = Isometry3::from_parts(tra, rot); + /// + /// let transformed_point = iso.inverse_transform_unit_vector(&Vector3::x_axis()); + /// assert_relative_eq!(transformed_point, -Vector3::y_axis(), epsilon = 1.0e-6); + /// ``` + #[inline] + pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { + self.rotation.inverse_transform_unit_vector(v) + } } // NOTE: we don't require `R: Rotation<...>` here because this is not useful for the implementation diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 0c996ede..22ee5309 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -1542,6 +1542,26 @@ where pub fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { self.inverse() * v } + + /// Rotate a vector by the inverse of this unit quaternion. This may be + /// cheaper than inverting the unit quaternion and transforming the + /// vector. + /// + /// # Example + /// + /// ``` + /// # #[macro_use] extern crate approx; + /// # use std::f32; + /// # use nalgebra::{UnitQuaternion, Vector3}; + /// let rot = UnitQuaternion::from_axis_angle(&Vector3::z_axis(), f32::consts::FRAC_PI_2); + /// let transformed_vector = rot.inverse_transform_unit_vector(&Vector3::x_axis()); + /// + /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); + /// ``` + #[inline] + pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { + self.inverse() * v + } } impl Default for UnitQuaternion { diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index bb3fc235..c30a3a97 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -19,7 +19,7 @@ use simba::simd::SimdRealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; +use crate::base::{DefaultAllocator, MatrixN, Scalar, Unit, VectorN}; use crate::geometry::Point; /// A rotation matrix. @@ -441,6 +441,25 @@ where pub fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { self.matrix().tr_mul(v) } + + /// Rotate the given vector by the inverse of this rotation. This may be + /// cheaper than inverting the rotation and then transforming the given + /// vector. + /// + /// # Example + /// ``` + /// # #[macro_use] extern crate approx; + /// # use std::f32; + /// # use nalgebra::{Rotation2, Rotation3, UnitQuaternion, Vector3}; + /// let rot = Rotation3::new(Vector3::z() * f32::consts::FRAC_PI_2); + /// let transformed_vector = rot.inverse_transform_unit_vector(&Vector3::x_axis()); + /// + /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); + /// ``` + #[inline] + pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { + Unit::new_unchecked(self.inverse_transform_vector(&**v)) + } } impl Eq for Rotation where DefaultAllocator: Allocator {} diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index a8ac5bcd..723ac6c0 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -360,6 +360,22 @@ where pub fn inverse_transform_vector(&self, v: &Vector2) -> Vector2 { self.inverse() * v } + + /// Rotate the given vector by the inverse of this unit complex number. + /// + /// # Example + /// ``` + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{UnitComplex, Vector2}; + /// # use std::f32; + /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2); + /// let transformed_vector = rot.inverse_transform_unit_vector(&Vector2::x_axis()); + /// assert_relative_eq!(transformed_vector, -Vector2::y_axis(), epsilon = 1.0e-6); + /// ``` + #[inline] + pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { + self.inverse() * v + } } impl fmt::Display for UnitComplex { From a623e63d08b1e11a73df0237c06e011987d1606a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:23:51 +0100 Subject: [PATCH 02/12] Add the conversion of an array of four elements to a quaternion. --- src/geometry/quaternion_conversion.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index 37a8bebd..330c97e4 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -265,6 +265,15 @@ impl From> for Quaternion { } } +impl From<[N; 4]> for Quaternion { + #[inline] + fn from(coords: [N; 4]) -> Self { + Self { + coords: coords.into(), + } + } +} + impl From<[Quaternion; 2]> for Quaternion where N: From<[::Element; 2]>, From 503040b8bce4956b1d54e824819fcf7b89976763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:24:05 +0100 Subject: [PATCH 03/12] Add Point.map(f) and Point.apply(f). --- src/geometry/point.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/geometry/point.rs b/src/geometry/point.rs index d12b9212..e0c26054 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -102,6 +102,45 @@ impl Point where DefaultAllocator: Allocator, { + /// Returns a point containing the result of `f` applied to each of its entries. + /// + /// # Example + /// ``` + /// # use nalgebra::{Point2, Point3}; + /// let p = Point2::new(1.0, 2.0); + /// assert_eq!(p.map(|e| e * 10.0), Point2::new(10.0, 20.0)); + /// + /// // This works in any dimension. + /// let p = Point3::new(1.1, 2.1, 3.1); + /// assert_eq!(p.map(|e| e as u32), Point3::new(1, 2, 3)); + /// ``` + #[inline] + pub fn map N2>(&self, f: F) -> Point + where + DefaultAllocator: Allocator, + { + self.coords.map(f).into() + } + + /// Replaces each component of `self` by the result of a closure `f` applied on it. + /// + /// # Example + /// ``` + /// # use nalgebra::{Point2, Point3}; + /// let mut p = Point2::new(1.0, 2.0); + /// p.apply(|e| e * 10.0); + /// assert_eq!(p, Point2::new(10.0, 20.0)); + /// + /// // This works in any dimension. + /// let mut p = Point3::new(1.0, 2.0, 3.0); + /// p.apply(|e| e * 10.0); + /// assert_eq!(p, Point3::new(10.0, 20.0, 30.0)); + /// ``` + #[inline] + pub fn apply N>(&mut self, f: F) { + self.coords.apply(f) + } + /// Converts this point into a vector in homogeneous coordinates, i.e., appends a `1` at the /// end of it. /// From 55689c238ae8f4933f29f2b253a811e5ca18b1b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:24:20 +0100 Subject: [PATCH 04/12] Add the conversion of a translation to an isometry. --- src/geometry/isometry_conversion.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 7cb6fe85..bdb128f9 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -151,6 +151,17 @@ where } } +impl> From> + for Isometry +where + DefaultAllocator: Allocator, +{ + #[inline] + fn from(tra: Translation) -> Self { + Self::from_parts(tra, R::identity()) + } +} + impl From> for MatrixN> where D: DimNameAdd, From 9c93a58b5d648697806075dc2cc41cf33cf33464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:25:38 +0100 Subject: [PATCH 05/12] Add Vector::ith_axis to build an unit vector with its i-th component set to 1. --- src/base/construction.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/base/construction.rs b/src/base/construction.rs index f810acdf..aa4cf956 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -1019,6 +1019,12 @@ where res } + /// The column unit vector with `N::one()` as its i-th component. + #[inline] + pub fn ith_axis(i: usize) -> Unit { + Unit::new_unchecked(Self::ith(i, N::one())) + } + /// The column vector with a 1 as its first component, and zero elsewhere. #[inline] pub fn x() -> Self From 097ae44efad1b52f6f1e31df99f6510e52b34979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:39:27 +0100 Subject: [PATCH 06/12] Add `lerp_slerp` to isometries for interpolation. --- src/geometry/abstract_rotation.rs | 44 +++++++++++++++++++++ src/geometry/isometry.rs | 66 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/src/geometry/abstract_rotation.rs b/src/geometry/abstract_rotation.rs index 52471851..e1cf7c10 100644 --- a/src/geometry/abstract_rotation.rs +++ b/src/geometry/abstract_rotation.rs @@ -35,6 +35,14 @@ pub trait AbstractRotation: PartialEq + ClosedMul + Clone fn inverse_transform_point(&self, p: &Point) -> Point where DefaultAllocator: Allocator; + /// Perfom a spherical interpolation between two rolations. + fn slerp(&self, other: &Self, t: N) -> Self + where + DefaultAllocator: Allocator; + /// Attempts to perfom a spherical interpolation between two rolations. + fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option + where + DefaultAllocator: Allocator; } impl AbstractRotation for Rotation @@ -96,6 +104,22 @@ where { self.inverse_transform_point(p) } + + #[inline] + fn slerp(&self, other: &Self, t: N) -> Self + where + DefaultAllocator: Allocator, + { + self.slerp(other, t) + } + + #[inline] + fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option + where + DefaultAllocator: Allocator, + { + self.try_slerp(other, t, epsilon) + } } impl AbstractRotation for UnitQuaternion @@ -136,6 +160,16 @@ where fn inverse_transform_point(&self, p: &Point) -> Point { self.inverse_transform_point(p) } + + #[inline] + fn slerp(&self, other: &Self, t: N) -> Self { + self.slerp(other, t) + } + + #[inline] + fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option { + self.try_slerp(other, t, epsilon) + } } impl AbstractRotation for UnitComplex @@ -176,4 +210,14 @@ where fn inverse_transform_point(&self, p: &Point) -> Point { self.inverse_transform_point(p) } + + #[inline] + fn slerp(&self, other: &Self, t: N) -> Self { + self.slerp(other, t) + } + + #[inline] + fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option { + self.try_slerp(other, t, epsilon) + } } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index b59c8b60..5b7e5dc7 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -373,6 +373,72 @@ where pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.rotation.inverse_transform_unit_vector(v) } + + /// Interpolates between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Translation3, UnitQuaternion}; + /// + /// let t1 = Translation3::new(1.0, 2.0, 3.0); + /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let q1 = UnitQuaternion::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); + /// let q2 = UnitQuaternion::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); + /// let iso1 = Isometry3::from_parts(t1, q1); + /// let iso2 = Isometry3::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); + /// ``` + #[inline] + pub fn lerp_slerp(&self, other: &Self, t: N) -> Self + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.slerp(&other.rotation, t); + Self::from_parts(tr.into(), rot) + } + + /// Attempts to interpolate between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Retuns `None` if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Translation3, UnitQuaternion}; + /// + /// let t1 = Translation3::new(1.0, 2.0, 3.0); + /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let q1 = UnitQuaternion::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); + /// let q2 = UnitQuaternion::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); + /// let iso1 = Isometry3::from_parts(t1, q1); + /// let iso2 = Isometry3::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); + /// ``` + #[inline] + pub fn try_lerp_slerp(&self, other: &Self, t: N, epsilon: N) -> Option + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.try_slerp(&other.rotation, t, epsilon)?; + Some(Self::from_parts(tr.into(), rot)) + } } // NOTE: we don't require `R: Rotation<...>` here because this is not useful for the implementation From 22b8fc92254a71f551d30c14ef9f5e657ea1fc81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 11:39:38 +0100 Subject: [PATCH 07/12] Update che changelog. --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db0cdc6b..1c158452 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.23.0] - WIP + +### Added + * The `.inverse_transform_unit_vector(v)` was added to `Rotation2/3`, `Isometry2/3`, `UnitQuaternion`, and `UnitComplex`. + It applies the corresponding rotation to a unit vector `Unit`. + * The `Point.map(f)` and `Point.apply(f)` to apply a function to each component of the point, similarly to `Vector.map(f)` + and `Vector.apply(f)`. + * The `Quaternion::from([N; 4])` conversion to build a quaternion from an array of four elements. + * The `Isometry::from(Translation)` conversion to build an isometry from a translation. + * The `Vector::ith_axis(i)` which build a unit vector, e.g., `Unit>` with its i-th component set to 1.0 and the + others set to zero. + * The `Isometry.lerp_slerp` and `Isometry.try_lerp_slerp` methods to interpolate between two isometries using linear + interpolation for the translational part, and spherical interpolation for the rotational part. + ## [0.22.0] In this release, we are using the new version 0.2 of simba. One major change of that version is that the use of `libm` is now opt-in when building targetting `no-std` environment. If you are using floating-point From 93f361cba8dbc5dad8445d712374d7ff11903156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 14:00:47 +0100 Subject: [PATCH 08/12] Add missing slerp implementations. --- CHANGELOG.md | 2 + src/geometry/abstract_rotation.rs | 44 ------- src/geometry/isometry.rs | 150 +++++++++++++++++++++++- src/geometry/rotation_specialization.rs | 71 +++++++++++ src/geometry/unit_complex.rs | 20 ++++ 5 files changed, 239 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c158452..853529f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). others set to zero. * The `Isometry.lerp_slerp` and `Isometry.try_lerp_slerp` methods to interpolate between two isometries using linear interpolation for the translational part, and spherical interpolation for the rotational part. + * The `Rotation2.slerp`, `Rotation3.slerp`, and `UnitQuaternion.slerp` method for + spherical interpolation. ## [0.22.0] In this release, we are using the new version 0.2 of simba. One major change of that version is that the diff --git a/src/geometry/abstract_rotation.rs b/src/geometry/abstract_rotation.rs index e1cf7c10..52471851 100644 --- a/src/geometry/abstract_rotation.rs +++ b/src/geometry/abstract_rotation.rs @@ -35,14 +35,6 @@ pub trait AbstractRotation: PartialEq + ClosedMul + Clone fn inverse_transform_point(&self, p: &Point) -> Point where DefaultAllocator: Allocator; - /// Perfom a spherical interpolation between two rolations. - fn slerp(&self, other: &Self, t: N) -> Self - where - DefaultAllocator: Allocator; - /// Attempts to perfom a spherical interpolation between two rolations. - fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option - where - DefaultAllocator: Allocator; } impl AbstractRotation for Rotation @@ -104,22 +96,6 @@ where { self.inverse_transform_point(p) } - - #[inline] - fn slerp(&self, other: &Self, t: N) -> Self - where - DefaultAllocator: Allocator, - { - self.slerp(other, t) - } - - #[inline] - fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option - where - DefaultAllocator: Allocator, - { - self.try_slerp(other, t, epsilon) - } } impl AbstractRotation for UnitQuaternion @@ -160,16 +136,6 @@ where fn inverse_transform_point(&self, p: &Point) -> Point { self.inverse_transform_point(p) } - - #[inline] - fn slerp(&self, other: &Self, t: N) -> Self { - self.slerp(other, t) - } - - #[inline] - fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option { - self.try_slerp(other, t, epsilon) - } } impl AbstractRotation for UnitComplex @@ -210,14 +176,4 @@ where fn inverse_transform_point(&self, p: &Point) -> Point { self.inverse_transform_point(p) } - - #[inline] - fn slerp(&self, other: &Self, t: N) -> Self { - self.slerp(other, t) - } - - #[inline] - fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option { - self.try_slerp(other, t, epsilon) - } } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 5b7e5dc7..c8eb34fb 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -14,10 +14,12 @@ use simba::scalar::{RealField, SubsetOf}; use simba::simd::SimdRealField; use crate::base::allocator::Allocator; -use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3}; use crate::base::storage::Owned; use crate::base::{DefaultAllocator, MatrixN, Scalar, Unit, VectorN}; -use crate::geometry::{AbstractRotation, Point, Translation}; +use crate::geometry::{ + AbstractRotation, Point, Rotation2, Rotation3, Translation, UnitComplex, UnitQuaternion, +}; /// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group. #[repr(C)] @@ -373,7 +375,9 @@ where pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.rotation.inverse_transform_unit_vector(v) } +} +impl Isometry> { /// Interpolates between two isometries using a linear interpolation for the translation part, /// and a spherical interpolation for the rotation part. /// @@ -383,7 +387,7 @@ where /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Translation3, UnitQuaternion}; + /// # use nalgebra::geometry::{Vector3, Translation3, UnitQuaternion}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); /// let t2 = Translation3::new(3.0, 6.0, 9.0); @@ -416,7 +420,7 @@ where /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Translation3, UnitQuaternion}; + /// # use nalgebra::geometry::{Vector3, Translation3, UnitQuaternion}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); /// let t2 = Translation3::new(3.0, 6.0, 9.0); @@ -441,6 +445,144 @@ where } } +impl Isometry> { + /// Interpolates between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Vector3, Translation3, Rotation3}; + /// + /// let t1 = Translation3::new(1.0, 2.0, 3.0); + /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); + /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); + /// let iso1 = Isometry3::from_parts(t1, q1); + /// let iso2 = Isometry3::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); + /// ``` + #[inline] + pub fn lerp_slerp(&self, other: &Self, t: N) -> Self + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.slerp(&other.rotation, t); + Self::from_parts(tr.into(), rot) + } + + /// Attempts to interpolate between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Retuns `None` if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Vector3, Translation3, Rotation3}; + /// + /// let t1 = Translation3::new(1.0, 2.0, 3.0); + /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); + /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); + /// let iso1 = Isometry3::from_parts(t1, q1); + /// let iso2 = Isometry3::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); + /// ``` + #[inline] + pub fn try_lerp_slerp(&self, other: &Self, t: N, epsilon: N) -> Option + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.try_slerp(&other.rotation, t, epsilon)?; + Some(Self::from_parts(tr.into(), rot)) + } +} + +impl Isometry> { + /// Interpolates between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Vector2, Translation2, UnitComplex, Isometry2}; + /// + /// let t1 = Translation2::new(1.0, 2.0); + /// let t2 = Translation2::new(3.0, 6.0); + /// let q1 = UnitComplex::new(std::f32::consts::FRAC_PI_4); + /// let q2 = UnitComplex::new(-std::f32::consts::PI); + /// let iso1 = Isometry2::from_parts(t1, q1); + /// let iso2 = Isometry2::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector2::new(2.0, 4.0)); + /// assert_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); + /// ``` + #[inline] + pub fn slerp(&self, other: &Self, t: N) -> Self + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.slerp(&other.rotation, t); + Self::from_parts(tr.into(), rot) + } +} + +impl Isometry> { + /// Interpolates between two isometries using a linear interpolation for the translation part, + /// and a spherical interpolation for the rotation part. + /// + /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::{Vector2, Translation2, Rotation2, Isometry2}; + /// + /// let t1 = Translation2::new(1.0, 2.0); + /// let t2 = Translation2::new(3.0, 6.0); + /// let q1 = Rotation2::new(std::f32::consts::FRAC_PI_4); + /// let q2 = Rotation2::new(-std::f32::consts::PI); + /// let iso1 = Isometry2::from_parts(t1, q1); + /// let iso2 = Isometry2::from_parts(t2, q2); + /// + /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); + /// + /// assert_eq!(iso3.translation_vector, Vector2::new(2.0, 4.0)); + /// assert_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); + /// ``` + #[inline] + pub fn slerp(&self, other: &Self, t: N) -> Self + where + N: RealField, + { + let tr = self.translation.vector.lerp(&other.translation.vector, t); + let rot = self.rotation.slerp(&other.rotation, t); + Self::from_parts(tr.into(), rot) + } +} + // NOTE: we don't require `R: Rotation<...>` here because this is not useful for the implementation // and makes it hard to use it, e.g., for Transform × Isometry implementation. // This is OK since all constructors of the isometry enforce the Rotation bound already (and diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 1ee4a9df..7f140c8b 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -236,6 +236,30 @@ impl Rotation2 { pub fn scaled_axis(&self) -> VectorN { Vector1::new(self.angle()) } + + /// Spherical linear interpolation between two rotation matrices. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::Rotation2; + /// + /// let rot1 = Rotation2::new(std::f32::consts::FRAC_PI_4); + /// let rot2 = Rotation2::new(-std::f32::consts::PI); + /// + /// let rot = rot1.slerp(&rot2, 1.0 / 3.0); + /// + /// assert_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); + /// ``` + #[inline] + pub fn slerp(&self, other: &Self, t: N) -> Self + where + N::Element: SimdRealField, + { + let c1 = UnitComplex::from(*self); + let c2 = UnitComplex::from(*other); + c1.slerp(&c2, t).into() + } } impl Distribution> for Standard @@ -862,6 +886,53 @@ where Self::identity() } } + + /// Spherical linear interpolation between two rotation matrices. + /// + /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation + /// is not well-defined). Use `.try_slerp` instead to avoid the panic. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::Rotation3; + /// + /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); + /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); + /// + /// let q = q1.slerp(&q2, 1.0 / 3.0); + /// + /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); + /// ``` + #[inline] + pub fn slerp(&self, other: &Self, t: N) -> Self + where + N: RealField, + { + let q1 = UnitQuaternion::from(*self); + let q2 = UnitQuaternion::from(*other); + q1.slerp(&q2, t).into() + } + + /// Computes the spherical linear interpolation between two rotation matrices or returns `None` + /// if both rotations are approximately 180 degrees apart (in which case the interpolation is + /// not well-defined). + /// + /// # Arguments + /// * `self`: the first rotation to interpolate from. + /// * `other`: the second rotation to interpolate toward. + /// * `t`: the interpolation parameter. Should be between 0 and 1. + /// * `epsilon`: the value below which the sinus of the angle separating both rotations + /// must be to return `None`. + #[inline] + pub fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option + where + N: RealField, + { + let q1 = Rotation3::from(*self); + let q2 = Rotation3::from(*other); + q1.try_slerp(&q2, t, epsilon).map(|q| q.into()) + } } impl Distribution> for Standard diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index 723ac6c0..f6a4f619 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -376,6 +376,26 @@ where pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } + + /// Spherical linear interpolation between two rotations represented as unit complex numbers. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::geometry::UnitComplex; + /// + /// let rot1 = UnitComplex::new(std::f32::consts::FRAC_PI_4); + /// let rot2 = UnitComplex::new(-std::f32::consts::PI); + /// + /// let rot = rot1.slerp(&rot2, 1.0 / 3.0); + /// + /// assert_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); + /// ``` + + #[inline] + pub fn slerp(&self, other: &Self, t: N) -> Self { + Self::new(self.angle() * (N::one() - t) + other.angle() * t) + } } impl fmt::Display for UnitComplex { From c410a32c8279d2d3b10c654a893d431025d6135c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 14:15:26 +0100 Subject: [PATCH 09/12] Fix doc-tests. --- src/geometry/isometry.rs | 58 +++++++++++++------------ src/geometry/rotation_specialization.rs | 3 +- src/geometry/unit_complex.rs | 3 +- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index c8eb34fb..edb27b5a 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -387,10 +387,10 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector3, Translation3, UnitQuaternion}; + /// # use nalgebra::{Vector3, Translation3, Isometry3, UnitQuaternion}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); - /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let t2 = Translation3::new(4.0, 8.0, 12.0); /// let q1 = UnitQuaternion::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); /// let q2 = UnitQuaternion::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); /// let iso1 = Isometry3::from_parts(t1, q1); @@ -398,7 +398,7 @@ impl Isometry> { /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.translation.vector, Vector3::new(2.0, 4.0, 6.0)); /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] @@ -420,10 +420,10 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector3, Translation3, UnitQuaternion}; + /// # use nalgebra::{Vector3, Translation3, Isometry3, UnitQuaternion}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); - /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let t2 = Translation3::new(4.0, 8.0, 12.0); /// let q1 = UnitQuaternion::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); /// let q2 = UnitQuaternion::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); /// let iso1 = Isometry3::from_parts(t1, q1); @@ -431,7 +431,7 @@ impl Isometry> { /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.translation.vector, Vector3::new(2.0, 4.0, 6.0)); /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] @@ -455,18 +455,18 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector3, Translation3, Rotation3}; + /// # use nalgebra::{Vector3, Translation3, Rotation3, IsometryMatrix3}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); - /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let t2 = Translation3::new(4.0, 8.0, 12.0); /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); - /// let iso1 = Isometry3::from_parts(t1, q1); - /// let iso2 = Isometry3::from_parts(t2, q2); + /// let iso1 = IsometryMatrix3::from_parts(t1, q1); + /// let iso2 = IsometryMatrix3::from_parts(t2, q2); /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.translation.vector, Vector3::new(2.0, 4.0, 6.0)); /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] @@ -488,18 +488,18 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector3, Translation3, Rotation3}; + /// # use nalgebra::{Vector3, Translation3, Rotation3, IsometryMatrix3}; /// /// let t1 = Translation3::new(1.0, 2.0, 3.0); - /// let t2 = Translation3::new(3.0, 6.0, 9.0); + /// let t2 = Translation3::new(4.0, 8.0, 12.0); /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0); /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0); - /// let iso1 = Isometry3::from_parts(t1, q1); - /// let iso2 = Isometry3::from_parts(t2, q2); + /// let iso1 = IsometryMatrix3::from_parts(t1, q1); + /// let iso2 = IsometryMatrix3::from_parts(t2, q2); /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector3::new(2.0, 4.0, 6.0)); + /// assert_eq!(iso3.translation.vector, Vector3::new(2.0, 4.0, 6.0)); /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] @@ -523,10 +523,11 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector2, Translation2, UnitComplex, Isometry2}; + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{Vector2, Translation2, UnitComplex, Isometry2}; /// /// let t1 = Translation2::new(1.0, 2.0); - /// let t2 = Translation2::new(3.0, 6.0); + /// let t2 = Translation2::new(4.0, 8.0); /// let q1 = UnitComplex::new(std::f32::consts::FRAC_PI_4); /// let q2 = UnitComplex::new(-std::f32::consts::PI); /// let iso1 = Isometry2::from_parts(t1, q1); @@ -534,11 +535,11 @@ impl Isometry> { /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector2::new(2.0, 4.0)); - /// assert_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); + /// assert_eq!(iso3.translation.vector, Vector2::new(2.0, 4.0)); + /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - pub fn slerp(&self, other: &Self, t: N) -> Self + pub fn lerp_slerp(&self, other: &Self, t: N) -> Self where N: RealField, { @@ -558,22 +559,23 @@ impl Isometry> { /// # Examples: /// /// ``` - /// # use nalgebra::geometry::{Vector2, Translation2, Rotation2, Isometry2}; + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{Vector2, Translation2, Rotation2, IsometryMatrix2}; /// /// let t1 = Translation2::new(1.0, 2.0); - /// let t2 = Translation2::new(3.0, 6.0); + /// let t2 = Translation2::new(4.0, 8.0); /// let q1 = Rotation2::new(std::f32::consts::FRAC_PI_4); /// let q2 = Rotation2::new(-std::f32::consts::PI); - /// let iso1 = Isometry2::from_parts(t1, q1); - /// let iso2 = Isometry2::from_parts(t2, q2); + /// let iso1 = IsometryMatrix2::from_parts(t1, q1); + /// let iso2 = IsometryMatrix2::from_parts(t2, q2); /// /// let iso3 = iso1.lerp_slerp(&iso2, 1.0 / 3.0); /// - /// assert_eq!(iso3.translation_vector, Vector2::new(2.0, 4.0)); - /// assert_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); + /// assert_eq!(iso3.translation.vector, Vector2::new(2.0, 4.0)); + /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - pub fn slerp(&self, other: &Self, t: N) -> Self + pub fn lerp_slerp(&self, other: &Self, t: N) -> Self where N: RealField, { diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 7f140c8b..085cb2d8 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -242,6 +242,7 @@ impl Rotation2 { /// # Examples: /// /// ``` + /// # #[macro_use] extern crate approx; /// # use nalgebra::geometry::Rotation2; /// /// let rot1 = Rotation2::new(std::f32::consts::FRAC_PI_4); @@ -249,7 +250,7 @@ impl Rotation2 { /// /// let rot = rot1.slerp(&rot2, 1.0 / 3.0); /// - /// assert_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); + /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] pub fn slerp(&self, other: &Self, t: N) -> Self diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index f6a4f619..a31f3ddf 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -382,6 +382,7 @@ where /// # Examples: /// /// ``` + /// # #[macro_use] extern crate approx; /// # use nalgebra::geometry::UnitComplex; /// /// let rot1 = UnitComplex::new(std::f32::consts::FRAC_PI_4); @@ -389,7 +390,7 @@ where /// /// let rot = rot1.slerp(&rot2, 1.0 / 3.0); /// - /// assert_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); + /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] From a473a3365c45a6f748d3b3d07dd569d538a1b61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 14:50:33 +0100 Subject: [PATCH 10/12] Bump dependencies. --- Cargo.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c98c13dc..378bf0c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,23 +36,23 @@ libm-force = [ "simba/libm_force" ] [dependencies] -typenum = "1.11" -generic-array = "0.13" +typenum = "1.12" +generic-array = "0.14" rand = { version = "0.7", default-features = false } num-traits = { version = "0.2", default-features = false } -num-complex = { version = "0.2", default-features = false } -num-rational = { version = "0.2", default-features = false } -approx = { version = "0.3", default-features = false } -simba = { version = "0.2", default-features = false } +num-complex = { version = "0.3", default-features = false } +num-rational = { version = "0.3", default-features = false } +approx = { version = "0.4", default-features = false } +simba = { version = "0.3", default-features = false } alga = { version = "0.9", default-features = false, optional = true } -rand_distr = { version = "0.2", optional = true } +rand_distr = { version = "0.3", optional = true } matrixmultiply = { version = "0.2", optional = true } serde = { version = "1.0", features = [ "derive" ], optional = true } abomonation = { version = "0.7", optional = true } mint = { version = "0.5", optional = true } quickcheck = { version = "0.9", optional = true } -pest = { version = "2.0", optional = true } -pest_derive = { version = "2.0", optional = true } +pest = { version = "2", optional = true } +pest_derive = { version = "2", optional = true } matrixcompare-core = { version = "0.1", optional = true } [dev-dependencies] From 3b723d7b9c20acd2b1447f92a19fffed7a7b4e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 15:13:56 +0100 Subject: [PATCH 11/12] Bump dependencies for nalgebra-glm and nalgebra-lapack. --- nalgebra-glm/Cargo.toml | 4 ++-- nalgebra-lapack/Cargo.toml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nalgebra-glm/Cargo.toml b/nalgebra-glm/Cargo.toml index 50f45eae..0400d91a 100644 --- a/nalgebra-glm/Cargo.toml +++ b/nalgebra-glm/Cargo.toml @@ -23,6 +23,6 @@ abomonation-serialize = [ "nalgebra/abomonation-serialize" ] [dependencies] num-traits = { version = "0.2", default-features = false } -approx = { version = "0.3", default-features = false } -simba = { version = "0.2", default-features = false } +approx = { version = "0.4", default-features = false } +simba = { version = "0.3", default-features = false } nalgebra = { path = "..", version = "0.22", default-features = false } diff --git a/nalgebra-lapack/Cargo.toml b/nalgebra-lapack/Cargo.toml index c5e397fb..e0fe4310 100644 --- a/nalgebra-lapack/Cargo.toml +++ b/nalgebra-lapack/Cargo.toml @@ -25,16 +25,16 @@ intel-mkl = ["lapack-src/intel-mkl"] [dependencies] nalgebra = { version = "0.22", path = ".." } num-traits = "0.2" -num-complex = { version = "0.2", default-features = false } -simba = "0.2" +num-complex = { version = "0.3", default-features = false } +simba = "0.3" serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } lapack = { version = "0.16", default-features = false } -lapack-src = { version = "0.5", default-features = false } +lapack-src = { version = "0.6", default-features = false } # clippy = "*" [dev-dependencies] nalgebra = { version = "0.22", path = "..", features = [ "arbitrary" ] } quickcheck = "0.9" -approx = "0.3" +approx = "0.4" rand = "0.7" From ee05a8f4d91b83734770cd239172c89983c21025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 25 Oct 2020 15:25:13 +0100 Subject: [PATCH 12/12] Revert dependencies bump for nalgebra-lapack because lapack needs to be updated first. --- nalgebra-lapack/Cargo.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nalgebra-lapack/Cargo.toml b/nalgebra-lapack/Cargo.toml index e0fe4310..e70359cc 100644 --- a/nalgebra-lapack/Cargo.toml +++ b/nalgebra-lapack/Cargo.toml @@ -23,18 +23,18 @@ accelerate = ["lapack-src/accelerate"] intel-mkl = ["lapack-src/intel-mkl"] [dependencies] -nalgebra = { version = "0.22", path = ".." } +nalgebra = { version = "0.22" } # , path = ".." } num-traits = "0.2" -num-complex = { version = "0.3", default-features = false } -simba = "0.3" +num-complex = { version = "0.2", default-features = false } +simba = "0.2" serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } lapack = { version = "0.16", default-features = false } -lapack-src = { version = "0.6", default-features = false } +lapack-src = { version = "0.5", default-features = false } # clippy = "*" [dev-dependencies] -nalgebra = { version = "0.22", path = "..", features = [ "arbitrary" ] } +nalgebra = { version = "0.22", features = [ "arbitrary" ] } # path = ".." } quickcheck = "0.9" -approx = "0.4" +approx = "0.3" rand = "0.7"