iron_shapes/
repetition.rs1use crate::prelude::{CoordinateType, Vector};
12use num_traits::Zero;
13
14#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub struct RegularRepetition<T>
20where
21    T: CoordinateType,
22{
23    a: Vector<T>,
25    b: Vector<T>,
27    n: u32,
29    m: u32,
31}
32
33impl<T> RegularRepetition<T>
34where
35    T: CoordinateType,
36{
37    pub fn new(a: Vector<T>, b: Vector<T>, n: u32, m: u32) -> Self {
43        RegularRepetition { a, b, n, m }
44    }
45
46    pub fn new_rectilinear(spacing_x: T, spacing_y: T, num_x: u32, num_y: u32) -> Self {
60        Self::new(
61            Vector::new(spacing_x, T::zero()),
62            Vector::new(T::zero(), spacing_y),
63            num_x,
64            num_y,
65        )
66    }
67
68    pub fn iter(self) -> impl Iterator<Item = Vector<T>> {
70        let mut current = Vector::zero();
71        (0..self.m).flat_map(move |_| {
72            let mut row = current;
73            current = current + self.b;
74
75            (0..self.n).map(move |_| {
76                let pos = row;
77                row = row + self.a;
78                pos
79            })
80        })
81    }
82
83    pub fn len(&self) -> usize {
85        (self.n as usize) * (self.m as usize)
86    }
87
88    pub fn is_empty(&self) -> bool {
90        self.n == 0 || self.m == 0
91    }
92}
93
94#[derive(PartialEq, Eq, Clone, Debug, Hash)]
96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97pub struct IrregularRepetition<T>
98where
99    T: CoordinateType,
100{
101    offsets: Vec<Vector<T>>,
103}
104
105impl<T> IrregularRepetition<T>
106where
107    T: CoordinateType,
108{
109    pub fn new(offsets: Vec<Vector<T>>) -> Self {
111        IrregularRepetition { offsets }
112    }
113
114    pub fn iter(&self) -> impl Iterator<Item = Vector<T>> + '_ {
116        self.offsets.iter().copied()
117    }
118
119    pub fn len(&self) -> usize {
121        self.offsets.len()
122    }
123
124    pub fn is_empty(&self) -> bool {
126        self.offsets.is_empty()
127    }
128}
129
130#[derive(PartialEq, Eq, Clone, Debug, Hash)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub enum Repetition<T>
134where
135    T: CoordinateType,
136{
137    Regular(RegularRepetition<T>),
139    Irregular(IrregularRepetition<T>),
141}
142
143impl<T> Repetition<T>
144where
145    T: CoordinateType,
146{
147    pub fn len(&self) -> usize {
149        match self {
150            Repetition::Regular(r) => r.len(),
151            Repetition::Irregular(r) => r.len(),
152        }
153    }
154
155    pub fn is_empty(&self) -> bool {
157        match self {
158            Repetition::Regular(r) => r.is_empty(),
159            Repetition::Irregular(r) => r.is_empty(),
160        }
161    }
162
163    pub fn iter(&self) -> Box<dyn Iterator<Item = Vector<T>> + '_> {
165        match self {
166            Repetition::Regular(r) => Box::new(r.iter()),
167            Repetition::Irregular(r) => Box::new(r.iter()),
168        }
169    }
170}