diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs
index edb27b5a..b2228301 100755
--- a/src/geometry/isometry.rs
+++ b/src/geometry/isometry.rs
@@ -14,14 +14,50 @@ 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).
+///
+/// The [`Isometry2`](crate::Isometry2), [`Isometry3`](crate::Isometry3), [`IsometryMatrix2`](crate::IsometryMatrix2),
+/// and [`IsometryMatrix3`](crate::IsometryMatrix3) type aliases are provided for convenience. All
+/// their available methods are listed in this page and cant be grouped as follows.
+///
+/// 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 `new`, `translation`, `rotation`…](#construction-from-a-2d-vector-andor-a-rotation-angle)
+/// * [From a 3D vector and/or an axis-angle `new`, `translation`, `rotation`…](#construction-from-a-3d-vector-andor-an-axis-angle)
+/// * [From a 3D eye position and target point `look_at`, `look_at_lh`, `face_towards`…](#construction-from-a-3d-eye-position-and-target-point)
+/// * [From the translation and rotation parts `from_parts`…](#from-the-translation-and-rotation-parts)
+///
+/// # Transformation and composition
+/// Note that transforming vectors and points can be done bu 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 `transform_vector`, `inverse_transform_point`…](#transformation-of-a-vector-or-a-point)
+/// * [Inversion and in-place composition `inverse`, `append_rotation_wrt_point_mut`…](#inversion-and-in-place-composition)
+/// * [2D interpolation `lerp_slerp`…](#2d-interpolation)
+/// * [3D interpolation `lerp_slerp`…](#3d-interpolation)
+///
+/// # Conversion to a matrix
+/// * [Conversion to a matrix `to_matrix`…](#conversion-to-a-matrix)
+///
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
@@ -103,7 +139,7 @@ where
}
}
}
-
+/// # From the translation and rotation parts
impl> Isometry
where
DefaultAllocator: Allocator,
@@ -131,6 +167,7 @@ where
}
}
+/// # Inversion and in-place composition
impl> Isometry
where
N::Element: SimdRealField,
@@ -261,7 +298,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> Isometry
+where
+ N::Element: SimdRealField,
+ DefaultAllocator: Allocator,
+{
/// Transform the given point by this isometry.
///
/// This is the same as the multiplication `self * pt`.
@@ -377,224 +421,19 @@ where
}
}
-impl Isometry> {
- /// Interpolates between two isometries using a linear interpolation for the translation part,
- /// and a spherical interpolation for the rotation part.
- ///
- /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation
- /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic.
- ///
- /// # Examples:
- ///
- /// ```
- /// # use nalgebra::{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
- where
- N: RealField,
- {
- let tr = self.translation.vector.lerp(&other.translation.vector, t);
- let rot = self.rotation.try_slerp(&other.rotation, t, epsilon)?;
- Some(Self::from_parts(tr.into(), rot))
- }
-}
-
-impl Isometry> {
- /// Interpolates between two isometries using a linear interpolation for the translation part,
- /// and a spherical interpolation for the rotation part.
- ///
- /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation
- /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic.
- ///
- /// # Examples:
- ///
- /// ```
- /// # use nalgebra::{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
- where
- N: RealField,
- {
- let tr = self.translation.vector.lerp(&other.translation.vector, t);
- let rot = self.rotation.try_slerp(&other.rotation, t, epsilon)?;
- Some(Self::from_parts(tr.into(), rot))
- }
-}
-
-impl Isometry> {
- /// Interpolates between two isometries using a linear interpolation for the translation part,
- /// and a spherical interpolation for the rotation part.
- ///
- /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation
- /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic.
- ///
- /// # Examples:
- ///
- /// ```
- /// # #[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 Isometry> {
- /// Interpolates between two isometries using a linear interpolation for the translation part,
- /// and a spherical interpolation for the rotation part.
- ///
- /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation
- /// is not well-defined). Use `.try_lerp_slerp` instead to avoid the panic.
- ///
- /// # Examples:
- ///
- /// ```
- /// # #[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 Isometry
where
DefaultAllocator: Allocator,
{
/// Converts this isometry into its equivalent homogeneous transformation matrix.
///
+ /// This is the same as `self.to_matrix()`.
+ ///
/// # Example
///
/// ```
@@ -621,6 +460,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>
+ where
+ D: DimNameAdd,
+ R: SubsetOf>>,
+ DefaultAllocator: Allocator, DimNameSum>,
+ {
+ self.to_homogeneous()
+ }
}
impl Eq for Isometry
diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs
index a9f9c978..0f487547 100644
--- a/src/geometry/isometry_construction.rs
+++ b/src/geometry/isometry_construction.rs
@@ -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> Isometry
@@ -112,8 +113,8 @@ where
*
*/
-// 2D rotation.
-impl Isometry>
+/// # Construction from a 2D vector and/or a rotation angle
+impl IsometryMatrix2
where
N::Element: SimdRealField,
{
@@ -151,7 +152,7 @@ where
}
}
-impl Isometry>
+impl Isometry2
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 Isometry>
- 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, axisangle: Vector3) -> 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, axisangle: Vector3) -> 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) -> 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,
- target: &Point3,
- up: &Vector3)
- -> 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,
- target: &Point3,
- up: &Vector3)
- -> 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,
- target: &Point3,
- up: &Vector3)
- -> 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,
- target: &Point3,
- up: &Vector3)
- -> 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) -> Self {
+ Self::new(Vector3::zeros(), axisangle)
}
}
);
-isometry_construction_impl!(Rotation3, U3, U3);
-isometry_construction_impl!(UnitQuaternion, 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,
+ target: &Point3,
+ up: &Vector3)
+ -> 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,
+ target: &Point3,
+ up: &Vector3)
+ -> 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,
+ target: &Point3,
+ up: &Vector3)
+ -> 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,
+ target: &Point3,
+ up: &Vector3)
+ -> 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 Isometry3
+where
+ N::Element: SimdRealField,
+{
+ basic_isometry_construction_impl!(UnitQuaternion);
+}
+
+impl IsometryMatrix3
+where
+ N::Element: SimdRealField,
+{
+ basic_isometry_construction_impl!(Rotation3);
+}
+
+/// # Construction from a 3D eye position and target point
+impl Isometry3
+where
+ N::Element: SimdRealField,
+{
+ look_at_isometry_construction_impl!(UnitQuaternion);
+}
+
+impl IsometryMatrix3
+where
+ N::Element: SimdRealField,
+{
+ look_at_isometry_construction_impl!(Rotation3);
+}
diff --git a/src/geometry/isometry_interpolation.rs b/src/geometry/isometry_interpolation.rs
new file mode 100644
index 00000000..50e3f305
--- /dev/null
+++ b/src/geometry/isometry_interpolation.rs
@@ -0,0 +1,211 @@
+use crate::{Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, RealField, SimdRealField};
+
+/// # 3D interpolation
+impl Isometry3 {
+ /// 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
+ 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 IsometryMatrix3 {
+ /// 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
+ 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))
+ }
+}
+
+/// # 2D interpolation
+impl Isometry2 {
+ /// 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 IsometryMatrix2 {
+ /// 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)
+ }
+}
diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs
index 5701aa8f..25ef89f1 100644
--- a/src/geometry/mod.rs
+++ b/src/geometry/mod.rs
@@ -83,6 +83,7 @@ mod transform_simba;
mod reflection;
+mod isometry_interpolation;
mod orthographic;
mod perspective;
diff --git a/src/geometry/point.rs b/src/geometry/point.rs
index 0684b3b0..75410ccd 100644
--- a/src/geometry/point.rs
+++ b/src/geometry/point.rs
@@ -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 `new`…](#construction-from-individual-components)
+/// * [Swizzling `xx`, `yxz`…](#swizzling)
+/// * [Other construction methods `origin`, `from_slice`, `from_homogeneous`…](#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
diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs
index c54cb779..f567cfac 100644
--- a/src/geometry/point_construction.rs
+++ b/src/geometry/point_construction.rs
@@ -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 Point
where
DefaultAllocator: Allocator,
@@ -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 Point1 {
+ /// 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 Point
- where DefaultAllocator: Allocator {
+ ($($doc: expr; $Point: ident, $Vector: ident, $($args: ident:$irow: expr),*);* $(;)*) => {$(
+ impl $Point {
#[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 From<[N; $len]> for Point {
- fn from (coords: [N; $len]) -> Self {
+ ($($Point: ident, $len: expr);*) => {$(
+ impl From<[N; $len]> for $Point {
+ 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);
diff --git a/src/geometry/swizzle.rs b/src/geometry/swizzle.rs
index 9ec6b2e5..26971b74 100644
--- a/src/geometry/swizzle.rs
+++ b/src/geometry/swizzle.rs
@@ -6,60 +6,61 @@ use typenum::{self, Cmp, Greater};
macro_rules! impl_swizzle {
($( where $BaseDim: ident: $( $name: ident() -> $Result: ident[$($i: expr),+] ),+ ;)* ) => {
$(
- impl Point
- where
- DefaultAllocator: Allocator,
- D::Value: Cmp
- {
- $(
- /// Builds a new point from components of `self`.
- #[inline]
- pub fn $name(&self) -> $Result {
- $Result::new($(self[$i].inlined_clone()),*)
- }
- )*
- }
+ $(
+ /// Builds a new point from components of `self`.
+ #[inline]
+ pub fn $name(&self) -> $Result
+ where D::Value: Cmp {
+ $Result::new($(self[$i].inlined_clone()),*)
+ }
+ )*
)*
}
}
-impl_swizzle!(
- where U0: xx() -> Point2[0, 0],
- xxx() -> Point3[0, 0, 0];
+/// # Swizzling
+impl Point
+where
+ DefaultAllocator: Allocator,
+{
+ 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];
+ );
+}