Skip to content

Commit d99c995

Browse files
authored
Add cast and to_* methods to Translation2D/Translation3D (#506)
Matches definitions that exist for `Vector2D`/`Vector3D`. These methods seem as applicable to "translations" as to "vectors". A space may have coordinates in different types, and conversion may be necessary.
1 parent d0a29cf commit d99c995

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

src/translation.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use core::fmt;
1616
use core::hash::Hash;
1717
use core::marker::PhantomData;
1818
use core::ops::{Add, AddAssign, Neg, Sub, SubAssign};
19+
use num_traits::NumCast;
1920
#[cfg(feature = "serde")]
2021
use serde::{Deserialize, Serialize};
2122
#[cfg(feature = "bytemuck")]
@@ -254,6 +255,84 @@ impl<T: Copy, Src, Dst> Translation2D<T, Src, Dst> {
254255
}
255256
}
256257

258+
impl<T: NumCast + Copy, Src, Dst> Translation2D<T, Src, Dst> {
259+
/// Cast from one numeric representation to another, preserving the units.
260+
///
261+
/// When casting from floating vector to integer coordinates, the decimals are truncated
262+
/// as one would expect from a simple cast, but this behavior does not always make sense
263+
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
264+
#[inline]
265+
pub fn cast<NewT: NumCast>(self) -> Translation2D<NewT, Src, Dst> {
266+
self.try_cast().unwrap()
267+
}
268+
269+
/// Fallible cast from one numeric representation to another, preserving the units.
270+
///
271+
/// When casting from floating vector to integer coordinates, the decimals are truncated
272+
/// as one would expect from a simple cast, but this behavior does not always make sense
273+
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
274+
pub fn try_cast<NewT: NumCast>(self) -> Option<Translation2D<NewT, Src, Dst>> {
275+
match (NumCast::from(self.x), NumCast::from(self.y)) {
276+
(Some(x), Some(y)) => Some(Translation2D::new(x, y)),
277+
_ => None,
278+
}
279+
}
280+
281+
// Convenience functions for common casts.
282+
283+
/// Cast into an `f32` vector.
284+
#[inline]
285+
pub fn to_f32(self) -> Translation2D<f32, Src, Dst> {
286+
self.cast()
287+
}
288+
289+
/// Cast into an `f64` vector.
290+
#[inline]
291+
pub fn to_f64(self) -> Translation2D<f64, Src, Dst> {
292+
self.cast()
293+
}
294+
295+
/// Cast into an `usize` vector, truncating decimals if any.
296+
///
297+
/// When casting from floating vector vectors, it is worth considering whether
298+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
299+
/// the desired conversion behavior.
300+
#[inline]
301+
pub fn to_usize(self) -> Translation2D<usize, Src, Dst> {
302+
self.cast()
303+
}
304+
305+
/// Cast into an `u32` vector, truncating decimals if any.
306+
///
307+
/// When casting from floating vector vectors, it is worth considering whether
308+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
309+
/// the desired conversion behavior.
310+
#[inline]
311+
pub fn to_u32(self) -> Translation2D<u32, Src, Dst> {
312+
self.cast()
313+
}
314+
315+
/// Cast into an i32 vector, truncating decimals if any.
316+
///
317+
/// When casting from floating vector vectors, it is worth considering whether
318+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
319+
/// the desired conversion behavior.
320+
#[inline]
321+
pub fn to_i32(self) -> Translation2D<i32, Src, Dst> {
322+
self.cast()
323+
}
324+
325+
/// Cast into an i64 vector, truncating decimals if any.
326+
///
327+
/// When casting from floating vector vectors, it is worth considering whether
328+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
329+
/// the desired conversion behavior.
330+
#[inline]
331+
pub fn to_i64(self) -> Translation2D<i64, Src, Dst> {
332+
self.cast()
333+
}
334+
}
335+
257336
#[cfg(feature = "bytemuck")]
258337
unsafe impl<T: Zeroable, Src, Dst> Zeroable for Translation2D<T, Src, Dst> {}
259338

@@ -580,6 +659,84 @@ impl<T: Copy, Src, Dst> Translation3D<T, Src, Dst> {
580659
}
581660
}
582661

662+
impl<T: NumCast + Copy, Src, Dst> Translation3D<T, Src, Dst> {
663+
/// Cast from one numeric representation to another, preserving the units.
664+
///
665+
/// When casting from floating vector to integer coordinates, the decimals are truncated
666+
/// as one would expect from a simple cast, but this behavior does not always make sense
667+
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
668+
#[inline]
669+
pub fn cast<NewT: NumCast>(self) -> Translation3D<NewT, Src, Dst> {
670+
self.try_cast().unwrap()
671+
}
672+
673+
/// Fallible cast from one numeric representation to another, preserving the units.
674+
///
675+
/// When casting from floating vector to integer coordinates, the decimals are truncated
676+
/// as one would expect from a simple cast, but this behavior does not always make sense
677+
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
678+
pub fn try_cast<NewT: NumCast>(self) -> Option<Translation3D<NewT, Src, Dst>> {
679+
match (NumCast::from(self.x), NumCast::from(self.y), NumCast::from(self.z)) {
680+
(Some(x), Some(y), Some(z)) => Some(Translation3D::new(x, y, z)),
681+
_ => None,
682+
}
683+
}
684+
685+
// Convenience functions for common casts.
686+
687+
/// Cast into an `f32` vector.
688+
#[inline]
689+
pub fn to_f32(self) -> Translation3D<f32, Src, Dst> {
690+
self.cast()
691+
}
692+
693+
/// Cast into an `f64` vector.
694+
#[inline]
695+
pub fn to_f64(self) -> Translation3D<f64, Src, Dst> {
696+
self.cast()
697+
}
698+
699+
/// Cast into an `usize` vector, truncating decimals if any.
700+
///
701+
/// When casting from floating vector vectors, it is worth considering whether
702+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
703+
/// the desired conversion behavior.
704+
#[inline]
705+
pub fn to_usize(self) -> Translation3D<usize, Src, Dst> {
706+
self.cast()
707+
}
708+
709+
/// Cast into an `u32` vector, truncating decimals if any.
710+
///
711+
/// When casting from floating vector vectors, it is worth considering whether
712+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
713+
/// the desired conversion behavior.
714+
#[inline]
715+
pub fn to_u32(self) -> Translation3D<u32, Src, Dst> {
716+
self.cast()
717+
}
718+
719+
/// Cast into an i32 vector, truncating decimals if any.
720+
///
721+
/// When casting from floating vector vectors, it is worth considering whether
722+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
723+
/// the desired conversion behavior.
724+
#[inline]
725+
pub fn to_i32(self) -> Translation3D<i32, Src, Dst> {
726+
self.cast()
727+
}
728+
729+
/// Cast into an i64 vector, truncating decimals if any.
730+
///
731+
/// When casting from floating vector vectors, it is worth considering whether
732+
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
733+
/// the desired conversion behavior.
734+
#[inline]
735+
pub fn to_i64(self) -> Translation3D<i64, Src, Dst> {
736+
self.cast()
737+
}
738+
}
739+
583740
#[cfg(feature = "bytemuck")]
584741
unsafe impl<T: Zeroable, Src, Dst> Zeroable for Translation3D<T, Src, Dst> {}
585742

0 commit comments

Comments
 (0)