1use crate::bound_type::{Left, Right};
2use crate::ndim::NDim;
3use crate::traits::BoundaryOf;
4use crate::{Bound, Exclusive, Inclusive, Interval};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct BoxN<const N: usize, T, L = Inclusive, R = L>(NDim<N, Interval<T, L, R>>);
9
10impl<const N: usize, T, L, R> std::ops::Deref for BoxN<N, T, L, R> {
11 type Target = NDim<N, Interval<T, L, R>>;
12 fn deref(&self) -> &Self::Target {
13 &self.0
14 }
15}
16impl<const N: usize, T, L, R> std::ops::DerefMut for BoxN<N, T, L, R> {
17 fn deref_mut(&mut self) -> &mut Self::Target {
18 &mut self.0
19 }
20}
21
22impl<const N: usize, T, L, R> From<[Interval<T, L, R>; N]> for BoxN<N, T, L, R> {
23 fn from(src: [Interval<T, L, R>; N]) -> Self {
24 Self(src.into())
25 }
26}
27
28impl<const N: usize, T, L, R> From<BoxN<N, T, L, R>> for [Interval<T, L, R>; N] {
29 fn from(src: BoxN<N, T, L, R>) -> Self {
30 src.0.into_array()
31 }
32}
33
34impl<const N: usize, T, L, R> AsRef<[Interval<T, L, R>; N]> for BoxN<N, T, L, R> {
35 fn as_ref(&self) -> &[Interval<T, L, R>; N] {
36 self.0.as_array()
37 }
38}
39
40impl<const N: usize, T, L, R> BoxN<N, T, L, R> {
41 pub fn from_array(src: [Interval<T, L, R>; N]) -> Self {
42 src.into()
43 }
44 pub fn into_array(self) -> [Interval<T, L, R>; N] {
45 self.into()
46 }
47}
48
49impl<T, L, R> BoxN<2, T, L, R> {
50 pub fn new(x: Interval<T, L, R>, y: Interval<T, L, R>) -> Self {
51 Self([x, y].into())
52 }
53}
54impl<T, L, R> BoxN<3, T, L, R> {
55 pub fn new(x: Interval<T, L, R>, y: Interval<T, L, R>, z: Interval<T, L, R>) -> Self {
56 Self([x, y, z].into())
57 }
58}
59impl<T, L, R> BoxN<4, T, L, R> {
60 pub fn new(
61 x: Interval<T, L, R>,
62 y: Interval<T, L, R>,
63 z: Interval<T, L, R>,
64 w: Interval<T, L, R>,
65 ) -> Self {
66 Self([x, y, z, w].into())
67 }
68}
69
70impl<const N: usize, T: PartialOrd + Clone, L: BoundaryOf<Left>, R: BoundaryOf<Right>>
71 BoxN<N, T, L, R>
72{
73 pub fn try_between(a: &[T; N], b: &[T; N]) -> Option<Self>
82 where
83 T: Into<Bound<T, L>> + Into<Bound<T, R>>,
84 {
85 let mut tmp: [_; N] =
86 std::array::from_fn(|i| Interval::try_between(a[i].clone(), b[i].clone()));
87 tmp.iter()
88 .all(|i| i.is_some())
89 .then(|| std::array::from_fn(|i| tmp[i].take().unwrap()).into())
90 }
91
92 pub fn between(a: &[T; N], b: &[T; N]) -> Self
98 where
99 T: Into<Bound<T, L>> + Into<Bound<T, R>>,
100 {
101 std::array::from_fn(|i| Interval::between(a[i].clone(), b[i].clone())).into()
102 }
103
104 pub fn inf(&self) -> NDim<N, T> {
105 std::array::from_fn(|i| self[i].inf().clone()).into()
106 }
107
108 pub fn sup(&self) -> NDim<N, T> {
109 std::array::from_fn(|i| self[i].sup().clone()).into()
110 }
111
112 pub fn contains(&self, t: &[T; N]) -> bool {
113 self.iter().zip(t.iter()).all(|(i, t)| i.contains(t))
114 }
115
116 pub fn includes(&self, other: &Self) -> bool {
117 self.iter().zip(other.iter()).all(|(i, o)| i.includes(o))
118 }
119
120 pub fn overlaps(&self, other: &Self) -> bool {
121 self.iter().zip(other.iter()).all(|(i, j)| i.overlaps(j))
122 }
123
124 pub fn closure(&self) -> BoxN<N, T, Inclusive> {
125 std::array::from_fn(|i| self[i].clone().closure()).into()
126 }
127
128 pub fn interior(&self) -> Option<BoxN<N, T, Exclusive>> {
129 let mut tmp: [_; N] = std::array::from_fn(|i| self[i].clone().interior());
130 tmp.iter()
131 .all(|i| i.is_some())
132 .then(|| std::array::from_fn(|i| tmp[i].take().unwrap()).into())
133 }
134
135 pub fn intersection(&self, other: &Self) -> Option<Self> {
136 let mut tmp: [_; N] = std::array::from_fn(|i| self[i].intersection(&other[i]));
137 tmp.iter()
138 .all(|i| i.is_some())
139 .then(|| std::array::from_fn(|i| tmp[i].take().unwrap()).into())
140 }
141
142 pub fn span(&self, other: &Self) -> Self {
143 std::array::from_fn(|i| self[i].clone().span(&other[i])).into()
144 }
145
146 pub fn dilate(&self, delta: T) -> Self
147 where
148 T: std::ops::Add<Output = T> + std::ops::Sub<Output = T>,
149 {
150 std::array::from_fn(|i| self[i].clone().dilate(delta.clone())).into()
151 }
152
153 pub fn hull(self, p: &[T; N]) -> Self {
160 std::array::from_fn(|i| self[i].clone().hull(p[i].clone())).into()
161 }
162
163 pub fn span_many<A: Into<Self>>(items: impl IntoIterator<Item = A>) -> Option<Self> {
164 let mut items = items.into_iter();
165 let first = items.next()?.into();
166 Some(items.fold(first, |acc, item| acc.span(&item.into())))
167 }
168
169 pub fn hull_many<'a>(items: impl IntoIterator<Item = &'a [T; N]>) -> Option<Self>
170 where
171 T: Clone + Into<Bound<T, L>> + Into<Bound<T, R>> + 'a,
172 {
173 let mut items = items.into_iter();
174 let mut lower = items.next()?.clone();
175 let mut upper = lower.clone();
176 for p in items {
177 for i in 0..N {
178 if p[i] < lower[i] {
179 lower[i] = p[i].clone();
180 } else if upper[i] < p[i] {
181 upper[i] = p[i].clone();
182 }
183 }
184 }
185 Self::try_between(&lower, &upper)
186 }
187}
188
189impl<const N: usize, T, L, R> BoxN<N, T, L, R>
190where
191 T: PartialOrd + Clone + num::Num,
192 L: BoundaryOf<Left>,
193 R: BoundaryOf<Right>,
194{
195 pub fn size(&self) -> NDim<N, T> {
196 std::array::from_fn(|i| self[i].measure()).into()
197 }
198 pub fn measure(&self) -> T {
199 self.iter()
200 .map(|item| item.measure())
201 .fold(T::one(), |a, b| a * b)
202 }
203}
204
205impl<const N: usize, T: num::Float, L: BoundaryOf<Left>, R: BoundaryOf<Right>> BoxN<N, T, L, R> {
206 pub fn center(&self) -> NDim<N, T> {
207 std::array::from_fn(|i| self[i].center()).into()
208 }
209}