Merge pull request #800 from dimforge/docs-improvements-2

Docs improvements - part 2
This commit is contained in:
Sébastien Crozet 2020-11-23 11:42:09 +01:00 committed by GitHub
commit 5afa938ad9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1435 additions and 837 deletions

View File

@ -14,138 +14,242 @@ use crate::base::Matrix;
*
*/
/// A statically sized column-major matrix with `R` rows and `C` columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated(note = "This matrix name contains a typo. Use MatrixMN instead.")]
pub type MatrixNM<N, R, C> = Matrix<N, R, C, Owned<N, R, C>>;
/// A statically sized column-major matrix with `R` rows and `C` columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixMN<N, R, C> = Matrix<N, R, C, Owned<N, R, C>>;
/// A statically sized column-major square matrix with `D` rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixN<N, D> = Matrix<N, D, D, Owned<N, D, D>>;
/// A dynamically sized column-major matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type DMatrix<N> = Matrix<N, Dynamic, Dynamic, Owned<N, Dynamic, Dynamic>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 1 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx1<N> = Matrix<N, Dynamic, U1, Owned<N, Dynamic, U1>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 2 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx2<N> = Matrix<N, Dynamic, U2, Owned<N, Dynamic, U2>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 3 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx3<N> = Matrix<N, Dynamic, U3, Owned<N, Dynamic, U3>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 4 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx4<N> = Matrix<N, Dynamic, U4, Owned<N, Dynamic, U4>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 5 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx5<N> = Matrix<N, Dynamic, U5, Owned<N, Dynamic, U5>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 6 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx6<N> = Matrix<N, Dynamic, U6, Owned<N, Dynamic, U6>>;
/// A heap-allocated, row-major, matrix with 1 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix1xX<N> = Matrix<N, U1, Dynamic, Owned<N, U1, Dynamic>>;
/// A heap-allocated, row-major, matrix with 2 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix2xX<N> = Matrix<N, U2, Dynamic, Owned<N, U2, Dynamic>>;
/// A heap-allocated, row-major, matrix with 3 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix3xX<N> = Matrix<N, U3, Dynamic, Owned<N, U3, Dynamic>>;
/// A heap-allocated, row-major, matrix with 4 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix4xX<N> = Matrix<N, U4, Dynamic, Owned<N, U4, Dynamic>>;
/// A heap-allocated, row-major, matrix with 5 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix5xX<N> = Matrix<N, U5, Dynamic, Owned<N, U5, Dynamic>>;
/// A heap-allocated, row-major, matrix with 6 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix6xX<N> = Matrix<N, U6, Dynamic, Owned<N, U6, Dynamic>>;
/// A stack-allocated, column-major, 1x1 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1<N> = Matrix<N, U1, U1, Owned<N, U1, U1>>;
/// A stack-allocated, column-major, 2x2 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2<N> = Matrix<N, U2, U2, Owned<N, U2, U2>>;
/// A stack-allocated, column-major, 3x3 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3<N> = Matrix<N, U3, U3, Owned<N, U3, U3>>;
/// A stack-allocated, column-major, 4x4 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4<N> = Matrix<N, U4, U4, Owned<N, U4, U4>>;
/// A stack-allocated, column-major, 5x5 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5<N> = Matrix<N, U5, U5, Owned<N, U5, U5>>;
/// A stack-allocated, column-major, 6x6 square matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6<N> = Matrix<N, U6, U6, Owned<N, U6, U6>>;
/// A stack-allocated, column-major, 1x2 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1x2<N> = Matrix<N, U1, U2, Owned<N, U1, U2>>;
/// A stack-allocated, column-major, 1x3 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1x3<N> = Matrix<N, U1, U3, Owned<N, U1, U3>>;
/// A stack-allocated, column-major, 1x4 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1x4<N> = Matrix<N, U1, U4, Owned<N, U1, U4>>;
/// A stack-allocated, column-major, 1x5 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1x5<N> = Matrix<N, U1, U5, Owned<N, U1, U5>>;
/// A stack-allocated, column-major, 1x6 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix1x6<N> = Matrix<N, U1, U6, Owned<N, U1, U6>>;
/// A stack-allocated, column-major, 2x3 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2x3<N> = Matrix<N, U2, U3, Owned<N, U2, U3>>;
/// A stack-allocated, column-major, 2x4 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2x4<N> = Matrix<N, U2, U4, Owned<N, U2, U4>>;
/// A stack-allocated, column-major, 2x5 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2x5<N> = Matrix<N, U2, U5, Owned<N, U2, U5>>;
/// A stack-allocated, column-major, 2x6 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2x6<N> = Matrix<N, U2, U6, Owned<N, U2, U6>>;
/// A stack-allocated, column-major, 3x4 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3x4<N> = Matrix<N, U3, U4, Owned<N, U3, U4>>;
/// A stack-allocated, column-major, 3x5 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3x5<N> = Matrix<N, U3, U5, Owned<N, U3, U5>>;
/// A stack-allocated, column-major, 3x6 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3x6<N> = Matrix<N, U3, U6, Owned<N, U3, U6>>;
/// A stack-allocated, column-major, 4x5 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4x5<N> = Matrix<N, U4, U5, Owned<N, U4, U5>>;
/// A stack-allocated, column-major, 4x6 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4x6<N> = Matrix<N, U4, U6, Owned<N, U4, U6>>;
/// A stack-allocated, column-major, 5x6 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5x6<N> = Matrix<N, U5, U6, Owned<N, U5, U6>>;
/// A stack-allocated, column-major, 2x1 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix2x1<N> = Matrix<N, U2, U1, Owned<N, U2, U1>>;
/// A stack-allocated, column-major, 3x1 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3x1<N> = Matrix<N, U3, U1, Owned<N, U3, U1>>;
/// A stack-allocated, column-major, 4x1 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4x1<N> = Matrix<N, U4, U1, Owned<N, U4, U1>>;
/// A stack-allocated, column-major, 5x1 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5x1<N> = Matrix<N, U5, U1, Owned<N, U5, U1>>;
/// A stack-allocated, column-major, 6x1 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6x1<N> = Matrix<N, U6, U1, Owned<N, U6, U1>>;
/// A stack-allocated, column-major, 3x2 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix3x2<N> = Matrix<N, U3, U2, Owned<N, U3, U2>>;
/// A stack-allocated, column-major, 4x2 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4x2<N> = Matrix<N, U4, U2, Owned<N, U4, U2>>;
/// A stack-allocated, column-major, 5x2 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5x2<N> = Matrix<N, U5, U2, Owned<N, U5, U2>>;
/// A stack-allocated, column-major, 6x2 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6x2<N> = Matrix<N, U6, U2, Owned<N, U6, U2>>;
/// A stack-allocated, column-major, 4x3 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix4x3<N> = Matrix<N, U4, U3, Owned<N, U4, U3>>;
/// A stack-allocated, column-major, 5x3 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5x3<N> = Matrix<N, U5, U3, Owned<N, U5, U3>>;
/// A stack-allocated, column-major, 6x3 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6x3<N> = Matrix<N, U6, U3, Owned<N, U6, U3>>;
/// A stack-allocated, column-major, 5x4 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix5x4<N> = Matrix<N, U5, U4, Owned<N, U5, U4>>;
/// A stack-allocated, column-major, 6x4 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6x4<N> = Matrix<N, U6, U4, Owned<N, U6, U4>>;
/// A stack-allocated, column-major, 6x5 matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type Matrix6x5<N> = Matrix<N, U6, U5, Owned<N, U6, U5>>;
/*

View File

@ -10,129 +10,207 @@ use crate::base::Matrix;
*
*/
/// A column-major matrix slice with `R` rows and `C` columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMN<'a, N, R, C, RStride = U1, CStride = R> =
Matrix<N, R, C, SliceStorage<'a, N, R, C, RStride, CStride>>;
/// A column-major matrix slice with `D` rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceN<'a, N, D, RStride = U1, CStride = D> =
Matrix<N, D, D, SliceStorage<'a, N, D, D, RStride, CStride>>;
/// A column-major matrix slice dynamic numbers of rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixSlice<'a, N, RStride = U1, CStride = Dynamic> =
Matrix<N, Dynamic, Dynamic, SliceStorage<'a, N, Dynamic, Dynamic, RStride, CStride>>;
/// A column-major 1x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U1, SliceStorage<'a, N, U1, U1, RStride, CStride>>;
/// A column-major 2x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U2, SliceStorage<'a, N, U2, U2, RStride, CStride>>;
/// A column-major 3x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U3, SliceStorage<'a, N, U3, U3, RStride, CStride>>;
/// A column-major 4x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U4, SliceStorage<'a, N, U4, U4, RStride, CStride>>;
/// A column-major 5x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U5, SliceStorage<'a, N, U5, U5, RStride, CStride>>;
/// A column-major 6x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U6, SliceStorage<'a, N, U6, U6, RStride, CStride>>;
/// A column-major 1x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1x2<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U2, SliceStorage<'a, N, U1, U2, RStride, CStride>>;
/// A column-major 1x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1x3<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U3, SliceStorage<'a, N, U1, U3, RStride, CStride>>;
/// A column-major 1x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1x4<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U4, SliceStorage<'a, N, U1, U4, RStride, CStride>>;
/// A column-major 1x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1x5<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U5, SliceStorage<'a, N, U1, U5, RStride, CStride>>;
/// A column-major 1x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice1x6<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U6, SliceStorage<'a, N, U1, U6, RStride, CStride>>;
/// A column-major 2x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2x1<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U1, SliceStorage<'a, N, U2, U1, RStride, CStride>>;
/// A column-major 2x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2x3<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U3, SliceStorage<'a, N, U2, U3, RStride, CStride>>;
/// A column-major 2x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2x4<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U4, SliceStorage<'a, N, U2, U4, RStride, CStride>>;
/// A column-major 2x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2x5<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U5, SliceStorage<'a, N, U2, U5, RStride, CStride>>;
/// A column-major 2x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice2x6<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U6, SliceStorage<'a, N, U2, U6, RStride, CStride>>;
/// A column-major 3x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3x1<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U1, SliceStorage<'a, N, U3, U1, RStride, CStride>>;
/// A column-major 3x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3x2<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U2, SliceStorage<'a, N, U3, U2, RStride, CStride>>;
/// A column-major 3x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3x4<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U4, SliceStorage<'a, N, U3, U4, RStride, CStride>>;
/// A column-major 3x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3x5<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U5, SliceStorage<'a, N, U3, U5, RStride, CStride>>;
/// A column-major 3x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice3x6<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U6, SliceStorage<'a, N, U3, U6, RStride, CStride>>;
/// A column-major 4x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4x1<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U1, SliceStorage<'a, N, U4, U1, RStride, CStride>>;
/// A column-major 4x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4x2<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U2, SliceStorage<'a, N, U4, U2, RStride, CStride>>;
/// A column-major 4x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4x3<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U3, SliceStorage<'a, N, U4, U3, RStride, CStride>>;
/// A column-major 4x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4x5<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U5, SliceStorage<'a, N, U4, U5, RStride, CStride>>;
/// A column-major 4x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice4x6<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U6, SliceStorage<'a, N, U4, U6, RStride, CStride>>;
/// A column-major 5x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5x1<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U1, SliceStorage<'a, N, U5, U1, RStride, CStride>>;
/// A column-major 5x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5x2<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U2, SliceStorage<'a, N, U5, U2, RStride, CStride>>;
/// A column-major 5x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5x3<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U3, SliceStorage<'a, N, U5, U3, RStride, CStride>>;
/// A column-major 5x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5x4<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U4, SliceStorage<'a, N, U5, U4, RStride, CStride>>;
/// A column-major 5x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice5x6<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U6, SliceStorage<'a, N, U5, U6, RStride, CStride>>;
/// A column-major 6x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6x1<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U1, SliceStorage<'a, N, U6, U1, RStride, CStride>>;
/// A column-major 6x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6x2<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U2, SliceStorage<'a, N, U6, U2, RStride, CStride>>;
/// A column-major 6x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6x3<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U3, SliceStorage<'a, N, U6, U3, RStride, CStride>>;
/// A column-major 6x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6x4<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U4, SliceStorage<'a, N, U6, U4, RStride, CStride>>;
/// A column-major 6x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSlice6x5<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U5, SliceStorage<'a, N, U6, U5, RStride, CStride>>;
@ -183,21 +261,33 @@ pub type DVectorSlice<'a, N, RStride = U1, CStride = Dynamic> =
Matrix<N, Dynamic, U1, SliceStorage<'a, N, Dynamic, U1, RStride, CStride>>;
/// A 1D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice1<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U1, SliceStorage<'a, N, U1, U1, RStride, CStride>>;
/// A 2D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice2<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U1, SliceStorage<'a, N, U2, U1, RStride, CStride>>;
/// A 3D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice3<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U1, SliceStorage<'a, N, U3, U1, RStride, CStride>>;
/// A 4D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice4<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U1, SliceStorage<'a, N, U4, U1, RStride, CStride>>;
/// A 5D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice5<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U1, SliceStorage<'a, N, U5, U1, RStride, CStride>>;
/// A 6D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSlice6<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U1, SliceStorage<'a, N, U6, U1, RStride, CStride>>;
@ -209,129 +299,207 @@ pub type VectorSlice6<'a, N, RStride = U1, CStride = U6> =
*
*/
/// A column-major matrix slice with `R` rows and `C` columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMutMN<'a, N, R, C, RStride = U1, CStride = R> =
Matrix<N, R, C, SliceStorageMut<'a, N, R, C, RStride, CStride>>;
/// A column-major matrix slice with `D` rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMutN<'a, N, D, RStride = U1, CStride = D> =
Matrix<N, D, D, SliceStorageMut<'a, N, D, D, RStride, CStride>>;
/// A column-major matrix slice dynamic numbers of rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixSliceMut<'a, N, RStride = U1, CStride = Dynamic> =
Matrix<N, Dynamic, Dynamic, SliceStorageMut<'a, N, Dynamic, Dynamic, RStride, CStride>>;
/// A column-major 1x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U1, SliceStorageMut<'a, N, U1, U1, RStride, CStride>>;
/// A column-major 2x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U2, SliceStorageMut<'a, N, U2, U2, RStride, CStride>>;
/// A column-major 3x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U3, SliceStorageMut<'a, N, U3, U3, RStride, CStride>>;
/// A column-major 4x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U4, SliceStorageMut<'a, N, U4, U4, RStride, CStride>>;
/// A column-major 5x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U5, SliceStorageMut<'a, N, U5, U5, RStride, CStride>>;
/// A column-major 6x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U6, SliceStorageMut<'a, N, U6, U6, RStride, CStride>>;
/// A column-major 1x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1x2<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U2, SliceStorageMut<'a, N, U1, U2, RStride, CStride>>;
/// A column-major 1x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1x3<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U3, SliceStorageMut<'a, N, U1, U3, RStride, CStride>>;
/// A column-major 1x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1x4<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U4, SliceStorageMut<'a, N, U1, U4, RStride, CStride>>;
/// A column-major 1x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1x5<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U5, SliceStorageMut<'a, N, U1, U5, RStride, CStride>>;
/// A column-major 1x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut1x6<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U6, SliceStorageMut<'a, N, U1, U6, RStride, CStride>>;
/// A column-major 2x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2x1<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U1, SliceStorageMut<'a, N, U2, U1, RStride, CStride>>;
/// A column-major 2x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2x3<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U3, SliceStorageMut<'a, N, U2, U3, RStride, CStride>>;
/// A column-major 2x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2x4<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U4, SliceStorageMut<'a, N, U2, U4, RStride, CStride>>;
/// A column-major 2x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2x5<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U5, SliceStorageMut<'a, N, U2, U5, RStride, CStride>>;
/// A column-major 2x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut2x6<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U6, SliceStorageMut<'a, N, U2, U6, RStride, CStride>>;
/// A column-major 3x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3x1<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U1, SliceStorageMut<'a, N, U3, U1, RStride, CStride>>;
/// A column-major 3x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3x2<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U2, SliceStorageMut<'a, N, U3, U2, RStride, CStride>>;
/// A column-major 3x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3x4<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U4, SliceStorageMut<'a, N, U3, U4, RStride, CStride>>;
/// A column-major 3x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3x5<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U5, SliceStorageMut<'a, N, U3, U5, RStride, CStride>>;
/// A column-major 3x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut3x6<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U6, SliceStorageMut<'a, N, U3, U6, RStride, CStride>>;
/// A column-major 4x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4x1<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U1, SliceStorageMut<'a, N, U4, U1, RStride, CStride>>;
/// A column-major 4x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4x2<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U2, SliceStorageMut<'a, N, U4, U2, RStride, CStride>>;
/// A column-major 4x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4x3<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U3, SliceStorageMut<'a, N, U4, U3, RStride, CStride>>;
/// A column-major 4x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4x5<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U5, SliceStorageMut<'a, N, U4, U5, RStride, CStride>>;
/// A column-major 4x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut4x6<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U6, SliceStorageMut<'a, N, U4, U6, RStride, CStride>>;
/// A column-major 5x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5x1<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U1, SliceStorageMut<'a, N, U5, U1, RStride, CStride>>;
/// A column-major 5x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5x2<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U2, SliceStorageMut<'a, N, U5, U2, RStride, CStride>>;
/// A column-major 5x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5x3<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U3, SliceStorageMut<'a, N, U5, U3, RStride, CStride>>;
/// A column-major 5x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5x4<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U4, SliceStorageMut<'a, N, U5, U4, RStride, CStride>>;
/// A column-major 5x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut5x6<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U6, SliceStorageMut<'a, N, U5, U6, RStride, CStride>>;
/// A column-major 6x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6x1<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U1, SliceStorageMut<'a, N, U6, U1, RStride, CStride>>;
/// A column-major 6x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6x2<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U2, SliceStorageMut<'a, N, U6, U2, RStride, CStride>>;
/// A column-major 6x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6x3<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U3, SliceStorageMut<'a, N, U6, U3, RStride, CStride>>;
/// A column-major 6x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6x4<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U4, SliceStorageMut<'a, N, U6, U4, RStride, CStride>>;
/// A column-major 6x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixSliceMut6x5<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U5, SliceStorageMut<'a, N, U6, U5, RStride, CStride>>;
@ -382,20 +550,32 @@ pub type DVectorSliceMut<'a, N, RStride = U1, CStride = Dynamic> =
Matrix<N, Dynamic, U1, SliceStorageMut<'a, N, Dynamic, U1, RStride, CStride>>;
/// A 1D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut1<'a, N, RStride = U1, CStride = U1> =
Matrix<N, U1, U1, SliceStorageMut<'a, N, U1, U1, RStride, CStride>>;
/// A 2D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut2<'a, N, RStride = U1, CStride = U2> =
Matrix<N, U2, U1, SliceStorageMut<'a, N, U2, U1, RStride, CStride>>;
/// A 3D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut3<'a, N, RStride = U1, CStride = U3> =
Matrix<N, U3, U1, SliceStorageMut<'a, N, U3, U1, RStride, CStride>>;
/// A 4D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut4<'a, N, RStride = U1, CStride = U4> =
Matrix<N, U4, U1, SliceStorageMut<'a, N, U4, U1, RStride, CStride>>;
/// A 5D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut5<'a, N, RStride = U1, CStride = U5> =
Matrix<N, U5, U1, SliceStorageMut<'a, N, U5, U1, RStride, CStride>>;
/// A 6D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorSliceMut6<'a, N, RStride = U1, CStride = U6> =
Matrix<N, U6, U1, SliceStorageMut<'a, N, U6, U1, RStride, CStride>>;

