iron_shapes/
repetition.rs

1// Copyright (c) 2018-2020 Thomas Kramer.
2// SPDX-FileCopyrightText: 2018-2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Describe repetitions of geometrical objects.
7//!
8//! Regular repetitions (arrays) are based on two lattice vectors, irregular repetitions are based
9//! on a list of offsets.
10
11use crate::prelude::{CoordinateType, Vector};
12use num_traits::Zero;
13
14/// Describe a equi-spaced n*m two-dimensional repetition as a lattice.
15/// The offsets are computed as `(i*a, j*b)` for `i` in `0..n` and `j` in `0..m`.
16/// `a` and `b` the distance vectors between two neighbouring points.
17#[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    /// First lattice vector.
24    a: Vector<T>,
25    /// Second lattice vector.
26    b: Vector<T>,
27    /// First dimension.
28    n: u32,
29    /// Second dimension.
30    m: u32,
31}
32
33impl<T> RegularRepetition<T>
34where
35    T: CoordinateType,
36{
37    /// Create a new lattice based repetition.
38    ///
39    /// # Parameters
40    /// * `a, b`: Lattice vectors.
41    /// * `n, m`: Number of repetitions in directions `a` and `b`.
42    pub fn new(a: Vector<T>, b: Vector<T>, n: u32, m: u32) -> Self {
43        RegularRepetition { a, b, n, m }
44    }
45
46    /// Create a repetition along the x and y axis.
47    ///
48    /// # Example
49    ///
50    /// ```
51    /// use iron_shapes::prelude::RegularRepetition;
52    ///
53    /// let rep = RegularRepetition::new_rectilinear(1, 1, 1, 2);
54    /// assert_eq!(rep.len(), 2);
55    /// let offsets: Vec<_> = rep.iter().collect();
56    ///
57    /// assert_eq!(offsets, [(0, 0).into(), (0, 1).into()]);
58    /// ```
59    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    /// Iterate over each offsets of this repetition.
69    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    /// Return the number of offsets in this repetition.
84    pub fn len(&self) -> usize {
85        (self.n as usize) * (self.m as usize)
86    }
87
88    /// Check if number of repetitions is zero.
89    pub fn is_empty(&self) -> bool {
90        self.n == 0 || self.m == 0
91    }
92}
93
94/// Describe a non-equispaced repetition by storing a list of offsets.
95#[derive(PartialEq, Eq, Clone, Debug, Hash)]
96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97pub struct IrregularRepetition<T>
98where
99    T: CoordinateType,
100{
101    /// Offset vectors of the repetition.
102    offsets: Vec<Vector<T>>,
103}
104
105impl<T> IrregularRepetition<T>
106where
107    T: CoordinateType,
108{
109    /// Create a new irregular repetition from a list of offsets.
110    pub fn new(offsets: Vec<Vector<T>>) -> Self {
111        IrregularRepetition { offsets }
112    }
113
114    /// Iterate over each offsets of this repetition.
115    pub fn iter(&self) -> impl Iterator<Item = Vector<T>> + '_ {
116        self.offsets.iter().copied()
117    }
118
119    /// Return the number of offsets in this repetition.
120    pub fn len(&self) -> usize {
121        self.offsets.len()
122    }
123
124    /// Check if there's no repetition at all.
125    pub fn is_empty(&self) -> bool {
126        self.offsets.is_empty()
127    }
128}
129
130/// Describe the regular or irregular repetition of a geometrical object.
131#[derive(PartialEq, Eq, Clone, Debug, Hash)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub enum Repetition<T>
134where
135    T: CoordinateType,
136{
137    /// Lattice based repetition.
138    Regular(RegularRepetition<T>),
139    /// Repetition with random offsets.
140    Irregular(IrregularRepetition<T>),
141}
142
143impl<T> Repetition<T>
144where
145    T: CoordinateType,
146{
147    /// Return the number of offsets in this repetition.
148    pub fn len(&self) -> usize {
149        match self {
150            Repetition::Regular(r) => r.len(),
151            Repetition::Irregular(r) => r.len(),
152        }
153    }
154
155    /// Check if there is no repetition at all.
156    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    /// Iterate over each offsets of this repetition.
164    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}