runmat_meshing_plc/build/
errors.rs1use 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 {}