View File

@ -56,6 +56,7 @@ impl<N: Scalar + Zero + One + ClosedAdd + ClosedSub + ClosedMul, D: Dim, S: Stor
}
}
/// # Interpolation between two unit vectors
impl<N: RealField, D: Dim, S: Storage<N, D>> Unit<Vector<N, D, S>> {
/// Computes the spherical linear interpolation between two unit vectors.
///

View File

@ -15,7 +15,14 @@ use crate::{Dim, MatrixMN, RealField, Scalar, SimdComplexField, SimdRealField};
/// A wrapper that ensures the underlying algebraic entity has a unit norm.
///
/// Use `.as_ref()` or `.into_inner()` to obtain the underlying value by-reference or by-move.
/// **It is likely that the only piece of documentation that you need in this page are:**
/// - **[The construction with normalization](#construction-with-normalization)**
/// - **[Data extraction and construction without normalization](#data-extraction-and-construction-without-normalization)**
/// - **[Interpolation between two unit vectors](#interpolation-between-two-unit-vectors)**
///
/// All the other impl blocks you will see in this page are about [`UnitComplex`](crate::UnitComplex)
/// and [`UnitQuaternion`](crate::UnitQuaternion); both built on top of `Unit`. If you are interested
/// in their documentation, read their dedicated pages directly.
#[repr(transparent)]
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Unit<T> {
@ -71,6 +78,7 @@ pub trait Normed {
fn unscale_mut(&mut self, n: Self::Norm);
}
/// # Construction with normalization
impl<T: Normed> Unit<T> {
/// Normalize the given vector and return it wrapped on a `Unit` structure.
#[inline]
@ -140,6 +148,7 @@ impl<T: Normed> Unit<T> {
}
}
/// # Data extraction and construction without normalization
impl<T> Unit<T> {
/// Wraps the given value, assuming it is already normalized.
#[inline]

View File

@ -14,14 +14,45 @@ use simba::scalar::{RealField, SubsetOf};
use simba::simd::SimdRealField;
use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3};
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use crate::base::storage::Owned;
use crate::base::{DefaultAllocator, MatrixN, Scalar, Unit, VectorN};
use crate::geometry::{
AbstractRotation, Point, Rotation2, Rotation3, Translation, UnitComplex, UnitQuaternion,
};
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.
/// A direct isometry, i.e., a rotation followed by a translation (aka. a rigid-body motion).
///
/// This is also known as an element of a Special Euclidean (SE) group.
/// The `Isometry` type can either represent a 2D or 3D isometry.
/// A 2D isometry is composed of:
/// - A translation part of type [`Translation2`](crate::Translation2)
/// - A rotation part which can either be a [`UnitComplex`](crate::UnitComplex) or a [`Rotation2`](crate::Rotation2).
/// A 3D isometry is composed of:
/// - A translation part of type [`Translation3`](crate::Translation3)
/// - A rotation part which can either be a [`UnitQuaternion`](crate::UnitQuaternion) or a [`Rotation3`](crate::Rotation3).
///
/// Note that instead of using the [`Isometry`](crate::Isometry) type in your code directly, you should use one
/// of its aliases: [`Isometry2`](crate::Isometry2), [`Isometry3`](crate::Isometry3),
/// [`IsometryMatrix2`](crate::IsometryMatrix2), [`IsometryMatrix3`](crate::IsometryMatrix3). Though
/// keep in mind that all the documentation of all the methods of these aliases will also appears on
/// this page.
///
/// # Construction
/// * [From a 2D vector and/or an angle <span style="float:right;">`new`, `translation`, `rotation`…</span>](#construction-from-a-2d-vector-andor-a-rotation-angle)
/// * [From a 3D vector and/or an axis-angle <span style="float:right;">`new`, `translation`, `rotation`…</span>](#construction-from-a-3d-vector-andor-an-axis-angle)
/// * [From a 3D eye position and target point <span style="float:right;">`look_at`, `look_at_lh`, `face_towards`…</span>](#construction-from-a-3d-eye-position-and-target-point)
/// * [From the translation and rotation parts <span style="float:right;">`from_parts`…</span>](#from-the-translation-and-rotation-parts)
///
/// # Transformation and composition
/// Note that transforming vectors and points can be done by multiplication, e.g., `isometry * point`.
/// Composing an isometry with another transformation can also be done by multiplication or division.
///
/// * [Transformation of a vector or a point <span style="float:right;">`transform_vector`, `inverse_transform_point`…</span>](#transformation-of-a-vector-or-a-point)
/// * [Inversion and in-place composition <span style="float:right;">`inverse`, `append_rotation_wrt_point_mut`…</span>](#inversion-and-in-place-composition)
/// * [Interpolation <span style="float:right;">`lerp_slerp`…</span>](#interpolation)
///
/// # Conversion to a matrix
/// * [Conversion to a matrix <span style="float:right;">`to_matrix`…</span>](#conversion-to-a-matrix)
///
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
@ -103,7 +134,7 @@ where
}
}
}
/// # From the translation and rotation parts
impl<N: Scalar, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
where
DefaultAllocator: Allocator<N, D>,
@ -131,6 +162,7 @@ where
}
}
/// # Inversion and in-place composition
impl<N: SimdRealField, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
where
N::Element: SimdRealField,
@ -261,7 +293,14 @@ where
pub fn append_rotation_wrt_center_mut(&mut self, r: &R) {
self.rotation = r.clone() * self.rotation.clone();
}
}
/// # Transformation of a vector or a point
impl<N: SimdRealField, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
where
N::Element: SimdRealField,
DefaultAllocator: Allocator<N, D>,
{
/// Transform the given point by this isometry.
///
/// This is the same as the multiplication `self * pt`.
@ -377,224 +416,19 @@ where
}
}
impl<N: SimdRealField> Isometry<N, U3, UnitQuaternion<N>> {
/// 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::{Vector3, Translation3, Isometry3, UnitQuaternion};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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);
/// 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::{Vector3, Translation3, Isometry3, UnitQuaternion};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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);
/// 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<Self>
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<N: SimdRealField> Isometry<N, U3, Rotation3<N>> {
/// 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::{Vector3, Translation3, Rotation3, IsometryMatrix3};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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 = 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.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::{Vector3, Translation3, Rotation3, IsometryMatrix3};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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 = 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.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<Self>
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<N: SimdRealField> Isometry<N, U2, UnitComplex<N>> {
/// 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:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Vector2, Translation2, UnitComplex, Isometry2};
///
/// let t1 = Translation2::new(1.0, 2.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);
/// 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_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2);
/// ```
#[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)
}
}
impl<N: SimdRealField> Isometry<N, U2, Rotation2<N>> {
/// 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:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Vector2, Translation2, Rotation2, IsometryMatrix2};
///
/// let t1 = Translation2::new(1.0, 2.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 = 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_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2);
/// ```
#[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)
}
}
// 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
// explicit struct construction is prevented by the dummy ZST field).
/// # Conversion to a matrix
impl<N: SimdRealField, D: DimName, R> Isometry<N, D, R>
where
DefaultAllocator: Allocator<N, D>,
{
/// Converts this isometry into its equivalent homogeneous transformation matrix.
///
/// This is the same as `self.to_matrix()`.
///
/// # Example
///
/// ```
@ -621,6 +455,33 @@ where
res
}
/// Converts this isometry into its equivalent homogeneous transformation matrix.
///
/// This is the same as `self.to_homogeneous()`.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry2, Vector2, Matrix3};
/// let iso = Isometry2::new(Vector2::new(10.0, 20.0), f32::consts::FRAC_PI_6);
/// let expected = Matrix3::new(0.8660254, -0.5, 10.0,
/// 0.5, 0.8660254, 20.0,
/// 0.0, 0.0, 1.0);
///
/// assert_relative_eq!(iso.to_matrix(), expected, epsilon = 1.0e-6);
/// ```
#[inline]
pub fn to_matrix(&self) -> MatrixN<N, DimNameSum<D, U1>>
where
D: DimNameAdd<U1>,
R: SubsetOf<MatrixN<N, DimNameSum<D, U1>>>,
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
{
self.to_homogeneous()
}
}
impl<N: SimdRealField, D: DimName, R> Eq for Isometry<N, D, R>

