1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{
access,
geom::Cube,
math::{Pos3, Vec3},
ord::{X, Y, Z},
};
pub struct Grid {
boundary: Cube,
res: [usize; 3],
voxel_size: Vec3,
}
impl Grid {
access!(boundary, Cube);
access!(res, [usize; 3]);
access!(voxel_size, Vec3);
#[inline]
#[must_use]
pub fn new(boundary: Cube, res: [usize; 3]) -> Self {
debug_assert!(res[X] > 0);
debug_assert!(res[Y] > 0);
debug_assert!(res[Z] > 0);
let mut voxel_size = boundary.widths();
for (w, n) in voxel_size.iter_mut().zip(&res) {
*w /= *n as f64;
}
Self {
boundary,
res,
voxel_size,
}
}
#[inline]
#[must_use]
pub fn voxel_vol(&self) -> f64 {
self.voxel_size.x * self.voxel_size.y * self.voxel_size.z
}
#[inline]
#[must_use]
pub const fn total_cells(&self) -> usize {
self.res[X] * self.res[Y] * self.res[Z]
}
#[inline]
#[must_use]
pub fn gen_index(&self, p: &Pos3) -> Option<[usize; 3]> {
if self.boundary.contains(p) {
let mins = self.boundary.mins();
let maxs = self.boundary.maxs();
Some([
(((p.x - mins.x) / (maxs.x - mins.x)) * self.res[X] as f64).floor() as usize,
(((p.y - mins.y) / (maxs.y - mins.y)) * self.res[Y] as f64).floor() as usize,
(((p.z - mins.z) / (maxs.z - mins.z)) * self.res[Z] as f64).floor() as usize,
])
} else {
None
}
}
#[inline]
#[must_use]
pub fn gen_index_voxel(&self, p: &Pos3) -> Option<([usize; 3], Cube)> {
if let Some(index) = self.gen_index(p) {
let mut min = *self.boundary.mins();
min.x += self.voxel_size[X] * index[X] as f64;
min.y += self.voxel_size[Y] * index[Y] as f64;
min.z += self.voxel_size[Z] * index[Z] as f64;
let boundary = Cube::new(min, min + self.voxel_size);
debug_assert!(boundary.contains(p));
Some((index, boundary))
} else {
None
}
}
#[inline]
#[must_use]
pub fn gen_voxel(&self, index: &[usize; 3]) -> Cube {
debug_assert!(index[X] < self.res[X]);
debug_assert!(index[Y] < self.res[Y]);
debug_assert!(index[Z] < self.res[Z]);
let x = self
.voxel_size
.x
.mul_add(index[X] as f64, self.boundary.mins().x);
let y = self
.voxel_size
.y
.mul_add(index[Y] as f64, self.boundary.mins().y);
let z = self
.voxel_size
.z
.mul_add(index[Z] as f64, self.boundary.mins().z);
let mins = Pos3::new(x, y, z);
Cube::new(mins, mins + self.voxel_size)
}
}