Skip to main content

conspire/geometry/mesh/from/pixels/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::{
5    geometry::{
6        Coordinate, Coordinates,
7        grid::Pixels,
8        mesh::{Connectivities, Connectivity, Mesh},
9    },
10    math::{Set, Tensor, TensorVec},
11};
12use std::collections::BTreeMap;
13
14impl Mesh<2> {
15    pub fn from_pixels<T>(pixels: Pixels<T>, remove: Option<&[T]>) -> Self
16    where
17        T: Copy + PartialEq + Into<usize>,
18    {
19        let [nx, ny] = *pixels.nel();
20        let (nxp, nyp) = (nx + 1, ny + 1);
21        let nodes_unfiltered = nxp * nyp;
22        let mut connectivity = Vec::with_capacity(pixels.len());
23        let mut materials = Vec::with_capacity(pixels.len());
24        for ([i, j], &block) in pixels.logical_iter() {
25            if remove.is_none_or(|ids| !ids.contains(&block)) {
26                let base = i + nxp * j;
27                connectivity.push([base, base + 1, base + nxp + 1, base + nxp]);
28                materials.push(block.into());
29            }
30        }
31        let mut used = vec![false; nodes_unfiltered];
32        connectivity
33            .iter()
34            .for_each(|nodes| nodes.iter().for_each(|&node| used[node] = true));
35        let mut mapping = vec![0usize; nodes_unfiltered];
36        let mut coordinates = Coordinates::new();
37        for (old, &is_used) in used.iter().enumerate() {
38            if is_used {
39                mapping[old] = coordinates.len();
40                let x = old % nxp;
41                let y = old / nxp;
42                coordinates.push(Coordinate::const_from([x as f64, y as f64]));
43            }
44        }
45        connectivity
46            .iter_mut()
47            .for_each(|nodes| nodes.iter_mut().for_each(|node| *node = mapping[*node]));
48        let mut blocks = BTreeMap::<usize, Vec<_>>::new();
49        connectivity
50            .into_iter()
51            .zip(materials)
52            .for_each(|(nodes, material)| blocks.entry(material).or_default().push(nodes));
53        let mut connectivities = Vec::with_capacity(blocks.len());
54        let mut numbers = Vec::with_capacity(blocks.len());
55        for (material, quads) in blocks {
56            numbers.push(material);
57            connectivities.push(Connectivity::Quadrilateral(quads.into()));
58        }
59        (
60            Connectivities::from((connectivities, numbers)),
61            Set::from(coordinates),
62        )
63            .into()
64    }
65}