Skip to main content

conspire/geometry/grid/from/tessellation/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::geometry::{Coordinate, grid::Voxels, mesh::Tessellation};
5use std::{
6    array::from_fn,
7    thread::{available_parallelism, scope},
8};
9
10impl Voxels<usize> {
11    pub fn from_tessellation(tessellation: &Tessellation, size: f64) -> Self {
12        let mesh = tessellation.mesh();
13        let bvh = tessellation.bvh();
14        let elements: Vec<&[usize]> = mesh.connectivities().iter().flatten().collect();
15        let coordinates = mesh.coordinates();
16        let mut min = [f64::INFINITY; 3];
17        let mut max = [f64::NEG_INFINITY; 3];
18        for point in coordinates {
19            (0..3).for_each(|ax| {
20                min[ax] = min[ax].min(point[ax]);
21                max[ax] = max[ax].max(point[ax]);
22            });
23        }
24        let nel: [usize; 3] = from_fn(|ax| (((max[ax] - min[ax]) / size).ceil() as usize).max(1));
25        let [nx, ny, _] = nel;
26        let layer = nx * ny;
27        let mut data = vec![0usize; layer * nel[2]];
28        let direction = Coordinate::from([1.0, 0.01, 0.001]);
29        let threads = available_parallelism().map_or(1, |threads| threads.get());
30        let chunk_size = data.len().div_ceil(threads).max(1);
31        scope(|scope| {
32            let (elements, direction) = (&elements, &direction);
33            data.chunks_mut(chunk_size)
34                .enumerate()
35                .for_each(|(chunk, voxels)| {
36                    let offset = chunk * chunk_size;
37                    scope.spawn(move || {
38                        voxels.iter_mut().enumerate().for_each(|(local, voxel)| {
39                            let flat = offset + local;
40                            let index = [flat % nx, flat / nx % ny, flat / layer];
41                            let center = Coordinate::from(from_fn::<_, 3, _>(|ax| {
42                                min[ax] + (index[ax] as f64 + 0.5) * size
43                            }));
44                            let ray = (center, direction.clone()).into();
45                            if bvh.intersections(&ray, coordinates, elements) % 2 == 1 {
46                                *voxel = 1;
47                            }
48                        });
49                    });
50                });
51        });
52        Voxels::new(data, nel)
53    }
54}