Skip to main content

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}