1use std::array::{self, from_fn};
2
3use datasize::DataSize;
4
5use crate::geometry::Split;
6
7#[derive(Debug, Copy, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
9pub struct HyperBox<const N: usize> {
10 #[serde(with = "crate::array")]
12 pub size: [f64; N],
13 #[serde(with = "crate::array")]
15 pub origin: [f64; N],
16}
17
18impl<const N: usize> DataSize for HyperBox<N> {
19 const IS_DYNAMIC: bool = false;
20 const STATIC_HEAP_SIZE: usize = 0;
21
22 fn estimate_heap_size(&self) -> usize {
23 0
24 }
25}
26
27impl<const N: usize> HyperBox<N> {
28 pub const UNIT: Self = HyperBox {
30 size: [1.0; N],
31 origin: [0.0; N],
32 };
33
34 pub fn from_aabb(aa: [f64; N], bb: [f64; N]) -> Self {
36 let size = array::from_fn(|axis| (bb[axis] - aa[axis]).max(0.0));
37 Self { size, origin: aa }
38 }
39
40 pub fn center(&self) -> [f64; N] {
42 array::from_fn(|i| self.origin[i] + self.size[i] / 2.0)
43 }
44
45 pub fn contains(&self, point: [f64; N]) -> bool {
47 for axis in 0..N {
48 if point[axis] < self.origin[axis] || point[axis] > self.origin[axis] + self.size[axis]
49 {
50 return false;
51 }
52 }
53
54 true
55 }
56
57 pub fn subdivide(&self, split: Split<N>) -> Self {
59 let size = array::from_fn(|i| self.size[i] / 2.0);
60 let origin = array::from_fn(|i| {
61 if split.is_set(i) {
62 self.origin[i] + self.size[i] / 2.0
63 } else {
64 self.origin[i]
65 }
66 });
67
68 Self { size, origin }
69 }
70
71 pub fn aa(&self) -> [f64; N] {
72 self.origin
73 }
74
75 pub fn bb(&self) -> [f64; N] {
76 from_fn(|i| self.origin[i] + self.size[i])
77 }
78
79 pub fn local_to_global(&self, local: [f64; N]) -> [f64; N] {
80 array::from_fn(|axis| local[axis] * self.size[axis] + self.origin[axis])
81 }
82
83 pub fn global_to_local(&self, global: [f64; N]) -> [f64; N] {
84 array::from_fn(|axis| (global[axis] - self.origin[axis]) / self.size[axis])
85 }
86}