Skip to main content

conspire/geometry/mesh/from/
mod.rs

1#[cfg(test)]
2mod test;
3
4mod lattice;
5mod ntree;
6mod pixels;
7mod segmentation;
8mod voxels;
9
10pub(crate) use ntree::Dualization;
11
12use crate::{
13    geometry::{
14        Coordinates,
15        mesh::{Connectivities, Connectivity, Mesh, NodeSets, SideSets},
16    },
17    math::{CrossProduct, Set},
18};
19use std::cell::OnceCell;
20
21/// The axis orders of the Kuhn/Freudenthal split: each a path of unit steps
22/// from a cell's all-low corner to its all-high one.
23const KUHN: [[usize; 2]; 6] = [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]];
24
25/// Splits a cell into six tetrahedra about the diagonal from corner `0` to
26/// corner `7` of `corners`, indexed by the bits of each corner's position.
27///
28/// Bit `b` is set on the high side of axis `b`, so corners `0` and `7` are the
29/// cell's lexicographic extremes and every square face ends up cut by the
30/// diagonal joining its own two extremes. That is a property of the face, not
31/// of either cell holding it, so neighbors cut a shared face identically.
32pub(super) fn kuhn(corners: &[usize; 8]) -> [[usize; 4]; 6] {
33    KUHN.map(|[first, second]| {
34        [
35            corners[0],
36            corners[1 << first],
37            corners[(1 << first) | (1 << second)],
38            corners[7],
39        ]
40    })
41}
42
43pub(super) fn positive(tet: &[usize; 4], coordinates: &Coordinates<3>) -> bool {
44    let u = &coordinates[tet[1]] - &coordinates[tet[0]];
45    let v = &coordinates[tet[2]] - &coordinates[tet[0]];
46    let w = &coordinates[tet[3]] - &coordinates[tet[0]];
47    (&u.cross(v) * &w).value() > 0.0
48}
49
50pub(super) fn orient(tets: &mut [[usize; 4]], coordinates: &Coordinates<3>) {
51    tets.iter_mut().for_each(|tet| {
52        if !positive(tet, coordinates) {
53            tet.swap(2, 3)
54        }
55    })
56}
57
58impl<const D: usize> From<(Connectivities, Set<Coordinates<D>>)> for Mesh<D> {
59    fn from((connectivities, coordinates): (Connectivities, Set<Coordinates<D>>)) -> Self {
60        Self {
61            connectivities,
62            coordinates,
63            node_sets: NodeSets::from(Vec::new()),
64            side_sets: SideSets::from(Vec::new()),
65            nodes_elements: OnceCell::new(),
66            nodes_nodes: OnceCell::new(),
67        }
68    }
69}
70
71impl<const D: usize> From<(Vec<Connectivity>, Coordinates<D>)> for Mesh<D> {
72    fn from((connectivities, coordinates): (Vec<Connectivity>, Coordinates<D>)) -> Self {
73        Self {
74            connectivities: Connectivities::from(connectivities),
75            coordinates: Set::from(coordinates),
76            node_sets: NodeSets::from(Vec::new()),
77            side_sets: SideSets::from(Vec::new()),
78            nodes_elements: OnceCell::new(),
79            nodes_nodes: OnceCell::new(),
80        }
81    }
82}