conspire/geometry/mesh/from/voxels/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 geometry::{
6 Coordinate, Coordinates,
7 grid::Voxels,
8 mesh::{Connectivities, Connectivity, Mesh},
9 },
10 math::{Set, Tensor, TensorVec},
11};
12use std::collections::BTreeMap;
13
14impl Mesh<3> {
15 pub fn from_voxels<T>(voxels: Voxels<T>, remove: Option<&[T]>) -> Self
16 where
17 T: Copy + PartialEq + Into<usize>,
18 {
19 Self::from_voxels_embedded(
20 voxels,
21 remove,
22 &Coordinate::from([1.0; 3]),
23 &Coordinate::from([0.0; 3]),
24 )
25 }
26 pub(super) fn from_voxels_embedded<T>(
27 voxels: Voxels<T>,
28 remove: Option<&[T]>,
29 scale: &Coordinate<3>,
30 translate: &Coordinate<3>,
31 ) -> Self
32 where
33 T: Copy + PartialEq + Into<usize>,
34 {
35 let [nx, ny, nz] = *voxels.nel();
36 let (nxp, nyp, nzp) = (nx + 1, ny + 1, nz + 1);
37 let layer = nxp * nyp;
38 let nodes_unfiltered = layer * nzp;
39 let mut connectivity = Vec::with_capacity(voxels.len());
40 let mut materials = Vec::with_capacity(voxels.len());
41 for ([i, j, k], &block) in voxels.logical_iter() {
42 if remove.is_none_or(|ids| !ids.contains(&block)) {
43 let base = i + nxp * j + layer * k;
44 let top = base + layer;
45 connectivity.push([
46 base,
47 base + 1,
48 base + nxp + 1,
49 base + nxp,
50 top,
51 top + 1,
52 top + nxp + 1,
53 top + nxp,
54 ]);
55 materials.push(block.into());
56 }
57 }
58 let mut used = vec![false; nodes_unfiltered];
59 connectivity
60 .iter()
61 .for_each(|nodes| nodes.iter().for_each(|&node| used[node] = true));
62 let mut mapping = vec![0usize; nodes_unfiltered];
63 let mut coordinates = Coordinates::new();
64 for (old, &is_used) in used.iter().enumerate() {
65 if is_used {
66 mapping[old] = coordinates.len();
67 let x = old % nxp;
68 let y = old / nxp % nyp;
69 let z = old / layer;
70 coordinates.push(Coordinate::const_from([
71 x as f64 * scale[0] + translate[0],
72 y as f64 * scale[1] + translate[1],
73 z as f64 * scale[2] + translate[2],
74 ]));
75 }
76 }
77 connectivity
78 .iter_mut()
79 .for_each(|nodes| nodes.iter_mut().for_each(|node| *node = mapping[*node]));
80 let mut blocks = BTreeMap::<usize, Vec<_>>::new();
81 connectivity
82 .into_iter()
83 .zip(materials)
84 .for_each(|(nodes, material)| blocks.entry(material).or_default().push(nodes));
85 let mut connectivities = Vec::with_capacity(blocks.len());
86 let mut numbers = Vec::with_capacity(blocks.len());
87 for (material, hexes) in blocks {
88 numbers.push(material);
89 connectivities.push(Connectivity::Hexahedral(hexes.into()));
90 }
91 (
92 Connectivities::from((connectivities, numbers)),
93 Set::from(coordinates),
94 )
95 .into()
96 }
97}