oxiphysics_io/mesh_quality/types.rs
1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5#[allow(unused_imports)]
6use super::functions::*;
7#[allow(unused_imports)]
8use super::functions_2::*;
9/// A suggestion for improving mesh quality.
10#[allow(dead_code)]
11#[derive(Debug, Clone)]
12pub enum QualitySuggestion {
13 /// Remove degenerate triangles.
14 RemoveDegenerates {
15 /// Number of degenerate triangles.
16 count: u32,
17 },
18 /// Refine triangles with high aspect ratio.
19 RefineHighAspectRatio {
20 /// Number of high aspect ratio triangles.
21 count: u32,
22 /// Maximum aspect ratio found.
23 max_ar: f32,
24 },
25 /// Split triangles with large angles.
26 SplitLargeAngleTriangles {
27 /// Number of large-angle triangles.
28 count: u32,
29 },
30 /// Remove duplicate vertices.
31 RemoveDuplicateVertices {
32 /// Estimated number of duplicate vertices.
33 estimated_duplicates: usize,
34 },
35 /// Mesh is good quality.
36 MeshIsGoodQuality,
37}
38/// Extended quality report with histogram data.
39#[allow(dead_code)]
40#[derive(Debug, Clone)]
41pub struct ExtendedQualityReport {
42 /// Basic quality report.
43 pub basic: MeshQualityReport,
44 /// Histogram of aspect ratios in 10 bins from 1.0 to max.
45 pub aspect_ratio_histogram: [u32; 10],
46 /// Histogram of minimum angles in 9 bins (0-10, 10-20, ..., 80-90 degrees).
47 pub min_angle_histogram: [u32; 9],
48 /// Median area.
49 pub median_area: f32,
50 /// Standard deviation of areas.
51 pub area_std_dev: f32,
52}
53/// Per-triangle quality values for visualization.
54#[allow(dead_code)]
55#[derive(Debug, Clone)]
56pub struct QualityVisualizationData {
57 /// Aspect ratio per triangle.
58 pub aspect_ratios: Vec<f32>,
59 /// Skewness per triangle.
60 pub skewness: Vec<f32>,
61 /// Minimum angle per triangle.
62 pub min_angles: Vec<f32>,
63 /// Maximum angle per triangle.
64 pub max_angles: Vec<f32>,
65 /// Area per triangle.
66 pub areas: Vec<f32>,
67 /// Jacobian (2*area) per triangle.
68 pub jacobians: Vec<f32>,
69}
70/// Result of comparing two meshes.
71#[allow(dead_code)]
72#[derive(Debug, Clone)]
73pub struct MeshComparison {
74 /// Difference in vertex count (mesh_b - mesh_a).
75 pub vertex_count_diff: i64,
76 /// Difference in triangle count (mesh_b - mesh_a).
77 pub triangle_count_diff: i64,
78 /// Difference in total surface area.
79 pub surface_area_diff: f32,
80 /// Difference in average edge length.
81 pub avg_edge_length_diff: f32,
82 /// Difference in mean skewness.
83 pub mean_skewness_diff: f32,
84 /// Whether mesh_b has fewer degenerate triangles.
85 pub fewer_degenerates: bool,
86}
87/// A poorly-shaped element with its index and the reason it is flagged.
88#[allow(dead_code)]
89#[derive(Debug, Clone)]
90pub struct PoorlyShapedElement {
91 /// Triangle index.
92 pub index: usize,
93 /// Reason(s) for being flagged.
94 pub reasons: Vec<PoorShapeReason>,
95}
96/// Reason a triangle is considered poorly shaped.
97#[allow(dead_code)]
98#[derive(Debug, Clone, PartialEq)]
99pub enum PoorShapeReason {
100 /// High aspect ratio (> threshold).
101 HighAspectRatio(f32),
102 /// Small minimum angle (< threshold degrees).
103 SmallAngle(f32),
104 /// Large maximum angle (> threshold degrees).
105 LargeAngle(f32),
106 /// Very small area (degenerate).
107 Degenerate,
108 /// High skewness (> threshold).
109 HighSkewness(f32),
110}
111/// Additional triangle mesh quality metrics.
112#[allow(dead_code)]
113pub struct MeshQuality;
114#[allow(dead_code)]
115impl MeshQuality {
116 /// Compute the dihedral angle (in degrees) between two adjacent triangles
117 /// sharing an edge defined by vertices `ea` and `eb`.
118 ///
119 /// The first triangle is `(ea, eb, p0)` and the second is `(ea, eb, p1)`.
120 /// Returns the angle between their face normals, in the range `[0°, 180°]`.
121 pub fn compute_dihedral_angle(ea: [f32; 3], eb: [f32; 3], p0: [f32; 3], p1: [f32; 3]) -> f32 {
122 let n0 = cross(sub(eb, ea), sub(p0, ea));
123 let n1 = cross(sub(eb, ea), sub(p1, ea));
124 let len0 = norm(n0);
125 let len1 = norm(n1);
126 if len0 < 1e-15 || len1 < 1e-15 {
127 return 0.0;
128 }
129 let cos_theta = (dot(n0, n1) / (len0 * len1)).clamp(-1.0, 1.0);
130 cos_theta.acos().to_degrees()
131 }
132 /// Compute the edge-length ratio (max edge / min edge) for a triangle.
133 ///
134 /// A value of 1 indicates an equilateral triangle. Returns `f32::INFINITY`
135 /// if the minimum edge length is effectively zero (degenerate triangle).
136 pub fn compute_edge_length_ratio(v0: [f32; 3], v1: [f32; 3], v2: [f32; 3]) -> f32 {
137 let e0 = norm(sub(v1, v0));
138 let e1 = norm(sub(v2, v1));
139 let e2 = norm(sub(v0, v2));
140 let max_e = e0.max(e1).max(e2);
141 let min_e = e0.min(e1).min(e2);
142 if min_e < 1e-15 {
143 f32::INFINITY
144 } else {
145 max_e / min_e
146 }
147 }
148 /// Compute a global mesh regularity score in `[0, 1]`.
149 ///
150 /// Regularity is defined as:
151 /// ```text
152 /// R = 1 / (1 + sigma)
153 /// ```
154 /// where `sigma` is the standard deviation of the per-triangle aspect ratios.
155 /// A perfectly regular mesh (all equilateral triangles) has `sigma = 0` → `R = 1`.
156 /// A highly irregular mesh has large `sigma` → `R → 0`.
157 ///
158 /// Returns `1.0` for an empty mesh.
159 pub fn compute_mesh_regularity(mesh: &TriangleMesh) -> f32 {
160 let n = mesh.triangle_count();
161 if n == 0 {
162 return 1.0;
163 }
164 let ratios: Vec<f32> = mesh
165 .triangles
166 .iter()
167 .map(|t| {
168 let v0 = mesh.vertices[t[0] as usize];
169 let v1 = mesh.vertices[t[1] as usize];
170 let v2 = mesh.vertices[t[2] as usize];
171 triangle_aspect_ratio(v0, v1, v2)
172 })
173 .collect();
174 let finite: Vec<f32> = ratios.iter().copied().filter(|v| v.is_finite()).collect();
175 if finite.is_empty() {
176 return 0.0;
177 }
178 let mean = finite.iter().sum::<f32>() / finite.len() as f32;
179 let variance =
180 finite.iter().map(|&r| (r - mean) * (r - mean)).sum::<f32>() / finite.len() as f32;
181 let sigma = variance.sqrt();
182 1.0 / (1.0 + sigma)
183 }
184}
185/// A triangle mesh consisting of vertices and triangle connectivity.
186#[allow(dead_code)]
187pub struct TriangleMesh {
188 /// 3D vertex positions.
189 pub vertices: Vec<[f32; 3]>,
190 /// Triangle face indices (each entry is \[v0, v1, v2\]).
191 pub triangles: Vec<[u32; 3]>,
192}
193impl TriangleMesh {
194 /// Create an empty mesh.
195 #[allow(dead_code)]
196 pub fn new() -> Self {
197 Self {
198 vertices: Vec::new(),
199 triangles: Vec::new(),
200 }
201 }
202 /// Create a mesh from raw vertex and triangle data.
203 #[allow(dead_code)]
204 pub fn from_raw(verts: Vec<[f32; 3]>, tris: Vec<[u32; 3]>) -> Self {
205 Self {
206 vertices: verts,
207 triangles: tris,
208 }
209 }
210 /// Return the number of vertices.
211 #[allow(dead_code)]
212 pub fn vertex_count(&self) -> usize {
213 self.vertices.len()
214 }
215 /// Return the number of triangles.
216 #[allow(dead_code)]
217 pub fn triangle_count(&self) -> usize {
218 self.triangles.len()
219 }
220}
221/// Full mesh quality report including angles, Jacobians, and element counts.
222#[allow(dead_code)]
223#[derive(Debug, Clone)]
224pub struct FullQualityReport {
225 /// Basic quality report.
226 pub basic: MeshQualityReport,
227 /// Minimum interior angle across all triangles (degrees).
228 pub global_min_angle_deg: f32,
229 /// Maximum interior angle across all triangles (degrees).
230 pub global_max_angle_deg: f32,
231 /// Mean interior angle across all triangles (degrees).
232 pub mean_angle_deg: f32,
233 /// Minimum Jacobian (2D: 2*area, proxy for triangle quality).
234 pub min_jacobian: f32,
235 /// Maximum Jacobian.
236 pub max_jacobian: f32,
237 /// Mean Jacobian.
238 pub mean_jacobian: f32,
239 /// Count of triangles per element type string.
240 pub element_type_counts: Vec<(String, u32)>,
241 /// Poorly-shaped element count (aspect ratio > 5 OR min angle < 15 deg).
242 pub n_poorly_shaped: u32,
243 /// Total surface area.
244 pub total_surface_area: f32,
245}
246/// Quality thresholds for evaluating mesh quality.
247#[allow(dead_code)]
248#[derive(Debug, Clone)]
249pub struct QualityThresholds {
250 /// Maximum acceptable aspect ratio.
251 pub max_aspect_ratio: f32,
252 /// Maximum acceptable skewness (0..1).
253 pub max_skewness: f32,
254 /// Minimum acceptable angle (degrees).
255 pub min_angle: f32,
256 /// Maximum acceptable angle (degrees).
257 pub max_angle: f32,
258 /// Minimum acceptable area.
259 pub min_area: f32,
260}
261/// Statistics about element shapes in the mesh.
262#[allow(dead_code)]
263#[derive(Debug, Clone, Default)]
264pub struct ElementTypeStats {
265 /// Number of near-equilateral triangles (all angles within 50-70 degrees).
266 pub n_equilateral: u32,
267 /// Number of right triangles (one angle within 85-95 degrees).
268 pub n_right: u32,
269 /// Number of obtuse triangles (one angle > 95 degrees).
270 pub n_obtuse: u32,
271 /// Number of acute triangles (all angles < 85 degrees, non-equilateral).
272 pub n_acute: u32,
273 /// Number of degenerate triangles (area < threshold).
274 pub n_degenerate: u32,
275 /// Total number of triangles.
276 pub total: u32,
277}
278/// Quality statistics broken down per element category.
279#[allow(dead_code)]
280#[derive(Debug, Clone, Default)]
281pub struct PerTypeMeshStats {
282 /// Mean aspect ratio of equilateral triangles.
283 pub equilateral_mean_ar: f32,
284 /// Mean aspect ratio of obtuse triangles.
285 pub obtuse_mean_ar: f32,
286 /// Mean aspect ratio of right triangles.
287 pub right_mean_ar: f32,
288 /// Count of each category.
289 pub n_equilateral: u32,
290 /// Count of obtuse triangles.
291 pub n_obtuse: u32,
292 /// Count of right triangles.
293 pub n_right: u32,
294 /// Count of acute triangles.
295 pub n_acute: u32,
296 /// Count of degenerate triangles.
297 pub n_degenerate: u32,
298}
299/// Result of checking a mesh against quality thresholds.
300#[allow(dead_code)]
301#[derive(Debug, Clone)]
302pub struct QualityCheckResult {
303 /// Number of triangles exceeding max aspect ratio.
304 pub n_bad_aspect_ratio: u32,
305 /// Number of triangles exceeding max skewness.
306 pub n_bad_skewness: u32,
307 /// Number of triangles with angles below min_angle.
308 pub n_small_angle: u32,
309 /// Number of triangles with angles above max_angle.
310 pub n_large_angle: u32,
311 /// Number of triangles below min area.
312 pub n_below_min_area: u32,
313 /// Whether the mesh passes all checks.
314 pub passes: bool,
315}
316/// Summary of mesh quality metrics computed over all triangles.
317#[allow(dead_code)]
318#[derive(Debug, Clone)]
319pub struct MeshQualityReport {
320 /// Minimum triangle area.
321 pub min_area: f32,
322 /// Maximum triangle area.
323 pub max_area: f32,
324 /// Mean triangle area.
325 pub mean_area: f32,
326 /// Minimum aspect ratio.
327 pub min_aspect_ratio: f32,
328 /// Maximum aspect ratio.
329 pub max_aspect_ratio: f32,
330 /// Mean skewness (0 = perfect, 1 = degenerate).
331 pub mean_skewness: f32,
332 /// Number of degenerate triangles (area < 1e-10).
333 pub n_degenerate: u32,
334}
335/// Automated quality improvement suggestion with priority.
336#[allow(dead_code)]
337#[derive(Debug, Clone)]
338pub struct AutoImproveSuggestion {
339 /// Human-readable description.
340 pub description: String,
341 /// Priority (1 = highest, 5 = lowest).
342 pub priority: u8,
343 /// Estimated number of affected elements.
344 pub affected: usize,
345}
346impl AutoImproveSuggestion {
347 /// Create a new suggestion.
348 pub fn new(description: impl Into<String>, priority: u8, affected: usize) -> Self {
349 Self {
350 description: description.into(),
351 priority,
352 affected,
353 }
354 }
355}