Skip to main content

runmat_meshing_surface/recovery/
types.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
4pub struct SurfaceRecoveryOptions {
5    pub require_closed: bool,
6    pub max_area_relative_error: f64,
7    pub min_normal_alignment: f64,
8}
9
10impl Default for SurfaceRecoveryOptions {
11    fn default() -> Self {
12        Self {
13            require_closed: true,
14            max_area_relative_error: 1.0e-8,
15            min_normal_alignment: 1.0 - 1.0e-8,
16        }
17    }
18}
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub struct SurfaceRecoveryReport {
22    pub surface_element_count: usize,
23    pub recovered_edge_count: usize,
24    pub open_edge_count: usize,
25    pub nonmanifold_edge_count: usize,
26    pub max_area_relative_error: f64,
27    pub min_normal_alignment: f64,
28    pub source_face_coverage_ratio: f64,
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum SurfaceRecoveryError {
33    EmptySurface,
34    InvalidOptions,
35    MissingSurfaceNode {
36        element_id: u32,
37        node_id: u32,
38    },
39    NonFiniteSurfaceNode {
40        node_id: u32,
41    },
42    DegenerateElement {
43        element_id: u32,
44    },
45    AreaMismatch {
46        element_id: u32,
47        relative_error: f64,
48        max_relative_error: f64,
49    },
50    SourceFaceAreaMismatch {
51        source_face_id: u32,
52        relative_error: f64,
53        max_relative_error: f64,
54    },
55    NormalMismatch {
56        element_id: u32,
57        alignment: f64,
58        min_alignment: f64,
59    },
60    MissingSourceFace {
61        source_face_id: u32,
62    },
63    UncoveredSourceFace {
64        source_face_id: u32,
65    },
66    OpenEdge {
67        edge: [u32; 2],
68        count: usize,
69    },
70    NonManifoldEdge {
71        edge: [u32; 2],
72        count: usize,
73    },
74}
75
76impl std::fmt::Display for SurfaceRecoveryError {
77    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        match self {
79            Self::EmptySurface => write!(formatter, "surface recovery input has no elements"),
80            Self::InvalidOptions => write!(
81                formatter,
82                "surface recovery options must use finite area and normal thresholds"
83            ),
84            Self::MissingSurfaceNode {
85                element_id,
86                node_id,
87            } => write!(
88                formatter,
89                "surface element {element_id} references missing node {node_id}"
90            ),
91            Self::NonFiniteSurfaceNode { node_id } => {
92                write!(formatter, "surface node {node_id} has non-finite coordinates")
93            }
94            Self::DegenerateElement { element_id } => {
95                write!(formatter, "surface element {element_id} is degenerate")
96            }
97            Self::AreaMismatch {
98                element_id,
99                relative_error,
100                max_relative_error,
101            } => write!(
102                formatter,
103                "surface element {element_id} area relative error {relative_error:.6e} exceeds {max_relative_error:.6e}"
104            ),
105            Self::SourceFaceAreaMismatch {
106                source_face_id,
107                relative_error,
108                max_relative_error,
109            } => write!(
110                formatter,
111                "source face {source_face_id} recovered area relative error {relative_error:.6e} exceeds {max_relative_error:.6e}"
112            ),
113            Self::NormalMismatch {
114                element_id,
115                alignment,
116                min_alignment,
117            } => write!(
118                formatter,
119                "surface element {element_id} normal alignment {alignment:.6e} is below {min_alignment:.6e}"
120            ),
121            Self::MissingSourceFace { source_face_id } => {
122                write!(formatter, "source face {source_face_id} is not present in topology")
123            }
124            Self::UncoveredSourceFace { source_face_id } => {
125                write!(formatter, "source face {source_face_id} is not covered by surface mesh")
126            }
127            Self::OpenEdge { edge, count } => write!(
128                formatter,
129                "surface edge {}-{} has incidence {count}, expected 2",
130                edge[0], edge[1]
131            ),
132            Self::NonManifoldEdge { edge, count } => write!(
133                formatter,
134                "surface edge {}-{} has non-manifold incidence {count}, expected 2",
135                edge[0], edge[1]
136            ),
137        }
138    }
139}
140
141impl std::error::Error for SurfaceRecoveryError {}