View File

@ -2,16 +2,33 @@ use crate::base::dimension::{U2, U3};
use crate::geometry::{Isometry, Rotation2, Rotation3, UnitComplex, UnitQuaternion};
/// A 2-dimensional direct isometry using a unit complex number for its rotational part. Also known as a rigid-body motion, or as an element of SE(2).
/// A 2-dimensional direct isometry using a unit complex number for its rotational part.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Isometry`](crate::Isometry) type too.**
///
/// Also known as a 2D rigid-body motion, or as an element of SE(2).
pub type Isometry2<N> = Isometry<N, U2, UnitComplex<N>>;
/// A 3-dimensional direct isometry using a unit quaternion for its rotational part. Also known as a rigid-body motion, or as an element of SE(3).
/// A 3-dimensional direct isometry using a unit quaternion for its rotational part.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Isometry`](crate::Isometry) type too.**
///
/// Also known as a rigid-body motion, or as an element of SE(3).
pub type Isometry3<N> = Isometry<N, U3, UnitQuaternion<N>>;
/// A 2-dimensional direct isometry using a rotation matrix for its rotational part. Also known as a rigid-body motion, or as an element of SE(2).
/// A 2-dimensional direct isometry using a rotation matrix for its rotational part.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Isometry`](crate::Isometry) type too.**
///
/// Also known as a rigid-body motion, or as an element of SE(2).
pub type IsometryMatrix2<N> = Isometry<N, U2, Rotation2<N>>;
/// A 3-dimensional direct isometry using a rotation matrix for its rotational part. Also known as a rigid-body motion, or as an element of SE(3).
/// A 3-dimensional direct isometry using a rotation matrix for its rotational part.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Isometry`](crate::Isometry) type too.**
///
/// Also known as a rigid-body motion, or as an element of SE(3).
pub type IsometryMatrix3<N> = Isometry<N, U3, Rotation3<N>>;
// This tests that the types correctly implement `Copy`, without having to run tests

View File

