nalgebra/geometry/
translation.rs

1use approx::{AbsDiffEq, RelativeEq, UlpsEq};
2use num::{One, Zero};
3use std::fmt;
4use std::hash;
5#[cfg(feature = "abomonation-serialize")]
6use std::io::{Result as IOResult, Write};
7
8#[cfg(feature = "serde-serialize-no-std")]
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10
11#[cfg(feature = "abomonation-serialize")]
12use abomonation::Abomonation;
13
14use simba::scalar::{ClosedAdd, ClosedNeg, ClosedSub};
15
16use crate::base::allocator::Allocator;
17use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
18use crate::base::storage::Owned;
19use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar};
20
21use crate::geometry::Point;
22
23/// A translation.
24#[repr(C)]
25#[cfg_attr(
26    all(not(target_os = "cuda"), feature = "cuda"),
27    derive(cust::DeviceCopy)
28)]
29#[derive(Copy, Clone)]
30pub struct Translation<T, const D: usize> {
31    /// The translation coordinates, i.e., how much is added to a point's coordinates when it is
32    /// translated.
33    pub vector: SVector<T, D>,
34}
35
36impl<T: fmt::Debug, const D: usize> fmt::Debug for Translation<T, D> {
37    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
38        self.vector.as_slice().fmt(formatter)
39    }
40}
41
42impl<T: Scalar + hash::Hash, const D: usize> hash::Hash for Translation<T, D>
43where
44    Owned<T, Const<D>>: hash::Hash,
45{
46    fn hash<H: hash::Hasher>(&self, state: &mut H) {
47        self.vector.hash(state)
48    }
49}
50
51#[cfg(feature = "bytemuck")]
52unsafe impl<T, const D: usize> bytemuck::Zeroable for Translation<T, D>
53where
54    T: Scalar + bytemuck::Zeroable,
55    SVector<T, D>: bytemuck::Zeroable,
56{
57}
58
59#[cfg(feature = "bytemuck")]
60unsafe impl<T, const D: usize> bytemuck::Pod for Translation<T, D>
61where
62    T: Scalar + bytemuck::Pod,
63    SVector<T, D>: bytemuck::Pod,
64{
65}
66
67#[cfg(feature = "abomonation-serialize")]
68impl<T, const D: usize> Abomonation for Translation<T, D>
69where
70    T: Scalar,
71    SVector<T, D>: Abomonation,
72{
73    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
74        self.vector.entomb(writer)
75    }
76
77    fn extent(&self) -> usize {
78        self.vector.extent()
79    }
80
81    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
82        self.vector.exhume(bytes)
83    }
84}
85
86#[cfg(feature = "serde-serialize-no-std")]
87impl<T: Scalar, const D: usize> Serialize for Translation<T, D>
88where
89    Owned<T, Const<D>>: Serialize,
90{
91    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
92    where
93        S: Serializer,
94    {
95        self.vector.serialize(serializer)
96    }
97}
98
99#[cfg(feature = "serde-serialize-no-std")]
100impl<'a, T: Scalar, const D: usize> Deserialize<'a> for Translation<T, D>
101where
102    Owned<T, Const<D>>: Deserialize<'a>,
103{
104    fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
105    where
106        Des: Deserializer<'a>,
107    {
108        let matrix = SVector::<T, D>::deserialize(deserializer)?;
109
110        Ok(Translation::from(matrix))
111    }
112}
113
114#[cfg(feature = "rkyv-serialize-no-std")]
115mod rkyv_impl {
116    use super::Translation;
117    use crate::base::SVector;
118    use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
119
120    impl<T: Archive, const D: usize> Archive for Translation<T, D> {
121        type Archived = Translation<T::Archived, D>;
122        type Resolver = <SVector<T, D> as Archive>::Resolver;
123
124        fn resolve(
125            &self,
126            pos: usize,
127            resolver: Self::Resolver,
128            out: &mut core::mem::MaybeUninit<Self::Archived>,
129        ) {
130            self.vector.resolve(
131                pos + offset_of!(Self::Archived, vector),
132                resolver,
133                project_struct!(out: Self::Archived => vector),
134            );
135        }
136    }
137
138    impl<T: Serialize<S>, S: Fallible + ?Sized, const D: usize> Serialize<S> for Translation<T, D> {
139        fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
140            self.vector.serialize(serializer)
141        }
142    }
143
144    impl<T: Archive, _D: Fallible + ?Sized, const D: usize> Deserialize<Translation<T, D>, _D>
145        for Translation<T::Archived, D>
146    where
147        T::Archived: Deserialize<T, _D>,
148    {
149        fn deserialize(&self, deserializer: &mut _D) -> Result<Translation<T, D>, _D::Error> {
150            Ok(Translation {
151                vector: self.vector.deserialize(deserializer)?,
152            })
153        }
154    }
155}
156
157impl<T: Scalar, const D: usize> Translation<T, D> {
158    /// Creates a new translation from the given vector.
159    #[inline]
160    #[deprecated(note = "Use `::from` instead.")]
161    pub fn from_vector(vector: SVector<T, D>) -> Translation<T, D> {
162        Translation { vector }
163    }
164
165    /// Inverts `self`.
166    ///
167    /// # Example
168    /// ```
169    /// # use nalgebra::{Translation2, Translation3};
170    /// let t = Translation3::new(1.0, 2.0, 3.0);
171    /// assert_eq!(t * t.inverse(), Translation3::identity());
172    /// assert_eq!(t.inverse() * t, Translation3::identity());
173    ///
174    /// // Work in all dimensions.
175    /// let t = Translation2::new(1.0, 2.0);
176    /// assert_eq!(t * t.inverse(), Translation2::identity());
177    /// assert_eq!(t.inverse() * t, Translation2::identity());
178    /// ```
179    #[inline]
180    #[must_use = "Did you mean to use inverse_mut()?"]
181    pub fn inverse(&self) -> Translation<T, D>
182    where
183        T: ClosedNeg,
184    {
185        Translation::from(-&self.vector)
186    }
187
188    /// Converts this translation into its equivalent homogeneous transformation matrix.
189    ///
190    /// # Example
191    /// ```
192    /// # use nalgebra::{Translation2, Translation3, Matrix3, Matrix4};
193    /// let t = Translation3::new(10.0, 20.0, 30.0);
194    /// let expected = Matrix4::new(1.0, 0.0, 0.0, 10.0,
195    ///                             0.0, 1.0, 0.0, 20.0,
196    ///                             0.0, 0.0, 1.0, 30.0,
197    ///                             0.0, 0.0, 0.0, 1.0);
198    /// assert_eq!(t.to_homogeneous(), expected);
199    ///
200    /// let t = Translation2::new(10.0, 20.0);
201    /// let expected = Matrix3::new(1.0, 0.0, 10.0,
202    ///                             0.0, 1.0, 20.0,
203    ///                             0.0, 0.0, 1.0);
204    /// assert_eq!(t.to_homogeneous(), expected);
205    /// ```
206    #[inline]
207    #[must_use]
208    pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
209    where
210        T: Zero + One,
211        Const<D>: DimNameAdd<U1>,
212        DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
213    {
214        let mut res = OMatrix::<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>::identity();
215        res.fixed_slice_mut::<D, 1>(0, D).copy_from(&self.vector);
216
217        res
218    }
219
220    /// Inverts `self` in-place.
221    ///
222    /// # Example
223    /// ```
224    /// # use nalgebra::{Translation2, Translation3};
225    /// let t = Translation3::new(1.0, 2.0, 3.0);
226    /// let mut inv_t = Translation3::new(1.0, 2.0, 3.0);
227    /// inv_t.inverse_mut();
228    /// assert_eq!(t * inv_t, Translation3::identity());
229    /// assert_eq!(inv_t * t, Translation3::identity());
230    ///
231    /// // Work in all dimensions.
232    /// let t = Translation2::new(1.0, 2.0);
233    /// let mut inv_t = Translation2::new(1.0, 2.0);
234    /// inv_t.inverse_mut();
235    /// assert_eq!(t * inv_t, Translation2::identity());
236    /// assert_eq!(inv_t * t, Translation2::identity());
237    /// ```
238    #[inline]
239    pub fn inverse_mut(&mut self)
240    where
241        T: ClosedNeg,
242    {
243        self.vector.neg_mut()
244    }
245}
246
247impl<T: Scalar + ClosedAdd, const D: usize> Translation<T, D> {
248    /// Translate the given point.
249    ///
250    /// This is the same as the multiplication `self * pt`.
251    ///
252    /// # Example
253    /// ```
254    /// # use nalgebra::{Translation3, Point3};
255    /// let t = Translation3::new(1.0, 2.0, 3.0);
256    /// let transformed_point = t.transform_point(&Point3::new(4.0, 5.0, 6.0));
257    /// assert_eq!(transformed_point, Point3::new(5.0, 7.0, 9.0));
258    #[inline]
259    #[must_use]
260    pub fn transform_point(&self, pt: &Point<T, D>) -> Point<T, D> {
261        pt + &self.vector
262    }
263}
264
265impl<T: Scalar + ClosedSub, const D: usize> Translation<T, D> {
266    /// Translate the given point by the inverse of this translation.
267    ///
268    /// # Example
269    /// ```
270    /// # use nalgebra::{Translation3, Point3};
271    /// let t = Translation3::new(1.0, 2.0, 3.0);
272    /// let transformed_point = t.inverse_transform_point(&Point3::new(4.0, 5.0, 6.0));
273    /// assert_eq!(transformed_point, Point3::new(3.0, 3.0, 3.0));
274    #[inline]
275    #[must_use]
276    pub fn inverse_transform_point(&self, pt: &Point<T, D>) -> Point<T, D> {
277        pt - &self.vector
278    }
279}
280
281impl<T: Scalar + Eq, const D: usize> Eq for Translation<T, D> {}
282
283impl<T: Scalar + PartialEq, const D: usize> PartialEq for Translation<T, D> {
284    #[inline]
285    fn eq(&self, right: &Translation<T, D>) -> bool {
286        self.vector == right.vector
287    }
288}
289
290impl<T: Scalar + AbsDiffEq, const D: usize> AbsDiffEq for Translation<T, D>
291where
292    T::Epsilon: Clone,
293{
294    type Epsilon = T::Epsilon;
295
296    #[inline]
297    fn default_epsilon() -> Self::Epsilon {
298        T::default_epsilon()
299    }
300
301    #[inline]
302    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
303        self.vector.abs_diff_eq(&other.vector, epsilon)
304    }
305}
306
307impl<T: Scalar + RelativeEq, const D: usize> RelativeEq for Translation<T, D>
308where
309    T::Epsilon: Clone,
310{
311    #[inline]
312    fn default_max_relative() -> Self::Epsilon {
313        T::default_max_relative()
314    }
315
316    #[inline]
317    fn relative_eq(
318        &self,
319        other: &Self,
320        epsilon: Self::Epsilon,
321        max_relative: Self::Epsilon,
322    ) -> bool {
323        self.vector
324            .relative_eq(&other.vector, epsilon, max_relative)
325    }
326}
327
328impl<T: Scalar + UlpsEq, const D: usize> UlpsEq for Translation<T, D>
329where
330    T::Epsilon: Clone,
331{
332    #[inline]
333    fn default_max_ulps() -> u32 {
334        T::default_max_ulps()
335    }
336
337    #[inline]
338    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
339        self.vector.ulps_eq(&other.vector, epsilon, max_ulps)
340    }
341}
342
343/*
344 *
345 * Display
346 *
347 */
348impl<T: Scalar + fmt::Display, const D: usize> fmt::Display for Translation<T, D> {
349    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350        let precision = f.precision().unwrap_or(3);
351
352        writeln!(f, "Translation {{")?;
353        write!(f, "{:.*}", precision, self.vector)?;
354        writeln!(f, "}}")
355    }
356}