1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
//! Numeric types used for coordinates and related quantities.
use euclid::{Point3D, Size2D, Size3D, Vector3D};
use crate::math::Cube;
/// Coordinates that are locked to the cube grid.
pub type GridCoordinate = i32;
/// Numeric type in a [`GridSize`].
///
/// TODO: This needs a cleaner name.
pub type GridSizeCoord = u32;
/// Positions that are locked to the cube grid.
pub type GridPoint = Point3D<GridCoordinate, Cube>;
/// Vectors that are locked to the cube grid.
pub type GridVector = Vector3D<GridCoordinate, Cube>;
/// Sizes of grid-aligned objects.
pub type GridSize = Size3D<GridSizeCoord, Cube>;
/// Coordinates that are not locked to the cube grid.
///
/// Note: Because `GridCoordinate = i32` and `FreeCoordinate = f64`, which has
/// more than 32 bits of mantissa, the infallible conversion
/// `From<GridCoordinate> for FreeCoordinate` exists, which is often convenient.
pub type FreeCoordinate = f64;
/// Positions that are not locked to the cube grid but may interact with it.
pub type FreePoint = Point3D<FreeCoordinate, Cube>;
/// Vectors that are not locked to the cube grid but may interact with it.
pub type FreeVector = Vector3D<FreeCoordinate, Cube>;
/// Additional element-wise operations on `euclid` types.
// TODO: Contribute these to `euclid` itself
pub trait VectorOps<O> {
/// Input vector element type.
type Elem;
/// Output vector type.
type Output;
/// Apply the function to each element.
fn map<F: FnMut(Self::Elem) -> O>(self, f: F) -> Self::Output;
/// Apply the function to each element of the two inputs, pairwise.
fn zip<F: FnMut(Self::Elem, Self::Elem) -> O>(self, rhs: Self, f: F) -> Self::Output;
}
macro_rules! impl_vector_ops {
($vec:ident, ($( $field:ident )*)) => {
impl<T, O, U> VectorOps<O> for $vec<T, U> {
type Elem = T;
type Output = $vec<O, U>;
#[inline]
fn map<F: FnMut(Self::Elem) -> O>(self, mut f: F) -> Self::Output {
$vec::new($(f(self.$field),)*)
}
#[inline]
fn zip<F: FnMut(Self::Elem, Self::Elem) -> O>(
self,
rhs: Self,
mut f: F,
) -> Self::Output {
$vec::new($(f(self.$field, rhs.$field),)*)
}
}
};
}
mod impl_euclid {
use super::*;
impl_vector_ops!(Size2D, (width height));
impl_vector_ops!(Size3D, (width height depth));
}