#[allow(unused_imports)]
use super::functions::*;
#[allow(unused_imports)]
use super::functions_2::*;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub enum QualitySuggestion {
RemoveDegenerates {
count: u32,
},
RefineHighAspectRatio {
count: u32,
max_ar: f32,
},
SplitLargeAngleTriangles {
count: u32,
},
RemoveDuplicateVertices {
estimated_duplicates: usize,
},
MeshIsGoodQuality,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ExtendedQualityReport {
pub basic: MeshQualityReport,
pub aspect_ratio_histogram: [u32; 10],
pub min_angle_histogram: [u32; 9],
pub median_area: f32,
pub area_std_dev: f32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct QualityVisualizationData {
pub aspect_ratios: Vec<f32>,
pub skewness: Vec<f32>,
pub min_angles: Vec<f32>,
pub max_angles: Vec<f32>,
pub areas: Vec<f32>,
pub jacobians: Vec<f32>,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MeshComparison {
pub vertex_count_diff: i64,
pub triangle_count_diff: i64,
pub surface_area_diff: f32,
pub avg_edge_length_diff: f32,
pub mean_skewness_diff: f32,
pub fewer_degenerates: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct PoorlyShapedElement {
pub index: usize,
pub reasons: Vec<PoorShapeReason>,
}
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub enum PoorShapeReason {
HighAspectRatio(f32),
SmallAngle(f32),
LargeAngle(f32),
Degenerate,
HighSkewness(f32),
}
#[allow(dead_code)]
pub struct MeshQuality;
#[allow(dead_code)]
impl MeshQuality {
pub fn compute_dihedral_angle(ea: [f32; 3], eb: [f32; 3], p0: [f32; 3], p1: [f32; 3]) -> f32 {
let n0 = cross(sub(eb, ea), sub(p0, ea));
let n1 = cross(sub(eb, ea), sub(p1, ea));
let len0 = norm(n0);
let len1 = norm(n1);
if len0 < 1e-15 || len1 < 1e-15 {
return 0.0;
}
let cos_theta = (dot(n0, n1) / (len0 * len1)).clamp(-1.0, 1.0);
cos_theta.acos().to_degrees()
}
pub fn compute_edge_length_ratio(v0: [f32; 3], v1: [f32; 3], v2: [f32; 3]) -> f32 {
let e0 = norm(sub(v1, v0));
let e1 = norm(sub(v2, v1));
let e2 = norm(sub(v0, v2));
let max_e = e0.max(e1).max(e2);
let min_e = e0.min(e1).min(e2);
if min_e < 1e-15 {
f32::INFINITY
} else {
max_e / min_e
}
}
pub fn compute_mesh_regularity(mesh: &TriangleMesh) -> f32 {
let n = mesh.triangle_count();
if n == 0 {
return 1.0;
}
let ratios: Vec<f32> = mesh
.triangles
.iter()
.map(|t| {
let v0 = mesh.vertices[t[0] as usize];
let v1 = mesh.vertices[t[1] as usize];
let v2 = mesh.vertices[t[2] as usize];
triangle_aspect_ratio(v0, v1, v2)
})
.collect();
let finite: Vec<f32> = ratios.iter().copied().filter(|v| v.is_finite()).collect();
if finite.is_empty() {
return 0.0;
}
let mean = finite.iter().sum::<f32>() / finite.len() as f32;
let variance =
finite.iter().map(|&r| (r - mean) * (r - mean)).sum::<f32>() / finite.len() as f32;
let sigma = variance.sqrt();
1.0 / (1.0 + sigma)
}
}
#[allow(dead_code)]
pub struct TriangleMesh {
pub vertices: Vec<[f32; 3]>,
pub triangles: Vec<[u32; 3]>,
}
impl TriangleMesh {
#[allow(dead_code)]
pub fn new() -> Self {
Self {
vertices: Vec::new(),
triangles: Vec::new(),
}
}
#[allow(dead_code)]
pub fn from_raw(verts: Vec<[f32; 3]>, tris: Vec<[u32; 3]>) -> Self {
Self {
vertices: verts,
triangles: tris,
}
}
#[allow(dead_code)]
pub fn vertex_count(&self) -> usize {
self.vertices.len()
}
#[allow(dead_code)]
pub fn triangle_count(&self) -> usize {
self.triangles.len()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FullQualityReport {
pub basic: MeshQualityReport,
pub global_min_angle_deg: f32,
pub global_max_angle_deg: f32,
pub mean_angle_deg: f32,
pub min_jacobian: f32,
pub max_jacobian: f32,
pub mean_jacobian: f32,
pub element_type_counts: Vec<(String, u32)>,
pub n_poorly_shaped: u32,
pub total_surface_area: f32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct QualityThresholds {
pub max_aspect_ratio: f32,
pub max_skewness: f32,
pub min_angle: f32,
pub max_angle: f32,
pub min_area: f32,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct ElementTypeStats {
pub n_equilateral: u32,
pub n_right: u32,
pub n_obtuse: u32,
pub n_acute: u32,
pub n_degenerate: u32,
pub total: u32,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct PerTypeMeshStats {
pub equilateral_mean_ar: f32,
pub obtuse_mean_ar: f32,
pub right_mean_ar: f32,
pub n_equilateral: u32,
pub n_obtuse: u32,
pub n_right: u32,
pub n_acute: u32,
pub n_degenerate: u32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct QualityCheckResult {
pub n_bad_aspect_ratio: u32,
pub n_bad_skewness: u32,
pub n_small_angle: u32,
pub n_large_angle: u32,
pub n_below_min_area: u32,
pub passes: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MeshQualityReport {
pub min_area: f32,
pub max_area: f32,
pub mean_area: f32,
pub min_aspect_ratio: f32,
pub max_aspect_ratio: f32,
pub mean_skewness: f32,
pub n_degenerate: u32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct AutoImproveSuggestion {
pub description: String,
pub priority: u8,
pub affected: usize,
}
impl AutoImproveSuggestion {
pub fn new(description: impl Into<String>, priority: u8, affected: usize) -> Self {
Self {
description: description.into(),
priority,
affected,
}
}
}