Skip to main content

runmat_meshing_plc/build/
errors.rs

1use crate::validate::PlcValidationError;
2use runmat_meshing_core::contracts::TopologyEntityId;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum PlcBuildError {
6    EmptySurface,
7    MissingCurveBoundaryValidation,
8    MissingSurfaceLoopCoverage,
9    InconsistentSurfaceLoopCoverage {
10        recovered_face_count: usize,
11        surface_source_face_count: usize,
12        boundary_loop_count: usize,
13        hole_loop_count: usize,
14        max_loops_per_face: usize,
15        boundary_node_count: usize,
16        recovered_source_edge_count: usize,
17        protected_source_edge_count: usize,
18        boundary_segment_count: usize,
19    },
20    InconsistentCadCurveBoundaryProvenance {
21        reason: &'static str,
22        recovered_source_edge_count: usize,
23        protected_source_edge_count: usize,
24        boundary_segment_count: usize,
25        edge_report_count: usize,
26    },
27    MissingSurfaceNode {
28        triangle_id: u32,
29        node_id: u32,
30    },
31    NonFiniteSurfaceNode {
32        node_id: u32,
33    },
34    NonFiniteSurfaceTriangle {
35        triangle_id: u32,
36    },
37    NonPositiveSurfaceTriangleArea {
38        triangle_id: u32,
39    },
40    InvalidSurfaceEntityId {
41        entity_id: TopologyEntityId,
42    },
43    DuplicateFacet {
44        element_id: u32,
45    },
46    AmbiguousProtectedBoundarySegment {
47        node_ids: [u32; 2],
48        first_source_edge_id: u32,
49        second_source_edge_id: u32,
50    },
51    PartiallyProtectedBoundarySegment {
52        node_ids: [u32; 2],
53        source_edge_id: u32,
54    },
55    OpenBoundaryEdge {
56        node_ids: [u32; 2],
57        incidence_count: usize,
58    },
59    NonManifoldBoundaryEdge {
60        node_ids: [u32; 2],
61        incidence_count: usize,
62    },
63    ProtectedBoundaryValidation(Box<PlcValidationError>),
64}
65
66impl std::fmt::Display for PlcBuildError {
67    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            Self::EmptySurface => write!(formatter, "surface mesh has no facets for PLC build"),
70            Self::MissingCurveBoundaryValidation => write!(
71                formatter,
72                "surface mesh has protected source edges but no curve-boundary validation evidence"
73            ),
74            Self::MissingSurfaceLoopCoverage => write!(
75                formatter,
76                "surface mesh has protected source edges but no surface loop coverage evidence"
77            ),
78            Self::InconsistentSurfaceLoopCoverage {
79                recovered_face_count,
80                surface_source_face_count,
81                boundary_loop_count,
82                hole_loop_count,
83                max_loops_per_face,
84                boundary_node_count,
85                recovered_source_edge_count,
86                protected_source_edge_count,
87                boundary_segment_count,
88            } => write!(
89                formatter,
90                "surface loop coverage is inconsistent with PLC input: recovered faces {recovered_face_count}, surface source faces {surface_source_face_count}, boundary loops {boundary_loop_count}, hole loops {hole_loop_count}, max loops per face {max_loops_per_face}, boundary nodes {boundary_node_count}, recovered source edges {recovered_source_edge_count}, protected source edges {protected_source_edge_count}, boundary segments {boundary_segment_count}"
91            ),
92            Self::InconsistentCadCurveBoundaryProvenance {
93                reason,
94                recovered_source_edge_count,
95                protected_source_edge_count,
96                boundary_segment_count,
97                edge_report_count,
98            } => write!(
99                formatter,
100                "CAD curve boundary provenance is inconsistent with PLC input ({reason}): recovered source edges {recovered_source_edge_count}, protected source edges {protected_source_edge_count}, boundary segments {boundary_segment_count}, edge reports {edge_report_count}"
101            ),
102            Self::MissingSurfaceNode {
103                triangle_id,
104                node_id,
105            } => write!(
106                formatter,
107                "surface triangle {triangle_id} references missing PLC node {node_id}"
108            ),
109            Self::NonFiniteSurfaceNode { node_id } => {
110                write!(
111                    formatter,
112                    "surface node {node_id} has non-finite coordinates"
113                )
114            }
115            Self::NonFiniteSurfaceTriangle { triangle_id } => write!(
116                formatter,
117                "surface triangle {triangle_id} has non-finite area or projection evidence"
118            ),
119            Self::NonPositiveSurfaceTriangleArea { triangle_id } => write!(
120                formatter,
121                "surface triangle {triangle_id} has non-positive area evidence"
122            ),
123            Self::InvalidSurfaceEntityId { entity_id } => write!(
124                formatter,
125                "surface contract entity {:?}:{} is not usable as a PLC numeric topology ID",
126                entity_id.stage, entity_id.id
127            ),
128            Self::DuplicateFacet { element_id } => write!(
129                formatter,
130                "surface triangle {element_id} duplicates an existing PLC facet"
131            ),
132            Self::AmbiguousProtectedBoundarySegment {
133                node_ids,
134                first_source_edge_id,
135                second_source_edge_id,
136            } => write!(
137                formatter,
138                "surface boundary segment {}-{} has ambiguous source edges {} and {}",
139                node_ids[0], node_ids[1], first_source_edge_id, second_source_edge_id
140            ),
141            Self::PartiallyProtectedBoundarySegment {
142                node_ids,
143                source_edge_id,
144            } => write!(
145                formatter,
146                "surface boundary segment {}-{} is only partially owned by protected source edge {}",
147                node_ids[0], node_ids[1], source_edge_id
148            ),
149            Self::OpenBoundaryEdge {
150                node_ids,
151                incidence_count,
152            } => write!(
153                formatter,
154                "PLC edge {}-{} has incidence {incidence_count}, expected 2",
155                node_ids[0], node_ids[1]
156            ),
157            Self::NonManifoldBoundaryEdge {
158                node_ids,
159                incidence_count,
160            } => write!(
161                formatter,
162                "PLC edge {}-{} has non-manifold incidence {incidence_count}, expected 2",
163                node_ids[0], node_ids[1]
164            ),
165            Self::ProtectedBoundaryValidation(error) => {
166                write!(formatter, "built PLC failed validation: {error}")
167            }
168        }
169    }
170}
171
172impl std::error::Error for PlcBuildError {}