@ -11,12 +11,13 @@ use simba::scalar::RealField;
use simba::simd::SimdRealField;
use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, U2, U3};
use crate::base::dimension::{DimName, U2};
use crate::base::{DefaultAllocator, Vector2, Vector3};
use crate::geometry::{
AbstractRotation, Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation,
Translation2, Translation3, UnitComplex, UnitQuaternion,
AbstractRotation, Isometry, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Point,
Point3, Rotation, Rotation3, Translation, Translation2, Translation3, UnitComplex,
UnitQuaternion,
};
impl<N: SimdRealField, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
@ -112,8 +113,8 @@ where
*
*/
// 2D rotation.
impl<N: SimdRealField> Isometry<N, U2, Rotation2<N>>
/// # Construction from a 2D vector and/or a rotation angle
impl<N: SimdRealField> IsometryMatrix2<N>
where
N::Element: SimdRealField,
{
@ -151,7 +152,7 @@ where
}
}
impl<N: SimdRealField> Isometry<N, U2, UnitComplex<N>>
impl<N: SimdRealField> Isometry2<N>
where
N::Element: SimdRealField,
{
@ -190,191 +191,219 @@ where
}
// 3D rotation.
macro_rules! isometry_construction_impl(
($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
impl<N: SimdRealField> Isometry<N, U3, $RotId<$($RotParams),*>>
where N::Element: SimdRealField {
/// Creates a new isometry from a translation and a rotation axis-angle.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2;
/// let translation = Vector3::new(1.0, 2.0, 3.0);
/// // Point and vector being transformed in the tests.
/// let pt = Point3::new(4.0, 5.0, 6.0);
/// let vec = Vector3::new(4.0, 5.0, 6.0);
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::new(translation, axisangle);
/// assert_relative_eq!(iso * pt, Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
/// assert_relative_eq!(iso * vec, Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
///
/// // Isometry with its rotation part represented as a Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::new(translation, axisangle);
/// assert_relative_eq!(iso * pt, Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
/// assert_relative_eq!(iso * vec, Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
/// ```
#[inline]
pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
Self::from_parts(
Translation::from(translation),
$RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
}
macro_rules! basic_isometry_construction_impl(
($RotId: ident < $($RotParams: ident),*>) => {
/// Creates a new isometry from a translation and a rotation axis-angle.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2;
/// let translation = Vector3::new(1.0, 2.0, 3.0);
/// // Point and vector being transformed in the tests.
/// let pt = Point3::new(4.0, 5.0, 6.0);
/// let vec = Vector3::new(4.0, 5.0, 6.0);
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::new(translation, axisangle);
/// assert_relative_eq!(iso * pt, Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
/// assert_relative_eq!(iso * vec, Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
///
/// // Isometry with its rotation part represented as a Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::new(translation, axisangle);
/// assert_relative_eq!(iso * pt, Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
/// assert_relative_eq!(iso * vec, Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
/// ```
#[inline]
pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
Self::from_parts(
Translation::from(translation),
$RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
}
/// Creates a new isometry from the given translation coordinates.
#[inline]
pub fn translation(x: N, y: N, z: N) -> Self {
Self::from_parts(Translation3::new(x, y, z), $RotId::identity())
}
/// Creates a new isometry from the given translation coordinates.
#[inline]
pub fn translation(x: N, y: N, z: N) -> Self {
Self::from_parts(Translation3::new(x, y, z), $RotId::identity())
}
/// Creates a new isometry from the given rotation angle.
#[inline]
pub fn rotation(axisangle: Vector3<N>) -> Self {
Self::new(Vector3::zeros(), axisangle)
}
/// Creates an isometry that corresponds to the local frame of an observer standing at the
/// point `eye` and looking toward `target`.
///
/// It maps the `z` axis to the view direction `target - eye`and the origin to the `eye`.
///
/// # Arguments
/// * eye - The observer position.
/// * target - The target position.
/// * up - Vertical direction. The only requirement of this parameter is to not be collinear
/// to `eye - at`. Non-collinearity is not checked.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::face_towards(&eye, &target, &up);
/// assert_eq!(iso * Point3::origin(), eye);
/// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::face_towards(&eye, &target, &up);
/// assert_eq!(iso * Point3::origin(), eye);
/// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
/// ```
#[inline]
pub fn face_towards(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
Self::from_parts(
Translation::from(eye.coords.clone()),
$RotId::face_towards(&(target - eye), up))
}
/// Deprecated: Use [Isometry::face_towards] instead.
#[deprecated(note="renamed to `face_towards`")]
pub fn new_observer_frame(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
Self::face_towards(eye, target, up)
}
/// Builds a right-handed look-at view matrix.
///
/// It maps the view direction `target - eye` to the **negative** `z` axis to and the `eye` to the origin.
/// This conforms to the common notion of right handed camera look-at **view matrix** from
/// the computer graphics community, i.e. the camera is assumed to look toward its local `-z` axis.
///
/// # Arguments
/// * eye - The eye position.
/// * target - The target position.
/// * up - A vector approximately aligned with required the vertical axis. The only
/// requirement of this parameter is to not be collinear to `target - eye`.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::look_at_rh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::look_at_rh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
/// ```
#[inline]
pub fn look_at_rh(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
let rotation = $RotId::look_at_rh(&(target - eye), up);
let trans = &rotation * (-eye);
Self::from_parts(Translation::from(trans.coords), rotation)
}
/// Builds a left-handed look-at view matrix.
///
/// It maps the view direction `target - eye` to the **positive** `z` axis and the `eye` to the origin.
/// This conforms to the common notion of right handed camera look-at **view matrix** from
/// the computer graphics community, i.e. the camera is assumed to look toward its local `z` axis.
///
/// # Arguments
/// * eye - The eye position.
/// * target - The target position.
/// * up - A vector approximately aligned with required the vertical axis. The only
/// requirement of this parameter is to not be collinear to `target - eye`.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::look_at_lh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::look_at_lh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
/// ```
#[inline]
pub fn look_at_lh(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
let rotation = $RotId::look_at_lh(&(target - eye), up);
let trans = &rotation * (-eye);
Self::from_parts(Translation::from(trans.coords), rotation)
}
/// Creates a new isometry from the given rotation angle.
#[inline]
pub fn rotation(axisangle: Vector3<N>) -> Self {
Self::new(Vector3::zeros(), axisangle)
}
}
);
isometry_construction_impl!(Rotation3<N>, U3, U3);
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
macro_rules! look_at_isometry_construction_impl(
($RotId: ident < $($RotParams: ident),*>) => {
/// Creates an isometry that corresponds to the local frame of an observer standing at the
/// point `eye` and looking toward `target`.
///
/// It maps the `z` axis to the view direction `target - eye`and the origin to the `eye`.
///
/// # Arguments
/// * eye - The observer position.
/// * target - The target position.
/// * up - Vertical direction. The only requirement of this parameter is to not be collinear
/// to `eye - at`. Non-collinearity is not checked.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::face_towards(&eye, &target, &up);
/// assert_eq!(iso * Point3::origin(), eye);
/// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::face_towards(&eye, &target, &up);
/// assert_eq!(iso * Point3::origin(), eye);
/// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
/// ```
#[inline]
pub fn face_towards(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
Self::from_parts(
Translation::from(eye.coords.clone()),
$RotId::face_towards(&(target - eye), up))
}
/// Deprecated: Use [Isometry::face_towards] instead.
#[deprecated(note="renamed to `face_towards`")]
pub fn new_observer_frame(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
Self::face_towards(eye, target, up)
}
/// Builds a right-handed look-at view matrix.
///
/// It maps the view direction `target - eye` to the **negative** `z` axis to and the `eye` to the origin.
/// This conforms to the common notion of right handed camera look-at **view matrix** from
/// the computer graphics community, i.e. the camera is assumed to look toward its local `-z` axis.
///
/// # Arguments
/// * eye - The eye position.
/// * target - The target position.
/// * up - A vector approximately aligned with required the vertical axis. The only
/// requirement of this parameter is to not be collinear to `target - eye`.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::look_at_rh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::look_at_rh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
/// ```
#[inline]
pub fn look_at_rh(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
let rotation = $RotId::look_at_rh(&(target - eye), up);
let trans = &rotation * (-eye);
Self::from_parts(Translation::from(trans.coords), rotation)
}
/// Builds a left-handed look-at view matrix.
///
/// It maps the view direction `target - eye` to the **positive** `z` axis and the `eye` to the origin.
/// This conforms to the common notion of right handed camera look-at **view matrix** from
/// the computer graphics community, i.e. the camera is assumed to look toward its local `z` axis.
///
/// # Arguments
/// * eye - The eye position.
/// * target - The target position.
/// * up - A vector approximately aligned with required the vertical axis. The only
/// requirement of this parameter is to not be collinear to `target - eye`.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use std::f32;
/// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
/// let eye = Point3::new(1.0, 2.0, 3.0);
/// let target = Point3::new(2.0, 2.0, 3.0);
/// let up = Vector3::y();
///
/// // Isometry with its rotation part represented as a UnitQuaternion
/// let iso = Isometry3::look_at_lh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
///
/// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
/// let iso = IsometryMatrix3::look_at_lh(&eye, &target, &up);
/// assert_eq!(iso * eye, Point3::origin());
/// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
/// ```
#[inline]
pub fn look_at_lh(eye: &Point3<N>,
target: &Point3<N>,
up: &Vector3<N>)
-> Self {
let rotation = $RotId::look_at_lh(&(target - eye), up);
let trans = &rotation * (-eye);
Self::from_parts(Translation::from(trans.coords), rotation)
}
}
);
/// # Construction from a 3D vector and/or an axis-angle
impl<N: SimdRealField> Isometry3<N>
where
N::Element: SimdRealField,
{
basic_isometry_construction_impl!(UnitQuaternion<N>);
}
impl<N: SimdRealField> IsometryMatrix3<N>
where
N::Element: SimdRealField,
{
basic_isometry_construction_impl!(Rotation3<N>);
}
/// # Construction from a 3D eye position and target point
impl<N: SimdRealField> Isometry3<N>
where
N::Element: SimdRealField,
{
look_at_isometry_construction_impl!(UnitQuaternion<N>);
}
impl<N: SimdRealField> IsometryMatrix3<N>
where
N::Element: SimdRealField,
{
look_at_isometry_construction_impl!(Rotation3<N>);
}

View File

@ -0,0 +1,210 @@
use crate::{Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, RealField, SimdRealField};
/// # Interpolation
impl<N: SimdRealField> Isometry3<N> {
/// 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::{Vector3, Translation3, Isometry3, UnitQuaternion};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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);
/// 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::{Vector3, Translation3, Isometry3, UnitQuaternion};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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);
/// 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<Self>
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<N: SimdRealField> IsometryMatrix3<N> {
/// 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::{Vector3, Translation3, Rotation3, IsometryMatrix3};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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 = 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.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::{Vector3, Translation3, Rotation3, IsometryMatrix3};
///
/// let t1 = Translation3::new(1.0, 2.0, 3.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 = 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.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<Self>
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<N: SimdRealField> Isometry2<N> {
/// 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:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Vector2, Translation2, UnitComplex, Isometry2};
///
/// let t1 = Translation2::new(1.0, 2.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);
/// 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_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2);
/// ```
#[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)
}
}
impl<N: SimdRealField> IsometryMatrix2<N> {
/// 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:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Vector2, Translation2, Rotation2, IsometryMatrix2};
///
/// let t1 = Translation2::new(1.0, 2.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 = 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_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2);
/// ```
#[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)
}
}

View File

@ -21,6 +21,7 @@ mod rotation_alga;
mod rotation_alias;
mod rotation_construction;
mod rotation_conversion;
mod rotation_interpolation;
mod rotation_ops;
mod rotation_simba; // TODO: implement Rotation methods.
mod rotation_specialization;
@ -58,6 +59,7 @@ mod isometry_alga;
mod isometry_alias;
mod isometry_construction;
mod isometry_conversion;
mod isometry_interpolation;
mod isometry_ops;
mod isometry_simba;

View File

@ -19,7 +19,25 @@ use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use crate::base::iter::{MatrixIter, MatrixIterMut};
use crate::base::{DefaultAllocator, Scalar, VectorN};
/// A point in a n-dimensional euclidean space.
/// A point in an euclidean space.
///
/// The difference between a point and a vector is only semantic. See [the user guide](https://www.nalgebra.org/points_and_transformations/)
/// for details on the distinction. The most notable difference that vectors ignore translations.
/// In particular, an [`Isometry2`](crate::Isometry2) or [`Isometry3`](crate::Isometry3) will
/// transform points by applying a rotation and a translation on them. However, these isometries
/// will only apply rotations to vectors (when doing `isometry * vector`, the translation part of
/// the isometry is ignored).
///
/// # Construction
/// * [From individual components <span style="float:right;">`new`…</span>](#construction-from-individual-components)
/// * [Swizzling <span style="float:right;">`xx`, `yxz`…</span>](#swizzling)
/// * [Other construction methods <span style="float:right;">`origin`, `from_slice`, `from_homogeneous`…</span>](#other-construction-methods)
///
/// # Transformation
/// Transforming a point by an [Isometry](crate::Isometry), [rotation](crate::Rotation), etc. can be
/// achieved by multiplication, e.g., `isometry * point` or `rotation * point`. Some of these transformation
/// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation
/// of said transformations for details.
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Point<N: Scalar, D: DimName>

View File

@ -3,14 +3,26 @@ use crate::base::dimension::{U1, U2, U3, U4, U5, U6};
use crate::geometry::Point;
/// A statically sized 1-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point1<N> = Point<N, U1>;
/// A statically sized 2-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point2<N> = Point<N, U2>;
/// A statically sized 3-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point3<N> = Point<N, U3>;
/// A statically sized 4-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point4<N> = Point<N, U4>;
/// A statically sized 5-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point5<N> = Point<N, U5>;
/// A statically sized 6-dimensional column point.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Point`](crate::Point) type too.**
pub type Point6<N> = Point<N, U6>;

View File

@ -6,12 +6,17 @@ use rand::distributions::{Distribution, Standard};
use rand::Rng;
use crate::base::allocator::Allocator;
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6};
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use crate::base::{DefaultAllocator, Scalar, VectorN};
use crate::{
Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, Vector4, Vector5,
Vector6,
};
use simba::scalar::ClosedDiv;
use crate::geometry::Point;
/// # Other construction methods
impl<N: Scalar, D: DimName> Point<N, D>
where
DefaultAllocator: Allocator<N, D>,
@ -79,7 +84,7 @@ where
/// assert_eq!(pt, Some(Point3::new(1.0, 2.0, 3.0)));
///
/// // All component of the result will be divided by the
/// // last component of the vector, here 2.0.
/// // last component of the vector, here 2.0.
/// let coords = Vector4::new(1.0, 2.0, 3.0, 2.0);
/// let pt = Point3::from_homogeneous(coords);
/// assert_eq!(pt, Some(Point3::new(0.5, 1.0, 1.5)));
@ -158,46 +163,56 @@ where
* Small points construction from components.
*
*/
// NOTE: the impl for Point1 is not with the others so that we
// can add a section with the impl block comment.
/// # Construction from individual components
impl<N: Scalar> Point1<N> {
/// Initializes this point from its components.
///
/// # Example
///
/// ```
/// # use nalgebra::Point1;
/// let p = Point1::new(1.0);
/// assert_eq!(p.x, 1.0);
/// ```
#[inline]
pub fn new(x: N) -> Self {
Vector1::new(x).into()
}
}
macro_rules! componentwise_constructors_impl(
($($doc: expr; $D: ty, $($args: ident:$irow: expr),*);* $(;)*) => {$(
impl<N: Scalar> Point<N, $D>
where DefaultAllocator: Allocator<N, $D> {
($($doc: expr; $Point: ident, $Vector: ident, $($args: ident:$irow: expr),*);* $(;)*) => {$(
impl<N: Scalar> $Point<N> {
#[doc = "Initializes this point from its components."]
#[doc = "# Example\n```"]
#[doc = $doc]
#[doc = "```"]
#[inline]
pub fn new($($args: N),*) -> Self {
unsafe {
let mut res = Self::new_uninitialized();
$( *res.get_unchecked_mut($irow) = $args; )*
res
}
$Vector::new($($args),*).into()
}
}
)*}
);
componentwise_constructors_impl!(
"# use nalgebra::Point1;\nlet p = Point1::new(1.0);\nassert!(p.x == 1.0);";
U1, x:0;
"# use nalgebra::Point2;\nlet p = Point2::new(1.0, 2.0);\nassert!(p.x == 1.0 && p.y == 2.0);";
U2, x:0, y:1;
Point2, Vector2, x:0, y:1;
"# use nalgebra::Point3;\nlet p = Point3::new(1.0, 2.0, 3.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0);";
U3, x:0, y:1, z:2;
Point3, Vector3, x:0, y:1, z:2;
"# use nalgebra::Point4;\nlet p = Point4::new(1.0, 2.0, 3.0, 4.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0);";
U4, x:0, y:1, z:2, w:3;
Point4, Vector4, x:0, y:1, z:2, w:3;
"# use nalgebra::Point5;\nlet p = Point5::new(1.0, 2.0, 3.0, 4.0, 5.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0);";
U5, x:0, y:1, z:2, w:3, a:4;
Point5, Vector5, x:0, y:1, z:2, w:3, a:4;
"# 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);";
U6, 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(
($($D: ty, $len: expr);*) => {$(
impl <N: Scalar> From<[N; $len]> for Point<N, $D> {
fn from (coords: [N; $len]) -> Self {
($($Point: ident, $len: expr);*) => {$(
impl <N: Scalar> From<[N; $len]> for $Point<N> {
fn from(coords: [N; $len]) -> Self {
Self {
coords: coords.into()
}
@ -206,4 +221,4 @@ macro_rules! from_array_impl(
)*}
);
from_array_impl!(U1, 1; U2, 2; U3, 3; U4, 4; U5, 5; U6, 6);
from_array_impl!(Point1, 1; Point2, 2; Point3, 3; Point4, 4; Point5, 5; Point6, 6);

View File

@ -23,6 +23,36 @@ use crate::base::{DefaultAllocator, MatrixN, Scalar, Unit, VectorN};
use crate::geometry::Point;
/// A rotation matrix.
///
/// This is also known as an element of a Special Orthogonal (SO) group.
/// The `Rotation` type can either represent a 2D or 3D rotation, represented as a matrix.
/// For a rotation based on quaternions, see [`UnitQuaternion`](crate::UnitQuaternion) instead.
///
/// Note that instead of using the [`Rotation`](crate::Rotation) type in your code directly, you should use one
/// of its aliases: [`Rotation2`](crate::Rotation2), or [`Rotation3`](crate::Rotation3). Though
/// keep in mind that all the documentation of all the methods of these aliases will also appears on
/// this page.
///
/// # Construction
/// * [Identity <span style="float:right;">`identity`</span>](#identity)
/// * [From a 2D rotation angle <span style="float:right;">`new`…</span>](#construction-from-a-2d-rotation-angle)
/// * [From an existing 2D matrix or rotations <span style="float:right;">`from_matrix`, `rotation_between`, `powf`…</span>](#construction-from-an-existing-2d-matrix-or-rotations)
/// * [From a 3D axis and/or angles <span style="float:right;">`new`, `from_euler_angles`, `from_axis_angle`…</span>](#construction-from-a-3d-axis-andor-angles)
/// * [From a 3D eye position and target point <span style="float:right;">`look_at`, `look_at_lh`, `rotation_between`…</span>](#construction-from-a-3d-eye-position-and-target-point)
/// * [From an existing 3D matrix or rotations <span style="float:right;">`from_matrix`, `rotation_between`, `powf`…</span>](#construction-from-an-existing-3d-matrix-or-rotations)
///
/// # Transformation and composition
/// Note that transforming vectors and points can be done by multiplication, e.g., `rotation * point`.
/// Composing an rotation with another transformation can also be done by multiplication or division.
/// * [3D axis and angle extraction <span style="float:right;">`angle`, `euler_angles`, `scaled_axis`, `angle_to`…</span>](#3d-axis-and-angle-extraction)
/// * [2D angle extraction <span style="float:right;">`angle`, `angle_to`…</span>](#2d-angle-extraction)
/// * [Transformation of a vector or a point <span style="float:right;">`transform_vector`, `inverse_transform_point`…</span>](#transformation-of-a-vector-or-a-point)
/// * [Transposition and inversion <span style="float:right;">`transpose`, `inverse`…</span>](#transposition-and-inversion)
/// * [Interpolation <span style="float:right;">`slerp`…</span>](#interpolation)
///
/// # Conversion
/// * [Conversion to a matrix <span style="float:right;">`matrix`, `to_homogeneous`…</span>](#conversion-to-a-matrix)
///
#[repr(C)]
#[derive(Debug)]
pub struct Rotation<N: Scalar, D: DimName>
@ -111,6 +141,44 @@ where
}
}
impl<N: Scalar, D: DimName> Rotation<N, D>
where
DefaultAllocator: Allocator<N, D, D>,
{
/// Creates a new rotation from the given square matrix.
///
/// The matrix squareness is checked but not its orthonormality.
///
/// # Example
/// ```
/// # use nalgebra::{Rotation2, Rotation3, Matrix2, Matrix3};
/// # use std::f32;
/// let mat = Matrix3::new(0.8660254, -0.5, 0.0,
/// 0.5, 0.8660254, 0.0,
/// 0.0, 0.0, 1.0);
/// let rot = Rotation3::from_matrix_unchecked(mat);
///
/// assert_eq!(*rot.matrix(), mat);
///
///
/// let mat = Matrix2::new(0.8660254, -0.5,
/// 0.5, 0.8660254);
/// let rot = Rotation2::from_matrix_unchecked(mat);
///
/// assert_eq!(*rot.matrix(), mat);
/// ```
#[inline]
pub fn from_matrix_unchecked(matrix: MatrixN<N, D>) -> Self {
assert!(
matrix.is_square(),
"Unable to create a rotation from a non-square matrix."
);
Self { matrix }
}
}
/// # Conversion to a matrix
impl<N: Scalar, D: DimName> Rotation<N, D>
where
DefaultAllocator: Allocator<N, D, D>,
@ -225,39 +293,13 @@ where
res
}
}
/// Creates a new rotation from the given square matrix.
///
/// The matrix squareness is checked but not its orthonormality.
///
/// # Example
/// ```
/// # use nalgebra::{Rotation2, Rotation3, Matrix2, Matrix3};
/// # use std::f32;
/// let mat = Matrix3::new(0.8660254, -0.5, 0.0,
/// 0.5, 0.8660254, 0.0,
/// 0.0, 0.0, 1.0);
/// let rot = Rotation3::from_matrix_unchecked(mat);
///
/// assert_eq!(*rot.matrix(), mat);
///
///
/// let mat = Matrix2::new(0.8660254, -0.5,
/// 0.5, 0.8660254);
/// let rot = Rotation2::from_matrix_unchecked(mat);
///
/// assert_eq!(*rot.matrix(), mat);
/// ```
#[inline]
pub fn from_matrix_unchecked(matrix: MatrixN<N, D>) -> Self {
assert!(
matrix.is_square(),
"Unable to create a rotation from a non-square matrix."
);
Self { matrix }
}
/// # Transposition and inversion
impl<N: Scalar, D: DimName> Rotation<N, D>
where
DefaultAllocator: Allocator<N, D, D>,
{
/// Transposes `self`.
///
/// Same as `.inverse()` because the inverse of a rotation matrix is its transform.
@ -361,6 +403,7 @@ where
}
}
/// # Transformation of a vector or a point
impl<N: SimdRealField, D: DimName> Rotation<N, D>
where
N::Element: SimdRealField,

View File

@ -3,7 +3,11 @@ use crate::base::dimension::{U2, U3};
use crate::geometry::Rotation;
/// A 2-dimensional rotation matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Rotation`](crate::Rotation) type too.**
pub type Rotation2<N> = Rotation<N, U2>;
/// A 3-dimensional rotation matrix.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Rotation`](crate::Rotation) type too.**
pub type Rotation3<N> = Rotation<N, U3>;

View File

@ -8,6 +8,7 @@ use crate::base::{DefaultAllocator, MatrixN, Scalar};
use crate::geometry::Rotation;
/// # Identity
impl<N, D: DimName> Rotation<N, D>
where
N: Scalar + Zero + One,

View File

@ -0,0 +1,78 @@
use crate::{RealField, Rotation2, Rotation3, SimdRealField, UnitComplex, UnitQuaternion};
/// # Interpolation
impl<N: SimdRealField> Rotation2<N> {
/// Spherical linear interpolation between two rotation matrices.
///
/// # Examples:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # 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_relative_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<N: SimdRealField> Rotation3<N> {
/// 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<Self>
where
N: RealField,
{
let q1 = Rotation3::from(*self);
let q2 = Rotation3::from(*other);
q1.try_slerp(&q2, t, epsilon).map(|q| q.into())
}
}

View File

@ -21,6 +21,7 @@ use crate::geometry::{Rotation2, Rotation3, UnitComplex, UnitQuaternion};
* 2D Rotation matrix.
*
*/
/// # Construction from a 2D rotation angle
impl<N: SimdRealField> Rotation2<N> {
/// Builds a 2 dimensional rotation matrix from an angle in radian.
///
@ -48,7 +49,10 @@ impl<N: SimdRealField> Rotation2<N> {
pub fn from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self {
Self::new(axisangle[0])
}
}
/// # Construction from an existing 2D matrix or rotations
impl<N: SimdRealField> Rotation2<N> {
/// Builds a rotation matrix by extracting the rotation part of the given transformation `m`.
///
/// This is an iterative method. See `.from_matrix_eps` to provide mover
@ -150,35 +154,6 @@ impl<N: SimdRealField> Rotation2<N> {
crate::convert(UnitComplex::scaled_rotation_between(a, b, s).to_rotation_matrix())
}
/// The rotation angle.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation2;
/// let rot = Rotation2::new(1.78);
/// assert_relative_eq!(rot.angle(), 1.78);
/// ```
#[inline]
pub fn angle(&self) -> N {
self.matrix()[(1, 0)].simd_atan2(self.matrix()[(0, 0)])
}
/// The rotation angle needed to make `self` and `other` coincide.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation2;
/// let rot1 = Rotation2::new(0.1);
/// let rot2 = Rotation2::new(1.7);
/// assert_relative_eq!(rot1.angle_to(&rot2), 1.6);
/// ```
#[inline]
pub fn angle_to(&self, other: &Self) -> N {
self.rotation_to(other).angle()
}
/// The rotation matrix needed to make `self` and `other` coincide.
///
/// The result is such that: `self.rotation_to(other) * self == other`.
@ -227,6 +202,38 @@ impl<N: SimdRealField> Rotation2<N> {
pub fn powf(&self, n: N) -> Self {
Self::new(self.angle() * n)
}
}
/// # 2D angle extraction
impl<N: SimdRealField> Rotation2<N> {
/// The rotation angle.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation2;
/// let rot = Rotation2::new(1.78);
/// assert_relative_eq!(rot.angle(), 1.78);
/// ```
#[inline]
pub fn angle(&self) -> N {
self.matrix()[(1, 0)].simd_atan2(self.matrix()[(0, 0)])
}
/// The rotation angle needed to make `self` and `other` coincide.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation2;
/// let rot1 = Rotation2::new(0.1);
/// let rot2 = Rotation2::new(1.7);
/// assert_relative_eq!(rot1.angle_to(&rot2), 1.6);
/// ```
#[inline]
pub fn angle_to(&self, other: &Self) -> N {
self.rotation_to(other).angle()
}
/// The rotation angle returned as a 1-dimensional vector.
///
@ -236,31 +243,6 @@ impl<N: SimdRealField> Rotation2<N> {
pub fn scaled_axis(&self) -> VectorN<N, U1> {
Vector1::new(self.angle())
}
/// Spherical linear interpolation between two rotation matrices.
///
/// # Examples:
///
/// ```
/// # #[macro_use] extern crate approx;
/// # 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_relative_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<N: SimdRealField> Distribution<Rotation2<N>> for Standard
@ -292,6 +274,7 @@ where
* 3D Rotation matrix.
*
*/
/// # Construction from a 3D axis and/or angles
impl<N: SimdRealField> Rotation3<N>
where
N::Element: SimdRealField,
@ -325,60 +308,6 @@ where
Self::from_axis_angle(&axis, angle)
}
/// Builds a rotation matrix by extracting the rotation part of the given transformation `m`.
///
/// This is an iterative method. See `.from_matrix_eps` to provide mover
/// convergence parameters and starting solution.
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
pub fn from_matrix(m: &Matrix3<N>) -> Self
where
N: RealField,
{
Self::from_matrix_eps(m, N::default_epsilon(), 0, Self::identity())
}
/// Builds a rotation matrix by extracting the rotation part of the given transformation `m`.
///
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
///
/// # Parameters
///
/// * `m`: the matrix from which the rotational part is to be extracted.
/// * `eps`: the angular errors tolerated between the current rotation and the optimal one.
/// * `max_iter`: the maximum number of iterations. Loops indefinitely until convergence if set to `0`.
/// * `guess`: a guess of the solution. Convergence will be significantly faster if an initial solution close
/// to the actual solution is provided. Can be set to `Rotation3::identity()` if no other
/// guesses come to mind.
pub fn from_matrix_eps(m: &Matrix3<N>, eps: N, mut max_iter: usize, guess: Self) -> Self
where
N: RealField,
{
if max_iter == 0 {
max_iter = usize::max_value();
}
let mut rot = guess.into_inner();
for _ in 0..max_iter {
let axis = rot.column(0).cross(&m.column(0))
+ rot.column(1).cross(&m.column(1))
+ rot.column(2).cross(&m.column(2));
let denom = rot.column(0).dot(&m.column(0))
+ rot.column(1).dot(&m.column(1))
+ rot.column(2).dot(&m.column(2));
let axisangle = axis / (denom.abs() + N::default_epsilon());
if let Some((axis, angle)) = Unit::try_new_and_get(axisangle, eps) {
rot = Rotation3::from_axis_angle(&axis, angle) * rot;
} else {
break;
}
}
Self::from_matrix_unchecked(rot)
}
/// Builds a 3D rotation matrix from an axis scaled by the rotation angle.
///
/// This is the same as `Self::new(axisangle)`.
@ -488,67 +417,13 @@ where
cp * cr,
))
}
}
/// Creates Euler angles from a rotation.
///
/// The angles are produced in the form (roll, pitch, yaw).
#[deprecated(note = "This is renamed to use `.euler_angles()`.")]
pub fn to_euler_angles(&self) -> (N, N, N)
where
N: RealField,
{
self.euler_angles()
}
/// Euler angles corresponding to this rotation from a rotation.
///
/// The angles are produced in the form (roll, pitch, yaw).
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation3;
/// let rot = Rotation3::from_euler_angles(0.1, 0.2, 0.3);
/// let euler = rot.euler_angles();
/// assert_relative_eq!(euler.0, 0.1, epsilon = 1.0e-6);
/// assert_relative_eq!(euler.1, 0.2, epsilon = 1.0e-6);
/// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6);
/// ```
pub fn euler_angles(&self) -> (N, N, N)
where
N: RealField,
{
// Implementation informed by "Computing Euler angles from a rotation matrix", by Gregory G. Slabaugh
// https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.371.6578
if self[(2, 0)].abs() < N::one() {
let yaw = -self[(2, 0)].asin();
let roll = (self[(2, 1)] / yaw.cos()).atan2(self[(2, 2)] / yaw.cos());
let pitch = (self[(1, 0)] / yaw.cos()).atan2(self[(0, 0)] / yaw.cos());
(roll, yaw, pitch)
} else if self[(2, 0)] <= -N::one() {
(self[(0, 1)].atan2(self[(0, 2)]), N::frac_pi_2(), N::zero())
} else {
(
-self[(0, 1)].atan2(-self[(0, 2)]),
-N::frac_pi_2(),
N::zero(),
)
}
}
/// Ensure this rotation is an orthonormal rotation matrix. This is useful when repeated
/// computations might cause the matrix from progressively not being orthonormal anymore.
#[inline]
pub fn renormalize(&mut self)
where
N: RealField,
{
let mut c = UnitQuaternion::from(*self);
let _ = c.renormalize();
*self = Self::from_matrix_eps(self.matrix(), N::default_epsilon(), 0, c.into())
}
/// # Construction from a 3D eye position and target point
impl<N: SimdRealField> Rotation3<N>
where
N::Element: SimdRealField,
{
/// Creates a rotation that corresponds to the local frame of an observer standing at the
/// origin and looking toward `dir`.
///
@ -656,7 +531,13 @@ where
{
Self::face_towards(dir, up).inverse()
}
}
/// # Construction from an existing 3D matrix or rotations
impl<N: SimdRealField> Rotation3<N>
where
N::Element: SimdRealField,
{
/// The rotation matrix required to align `a` and `b` but with its angle.
///
/// This is the rotation `R` such that `(R * a).angle(b) == 0 && (R * a).dot(b).is_positive()`.
@ -727,6 +608,123 @@ where
Some(Self::identity())
}
/// The rotation matrix needed to make `self` and `other` coincide.
///
/// The result is such that: `self.rotation_to(other) * self == other`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Rotation3, Vector3};
/// let rot1 = Rotation3::from_axis_angle(&Vector3::y_axis(), 1.0);
/// let rot2 = Rotation3::from_axis_angle(&Vector3::x_axis(), 0.1);
/// let rot_to = rot1.rotation_to(&rot2);
/// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6);
/// ```
#[inline]
pub fn rotation_to(&self, other: &Self) -> Self {
other * self.inverse()
}
/// Raise the quaternion to a given floating power, i.e., returns the rotation with the same
/// axis as `self` and an angle equal to `self.angle()` multiplied by `n`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Rotation3, Vector3, Unit};
/// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0));
/// let angle = 1.2;
/// let rot = Rotation3::from_axis_angle(&axis, angle);
/// let pow = rot.powf(2.0);
/// assert_relative_eq!(pow.axis().unwrap(), axis, epsilon = 1.0e-6);
/// assert_eq!(pow.angle(), 2.4);
/// ```
#[inline]
pub fn powf(&self, n: N) -> Self
where
N: RealField,
{
if let Some(axis) = self.axis() {
Self::from_axis_angle(&axis, self.angle() * n)
} else if self.matrix()[(0, 0)] < N::zero() {
let minus_id = MatrixN::<N, U3>::from_diagonal_element(-N::one());
Self::from_matrix_unchecked(minus_id)
} else {
Self::identity()
}
}
/// Builds a rotation matrix by extracting the rotation part of the given transformation `m`.
///
/// This is an iterative method. See `.from_matrix_eps` to provide mover
/// convergence parameters and starting solution.
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
pub fn from_matrix(m: &Matrix3<N>) -> Self
where
N: RealField,
{
Self::from_matrix_eps(m, N::default_epsilon(), 0, Self::identity())
}
/// Builds a rotation matrix by extracting the rotation part of the given transformation `m`.
///
/// This implements "A Robust Method to Extract the Rotational Part of Deformations" by Müller et al.
///
/// # Parameters
///
/// * `m`: the matrix from which the rotational part is to be extracted.
/// * `eps`: the angular errors tolerated between the current rotation and the optimal one.
/// * `max_iter`: the maximum number of iterations. Loops indefinitely until convergence if set to `0`.
/// * `guess`: a guess of the solution. Convergence will be significantly faster if an initial solution close
/// to the actual solution is provided. Can be set to `Rotation3::identity()` if no other
/// guesses come to mind.
pub fn from_matrix_eps(m: &Matrix3<N>, eps: N, mut max_iter: usize, guess: Self) -> Self
where
N: RealField,
{
if max_iter == 0 {
max_iter = usize::max_value();
}
let mut rot = guess.into_inner();
for _ in 0..max_iter {
let axis = rot.column(0).cross(&m.column(0))
+ rot.column(1).cross(&m.column(1))
+ rot.column(2).cross(&m.column(2));
let denom = rot.column(0).dot(&m.column(0))
+ rot.column(1).dot(&m.column(1))
+ rot.column(2).dot(&m.column(2));
let axisangle = axis / (denom.abs() + N::default_epsilon());
if let Some((axis, angle)) = Unit::try_new_and_get(axisangle, eps) {
rot = Rotation3::from_axis_angle(&axis, angle) * rot;
} else {
break;
}
}
Self::from_matrix_unchecked(rot)
}
/// Ensure this rotation is an orthonormal rotation matrix. This is useful when repeated
/// computations might cause the matrix from progressively not being orthonormal anymore.
#[inline]
pub fn renormalize(&mut self)
where
N: RealField,
{
let mut c = UnitQuaternion::from(*self);
let _ = c.renormalize();
*self = Self::from_matrix_eps(self.matrix(), N::default_epsilon(), 0, c.into())
}
}
/// # 3D axis and angle extraction
impl<N: SimdRealField> Rotation3<N> {
/// The rotation angle in [0; pi].
///
/// # Example
@ -837,103 +835,59 @@ where
/// assert_relative_eq!(rot1.angle_to(&rot2), 1.0045657, epsilon = 1.0e-6);
/// ```
#[inline]
pub fn angle_to(&self, other: &Self) -> N {
pub fn angle_to(&self, other: &Self) -> N
where
N::Element: SimdRealField,
{
self.rotation_to(other).angle()
}
/// The rotation matrix needed to make `self` and `other` coincide.
/// Creates Euler angles from a rotation.
///
/// The result is such that: `self.rotation_to(other) * self == other`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Rotation3, Vector3};
/// let rot1 = Rotation3::from_axis_angle(&Vector3::y_axis(), 1.0);
/// let rot2 = Rotation3::from_axis_angle(&Vector3::x_axis(), 0.1);
/// let rot_to = rot1.rotation_to(&rot2);
/// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6);
/// ```
#[inline]
pub fn rotation_to(&self, other: &Self) -> Self {
other * self.inverse()
}
/// Raise the quaternion to a given floating power, i.e., returns the rotation with the same
/// axis as `self` and an angle equal to `self.angle()` multiplied by `n`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Rotation3, Vector3, Unit};
/// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0));
/// let angle = 1.2;
/// let rot = Rotation3::from_axis_angle(&axis, angle);
/// let pow = rot.powf(2.0);
/// assert_relative_eq!(pow.axis().unwrap(), axis, epsilon = 1.0e-6);
/// assert_eq!(pow.angle(), 2.4);
/// ```
#[inline]
pub fn powf(&self, n: N) -> Self
/// The angles are produced in the form (roll, pitch, yaw).
#[deprecated(note = "This is renamed to use `.euler_angles()`.")]
pub fn to_euler_angles(&self) -> (N, N, N)
where
N: RealField,
{
if let Some(axis) = self.axis() {
Self::from_axis_angle(&axis, self.angle() * n)
} else if self.matrix()[(0, 0)] < N::zero() {
let minus_id = MatrixN::<N, U3>::from_diagonal_element(-N::one());
Self::from_matrix_unchecked(minus_id)
self.euler_angles()
}
/// Euler angles corresponding to this rotation from a rotation.
///
/// The angles are produced in the form (roll, pitch, yaw).
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::Rotation3;
/// let rot = Rotation3::from_euler_angles(0.1, 0.2, 0.3);
/// let euler = rot.euler_angles();
/// assert_relative_eq!(euler.0, 0.1, epsilon = 1.0e-6);
/// assert_relative_eq!(euler.1, 0.2, epsilon = 1.0e-6);
/// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6);
/// ```
pub fn euler_angles(&self) -> (N, N, N)
where
N: RealField,
{
// Implementation informed by "Computing Euler angles from a rotation matrix", by Gregory G. Slabaugh
// https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.371.6578
if self[(2, 0)].abs() < N::one() {
let yaw = -self[(2, 0)].asin();
let roll = (self[(2, 1)] / yaw.cos()).atan2(self[(2, 2)] / yaw.cos());
let pitch = (self[(1, 0)] / yaw.cos()).atan2(self[(0, 0)] / yaw.cos());
(roll, yaw, pitch)
} else if self[(2, 0)] <= -N::one() {
(self[(0, 1)].atan2(self[(0, 2)]), N::frac_pi_2(), N::zero())
} else {
Self::identity()
(
-self[(0, 1)].atan2(-self[(0, 2)]),
-N::frac_pi_2(),
N::zero(),
)
}
}
/// 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<Self>
where
N: RealField,
{
let q1 = Rotation3::from(*self);
let q2 = Rotation3::from(*other);
q1.try_slerp(&q2, t, epsilon).map(|q| q.into())
}
}
impl<N: SimdRealField> Distribution<Rotation3<N>> for Standard

View File

@ -6,60 +6,61 @@ use typenum::{self, Cmp, Greater};
macro_rules! impl_swizzle {
($( where $BaseDim: ident: $( $name: ident() -> $Result: ident[$($i: expr),+] ),+ ;)* ) => {
$(
impl<N: Scalar, D: DimName> Point<N, D>
where
DefaultAllocator: Allocator<N, D>,
D::Value: Cmp<typenum::$BaseDim, Output=Greater>
{
$(
/// Builds a new point from components of `self`.
#[inline]
pub fn $name(&self) -> $Result<N> {
$Result::new($(self[$i].inlined_clone()),*)
}
)*
}
$(
/// Builds a new point from components of `self`.
#[inline]
pub fn $name(&self) -> $Result<N>
where D::Value: Cmp<typenum::$BaseDim, Output=Greater> {
$Result::new($(self[$i].inlined_clone()),*)
}
)*
)*
}
}
impl_swizzle!(
where U0: xx() -> Point2[0, 0],
xxx() -> Point3[0, 0, 0];
/// # Swizzling
impl<N: Scalar, D: DimName> Point<N, D>
where
DefaultAllocator: Allocator<N, D>,
{
impl_swizzle!(
where U0: xx() -> Point2[0, 0],
xxx() -> Point3[0, 0, 0];
where U1: xy() -> Point2[0, 1],
yx() -> Point2[1, 0],
yy() -> Point2[1, 1],
xxy() -> Point3[0, 0, 1],
xyx() -> Point3[0, 1, 0],
xyy() -> Point3[0, 1, 1],
yxx() -> Point3[1, 0, 0],
yxy() -> Point3[1, 0, 1],
yyx() -> Point3[1, 1, 0],
yyy() -> Point3[1, 1, 1];
where U1: xy() -> Point2[0, 1],
yx() -> Point2[1, 0],
yy() -> Point2[1, 1],
xxy() -> Point3[0, 0, 1],
xyx() -> Point3[0, 1, 0],
xyy() -> Point3[0, 1, 1],
yxx() -> Point3[1, 0, 0],
yxy() -> Point3[1, 0, 1],
yyx() -> Point3[1, 1, 0],
yyy() -> Point3[1, 1, 1];
where U2: xz() -> Point2[0, 2],
yz() -> Point2[1, 2],
zx() -> Point2[2, 0],
zy() -> Point2[2, 1],
zz() -> Point2[2, 2],
xxz() -> Point3[0, 0, 2],
xyz() -> Point3[0, 1, 2],
xzx() -> Point3[0, 2, 0],
xzy() -> Point3[0, 2, 1],
xzz() -> Point3[0, 2, 2],
yxz() -> Point3[1, 0, 2],
yyz() -> Point3[1, 1, 2],
yzx() -> Point3[1, 2, 0],
yzy() -> Point3[1, 2, 1],
yzz() -> Point3[1, 2, 2],
zxx() -> Point3[2, 0, 0],
zxy() -> Point3[2, 0, 1],
zxz() -> Point3[2, 0, 2],
zyx() -> Point3[2, 1, 0],
zyy() -> Point3[2, 1, 1],
zyz() -> Point3[2, 1, 2],
zzx() -> Point3[2, 2, 0],
zzy() -> Point3[2, 2, 1],
zzz() -> Point3[2, 2, 2];
);
where U2: xz() -> Point2[0, 2],
yz() -> Point2[1, 2],
zx() -> Point2[2, 0],
zy() -> Point2[2, 1],
zz() -> Point2[2, 2],
xxz() -> Point3[0, 0, 2],
xyz() -> Point3[0, 1, 2],
xzx() -> Point3[0, 2, 0],
xzy() -> Point3[0, 2, 1],
xzz() -> Point3[0, 2, 2],
yxz() -> Point3[1, 0, 2],
yyz() -> Point3[1, 1, 2],
yzx() -> Point3[1, 2, 0],
yzy() -> Point3[1, 2, 1],
yzz() -> Point3[1, 2, 2],
zxx() -> Point3[2, 0, 0],
zxy() -> Point3[2, 0, 1],
zxz() -> Point3[2, 0, 2],
zyx() -> Point3[2, 1, 0],
zyy() -> Point3[2, 1, 1],
zyz() -> Point3[2, 1, 2],
zzx() -> Point3[2, 2, 0],
zzy() -> Point3[2, 2, 1],
zzz() -> Point3[2, 2, 2];
);
}

View File

@ -7,7 +7,26 @@ use crate::geometry::{Point2, Rotation2};
use simba::scalar::RealField;
use simba::simd::SimdRealField;
/// A complex number with a norm equal to 1.
/// A 2D rotation represented as a complex number with magnitude 1.
///
/// All the methods specific [`UnitComplex`](crate::UnitComplex) are listed here. You may also
/// read the documentation of the [`Complex`](crate::Complex) type which
/// is used internally and accessible with `unit_complex.complex()`.
///
/// # Construction
/// * [Identity <span style="float:right;">`identity`</span>](#identity)
/// * [From a 2D rotation angle <span style="float:right;">`new`, `from_cos_sin_unchecked`…</span>](#construction-from-a-2d-rotation-angle)
/// * [From an existing 2D matrix or complex number <span style="float:right;">`from_matrix`, `rotation_to`, `powf`…</span>](#construction-from-an-existing-2d-matrix-or-complex-number)
/// * [From two vectors <span style="float:right;">`rotation_between`, `scaled_rotation_between_axis`…</span>](#construction-from-two-vectors)
///
/// # Transformation and composition
/// * [Angle extraction <span style="float:right;">`angle`, `angle_to`…</span>](#angle-extraction)
/// * [Transformation of a vector or a point <span style="float:right;">`transform_vector`, `inverse_transform_point`…</span>](#transformation-of-a-vector-or-a-point)
/// * [Conjugation and inversion <span style="float:right;">`conjugate`, `inverse_mut`…</span>](#conjugation-and-inversion)
/// * [Interpolation <span style="float:right;">`slerp`…</span>](#interpolation)
///
/// # Conversion
/// * [Conversion to a matrix <span style="float:right;">`to_rotation_matrix`, `to_homogeneous`…</span>](#conversion-to-a-matrix)
pub type UnitComplex<N> = Unit<Complex<N>>;
impl<N: SimdRealField> Normed for Complex<N> {
@ -40,6 +59,7 @@ impl<N: SimdRealField> Normed for Complex<N> {
}
}
/// # Angle extraction
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
@ -115,24 +135,28 @@ where
}
}
/// The underlying complex number.
///
/// Same as `self.as_ref()`.
/// The rotation angle needed to make `self` and `other` coincide.
///
/// # Example
/// ```
/// # extern crate num_complex;
/// # use num_complex::Complex;
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let angle = 1.78f32;
/// let rot = UnitComplex::new(angle);
/// assert_eq!(*rot.complex(), Complex::new(angle.cos(), angle.sin()));
/// let rot1 = UnitComplex::new(0.1);
/// let rot2 = UnitComplex::new(1.7);
/// assert_relative_eq!(rot1.angle_to(&rot2), 1.6);
/// ```
#[inline]
pub fn complex(&self) -> &Complex<N> {
self.as_ref()
pub fn angle_to(&self, other: &Self) -> N {
let delta = self.rotation_to(other);
delta.angle()
}
}
/// # Conjugation and inversion
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// Compute the conjugate of this unit complex number.
///
/// # Example
@ -166,42 +190,6 @@ where
self.conjugate()
}
/// The rotation angle needed to make `self` and `other` coincide.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let rot1 = UnitComplex::new(0.1);
/// let rot2 = UnitComplex::new(1.7);
/// assert_relative_eq!(rot1.angle_to(&rot2), 1.6);
/// ```
#[inline]
pub fn angle_to(&self, other: &Self) -> N {
let delta = self.rotation_to(other);
delta.angle()
}
/// The unit complex number needed to make `self` and `other` coincide.
///
/// The result is such that: `self.rotation_to(other) * self == other`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let rot1 = UnitComplex::new(0.1);
/// let rot2 = UnitComplex::new(1.7);
/// let rot_to = rot1.rotation_to(&rot2);
///
/// assert_relative_eq!(rot_to * rot1, rot2);
/// assert_relative_eq!(rot_to.inverse() * rot2, rot1);
/// ```
#[inline]
pub fn rotation_to(&self, other: &Self) -> Self {
other / self
}
/// Compute in-place the conjugate of this unit complex number.
///
/// # Example
@ -237,25 +225,13 @@ where
pub fn inverse_mut(&mut self) {
self.conjugate_mut()
}
}
/// Raise this unit complex number to a given floating power.
///
/// This returns the unit complex number that identifies a rotation angle equal to
/// `self.angle() × n`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let rot = UnitComplex::new(0.78);
/// let pow = rot.powf(2.0);
/// assert_relative_eq!(pow.angle(), 2.0 * 0.78);
/// ```
#[inline]
pub fn powf(&self, n: N) -> Self {
Self::from_angle(self.angle() * n)
}
/// # Conversion to a matrix
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// Builds the rotation matrix corresponding to this unit complex number.
///
/// # Example
@ -290,7 +266,13 @@ where
pub fn to_homogeneous(&self) -> Matrix3<N> {
self.to_rotation_matrix().to_homogeneous()
}
}
/// # Transformation of a vector or a point
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// Rotate the given point by this unit complex number.
///
/// This is the same as the multiplication `self * pt`.
@ -376,7 +358,13 @@ where
pub fn inverse_transform_unit_vector(&self, v: &Unit<Vector2<N>>) -> Unit<Vector2<N>> {
self.inverse() * v
}
}
/// # Interpolation
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// Spherical linear interpolation between two rotations represented as unit complex numbers.
///
/// # Examples:
@ -392,7 +380,6 @@ where
///
/// assert_relative_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)

View File

@ -13,6 +13,7 @@ use crate::geometry::{Rotation2, UnitComplex};
use simba::scalar::RealField;
use simba::simd::SimdRealField;
/// # Identity
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
@ -32,7 +33,13 @@ where
pub fn identity() -> Self {
Self::new_unchecked(Complex::new(N::one(), N::zero()))
}
}
/// # Construction from a 2D rotation angle
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// Builds the unit complex number corresponding to the rotation with the given angle.
///
/// # Example
@ -100,6 +107,30 @@ where
pub fn from_scaled_axis<SB: Storage<N, U1>>(axisangle: Vector<N, U1, SB>) -> Self {
Self::from_angle(axisangle[0])
}
}
/// # Construction from an existing 2D matrix or complex number
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// The underlying complex number.
///
/// Same as `self.as_ref()`.
///
/// # Example
/// ```
/// # extern crate num_complex;
/// # use num_complex::Complex;
/// # use nalgebra::UnitComplex;
/// let angle = 1.78f32;
/// let rot = UnitComplex::new(angle);
/// assert_eq!(*rot.complex(), Complex::new(angle.cos(), angle.sin()));
/// ```
#[inline]
pub fn complex(&self) -> &Complex<N> {
self.as_ref()
}
/// Creates a new unit complex number from a complex number.
///
@ -165,6 +196,50 @@ where
Rotation2::from_matrix_eps(m, eps, max_iter, guess).into()
}
/// The unit complex number needed to make `self` and `other` coincide.
///
/// The result is such that: `self.rotation_to(other) * self == other`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let rot1 = UnitComplex::new(0.1);
/// let rot2 = UnitComplex::new(1.7);
/// let rot_to = rot1.rotation_to(&rot2);
///
/// assert_relative_eq!(rot_to * rot1, rot2);
/// assert_relative_eq!(rot_to.inverse() * rot2, rot1);
/// ```
#[inline]
pub fn rotation_to(&self, other: &Self) -> Self {
other / self
}
/// Raise this unit complex number to a given floating power.
///
/// This returns the unit complex number that identifies a rotation angle equal to
/// `self.angle() × n`.
///
/// # Example
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::UnitComplex;
/// let rot = UnitComplex::new(0.78);
/// let pow = rot.powf(2.0);
/// assert_relative_eq!(pow.angle(), 2.0 * 0.78);
/// ```
#[inline]
pub fn powf(&self, n: N) -> Self {
Self::from_angle(self.angle() * n)
}
}
/// # Construction from two vectors
impl<N: SimdRealField> UnitComplex<N>
where
N::Element: SimdRealField,
{
/// The unit complex needed to make `a` and `b` be collinear and point toward the same
/// direction.
///

View File

@ -1,6 +1,5 @@
#![cfg(feature = "arbitrary")]
macro_rules! gen_tests(
($module: ident, $scalar: ty) => {
mod $module {

View File

@ -1,6 +1,5 @@
#![cfg(feature = "arbitrary")]
macro_rules! gen_tests(
($module: ident, $scalar: ty) => {
mod $module {

View File

@ -1,6 +1,5 @@
#![cfg(feature = "arbitrary")]
macro_rules! gen_tests(
($module: ident, $scalar: ty) => {
mod $module {