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
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use building_blocks_core::{ConstZero, IntegerPoint, PointN};

use core::ops::{Add, AddAssign, Deref, Mul, Sub, SubAssign};
use num::Zero;

/// Map-local coordinates.
///
/// Most commonly, you will index a lattice map with a `PointN<N>`, which is assumed to be in global
/// coordinates. `Local<N>` only applies to lattice maps where a point must first be translated from
/// global coordinates into map-local coordinates before indexing with `Get<Local<N>>`.
#[derive(Debug, Eq, PartialEq)]
pub struct Local<N>(pub PointN<N>);

/// Map-local coordinates, wrapping a `Point2i`.
pub type Local2i = Local<[i32; 2]>;
/// Map-local coordinates, wrapping a `Point3i`.
pub type Local3i = Local<[i32; 3]>;

impl<N> Clone for Local<N>
where
    PointN<N>: Clone,
{
    fn clone(&self) -> Self {
        Local(self.0.clone())
    }
}
impl<N> Copy for Local<N> where PointN<N>: Copy {}

impl<N> Local<N> {
    /// Wraps all of the `points` using the `Local` constructor.
    #[inline]
    pub fn localize_points_slice(points: &[PointN<N>]) -> Vec<Local<N>>
    where
        PointN<N>: Clone,
    {
        points.iter().cloned().map(Local).collect()
    }

    /// Wraps all of the `points` using the `Local` constructor.
    #[inline]
    pub fn localize_points_array<const LEN: usize>(points: &[PointN<N>; LEN]) -> [Local<N>; LEN]
    where
        PointN<N>: ConstZero,
    {
        let mut locals = [Local(PointN::ZERO); LEN];
        for (l, p) in locals.iter_mut().zip(points.iter()) {
            *l = Local(*p);
        }

        locals
    }
}

impl<N> Deref for Local<N> {
    type Target = PointN<N>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// The most efficient coordinates for slice-backed lattice maps. A single number that translates directly to a slice offset.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct Stride(pub usize);

impl Zero for Stride {
    #[inline]
    fn zero() -> Self {
        Stride(0)
    }

    #[inline]
    fn is_zero(&self) -> bool {
        self.0 == 0
    }
}

impl Add for Stride {
    type Output = Self;

    #[inline]
    fn add(self, rhs: Self) -> Self::Output {
        // Wraps for negative point offsets.
        Self(self.0.wrapping_add(rhs.0))
    }
}

impl Sub for Stride {
    type Output = Self;

    #[inline]
    fn sub(self, rhs: Self) -> Self::Output {
        // Wraps for negative point offsets.
        Self(self.0.wrapping_sub(rhs.0))
    }
}

impl Mul<usize> for Stride {
    type Output = Self;

    #[inline]
    fn mul(self, rhs: usize) -> Self::Output {
        Self(self.0.wrapping_mul(rhs))
    }
}

impl AddAssign for Stride {
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl SubAssign for Stride {
    #[inline]
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

/// A newtype wrapper for `PointN` where each point represents exactly one chunk.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ChunkUnits<N>(pub PointN<N>);

pub type ChunkUnits2 = ChunkUnits<[i32; 2]>;
pub type ChunkUnits3 = ChunkUnits<[i32; 3]>;

impl<N> ChunkUnits<N>
where
    PointN<N>: IntegerPoint<N>,
{
    pub fn chunk_min(&self, chunk_shape: PointN<N>) -> PointN<N> {
        chunk_shape * self.0
    }
}