1use std::{
2 array::from_fn,
3 fmt::{Display, Write},
4 ops::{Index, IndexMut},
5};
6
7use crate::array::ArrayWrap;
8
9use super::{Region, Side, Split, index::IndexWindow};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
15pub struct Face<const N: usize> {
16 pub axis: usize,
17 pub side: bool,
18}
19
20impl<const N: usize> Face<N> {
21 pub fn iterate() -> FaceIter<N> {
22 FaceIter {
23 axis: 0,
24 side: false,
25 }
26 }
27
28 pub fn negative(axis: usize) -> Self {
30 debug_assert!(axis < N);
31 Self { axis, side: false }
32 }
33
34 pub fn positive(axis: usize) -> Self {
36 debug_assert!(axis < N);
37 Self { axis, side: true }
38 }
39
40 pub fn reversed(self) -> Self {
42 Self {
43 axis: self.axis,
44 side: !self.side,
45 }
46 }
47
48 pub fn to_linear(self) -> usize {
50 2 * self.axis + self.side as usize
51 }
52
53 pub fn from_linear(linear: usize) -> Self {
55 assert!(linear < 2 * N);
56
57 Self {
58 axis: linear / 2,
59 side: linear % 2 == 1,
60 }
61 }
62
63 pub fn adjacent_split(self) -> Split<N> {
65 let mut result = Split::empty();
66 result.set_to(self.axis, self.side);
67 result
68 }
69
70 pub fn adjacent_splits(self) -> impl Iterator<Item = Split<N>> {
72 Split::<N>::enumerate().filter(move |split| split.is_set(self.axis) == self.side)
73 }
74}
75
76const AXIS_NAMES: [char; 4] = ['x', 'y', 'z', 'w'];
77
78impl<const N: usize> Display for Face<N> {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 if self.side {
81 f.write_char('+')?;
82 } else {
83 f.write_char('-')?;
84 }
85
86 if N < 4 {
87 f.write_char(AXIS_NAMES[self.axis])
88 } else {
89 f.write_str(&self.axis.to_string())
90 }
91 }
92}
93
94#[derive(Debug)]
96pub struct FaceIter<const N: usize> {
97 axis: usize,
98 side: bool,
99}
100
101impl<const N: usize> Iterator for FaceIter<N> {
102 type Item = Face<N>;
103
104 fn next(&mut self) -> Option<Self::Item> {
105 if self.axis >= N {
106 return None;
107 }
108
109 let result = Face {
110 axis: self.axis,
111 side: self.side,
112 };
113
114 self.axis += self.side as usize;
115 self.side = !self.side;
116
117 Some(result)
118 }
119
120 fn size_hint(&self) -> (usize, Option<usize>) {
121 (2 * N, Some(2 * N))
122 }
123}
124
125impl<const N: usize> ExactSizeIterator for FaceIter<N> {
126 fn len(&self) -> usize {
127 2 * N
128 }
129}
130
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub struct FaceArray<const N: usize, T>([[T; 2]; N]);
134
135impl<const N: usize, T> FaceArray<N, T> {
136 pub fn from_fn<F: FnMut(Face<N>) -> T>(mut f: F) -> Self {
138 Self(core::array::from_fn(|axis| {
139 [f(Face::negative(axis)), f(Face::positive(axis))]
140 }))
141 }
142
143 pub fn into_inner(self) -> [[T; 2]; N] {
146 self.0
147 }
148}
149
150impl<const N: usize, T: Clone> FaceArray<N, T> {
151 pub fn splat(value: T) -> Self {
153 Self::from_fn(|_| value.clone())
154 }
155
156 pub fn from_sides(negative: [T; N], positive: [T; N]) -> Self {
157 Self::from_fn(|face| match face.side {
158 true => positive[face.axis].clone(),
159 false => negative[face.axis].clone(),
160 })
161 }
162}
163
164impl<const N: usize, T> From<[[T; 2]; N]> for FaceArray<N, T> {
165 fn from(value: [[T; 2]; N]) -> Self {
166 Self(value)
167 }
168}
169
170impl<const N: usize, T> From<[(T, T); N]> for FaceArray<N, T> {
171 fn from(value: [(T, T); N]) -> Self {
172 Self(value.map(|(l, r)| [l, r]))
173 }
174}
175
176impl<const N: usize, T: serde::Serialize + Clone> serde::Serialize for FaceArray<N, T> {
177 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
178 where
179 S: serde::Serializer,
180 {
181 ArrayWrap(self.0.clone()).serialize(serializer)
182 }
183}
184
185impl<'de, const N: usize, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de>
186 for FaceArray<N, T>
187where
188 T: serde::de::Deserialize<'de>,
189{
190 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
191 where
192 D: serde::Deserializer<'de>,
193 {
194 Ok(FaceArray(ArrayWrap::deserialize(deserializer)?.0))
195 }
196}
197
198impl<const N: usize, T: Default> Default for FaceArray<N, T> {
199 fn default() -> Self {
200 Self::from_fn(|_| T::default())
201 }
202}
203
204impl<const N: usize, T> Index<Face<N>> for FaceArray<N, T> {
205 type Output = T;
206 fn index(&self, index: Face<N>) -> &Self::Output {
207 &self.0[index.axis][index.side as usize]
208 }
209}
210
211impl<const N: usize, T> IndexMut<Face<N>> for FaceArray<N, T> {
212 fn index_mut(&mut self, index: Face<N>) -> &mut Self::Output {
213 &mut self.0[index.axis][index.side as usize]
214 }
215}
216
217#[derive(Clone, Copy, Debug, PartialEq, Eq)]
219pub struct FaceMask<const N: usize>([[bool; 2]; N]);
220
221impl<const N: usize> FaceMask<N> {
222 pub fn from_fn<F: FnMut(Face<N>) -> bool>(mut f: F) -> Self {
223 Self(core::array::from_fn(|axis| {
224 [f(Face::negative(axis)), f(Face::positive(axis))]
225 }))
226 }
227
228 pub fn pack(bits: [[bool; 2]; N]) -> Self {
229 Self(bits)
230 }
231
232 pub fn empty() -> Self {
234 Self([[false; 2]; N])
235 }
236
237 pub fn full() -> Self {
239 Self([[true; 2]; N])
240 }
241
242 pub fn is_set(&self, face: Face<N>) -> bool {
243 self.0[face.axis][face.side as usize]
244 }
245
246 pub fn set(&mut self, face: Face<N>) {
247 self.0[face.axis][face.side as usize] = true;
248 }
249
250 pub fn clear(&mut self, face: Face<N>) {
251 self.0[face.axis][face.side as usize] = false;
252 }
253
254 pub fn set_to(&mut self, face: Face<N>, val: bool) {
255 self.0[face.axis][face.side as usize] = val;
256 }
257
258 pub fn adjacent_regions(&self) -> impl Iterator<Item = Region<N>> {
260 let mut window = IndexWindow::new([1; N], [1; N]);
261
262 for axis in 0..N {
263 if self.is_set(Face::negative(axis)) {
264 window.origin[axis] -= 1;
265 window.size[axis] += 1;
266 }
267
268 if self.is_set(Face::positive(axis)) {
269 window.size[axis] += 1;
270 }
271 }
272
273 window
274 .iter()
275 .map(|index| Region::new(from_fn(|axis| Side::from_value(index[axis] as u8))))
276 }
277}
278
279impl<const N: usize> Default for FaceMask<N> {
280 fn default() -> Self {
281 Self::from_fn(|_| false)
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 #[test]
290 fn face_iteration() {
291 let mut list = Face::<3>::iterate();
292 assert_eq!(list.next(), Some(Face::negative(0)));
293 assert_eq!(list.next(), Some(Face::positive(0)));
294 assert_eq!(list.next(), Some(Face::negative(1)));
295 assert_eq!(list.next(), Some(Face::positive(1)));
296 assert_eq!(list.next(), Some(Face::negative(2)));
297 assert_eq!(list.next(), Some(Face::positive(2)));
298 assert_eq!(list.next(), None);
299
300 assert_eq!(Face::<4>::negative(1).to_linear(), 2);
301 assert_eq!(Face::<4>::positive(3).to_linear(), 7);
302 assert_eq!(Face::<4>::positive(3), Face::<4>::from_linear(7));
303 }
304
305 #[test]
306 fn adjacent_regions() {
307 let mut mask = FaceMask::<2>::empty();
308 mask.set(Face::positive(0));
309 mask.set(Face::negative(1));
310
311 let mut regions = mask.adjacent_regions();
312
313 assert_eq!(
314 regions.next(),
315 Some(Region::new([Side::Middle, Side::Left]))
316 );
317 assert_eq!(regions.next(), Some(Region::new([Side::Right, Side::Left])));
318 assert_eq!(
319 regions.next(),
320 Some(Region::new([Side::Middle, Side::Middle]))
321 );
322 assert_eq!(
323 regions.next(),
324 Some(Region::new([Side::Right, Side::Middle]))
325 );
326 assert_eq!(regions.next(), None);
327 }
328}