oxiphysics_geometry/mesh_processing/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_2::*;
7use std::collections::HashSet;
8
9#[allow(unused_imports)]
10use super::functions::*;
11use super::functions::{Face, Uv, Vertex};
12
13/// An anisotropic size field: target edge lengths along principal curvature
14/// directions.
15#[derive(Debug, Clone)]
16pub struct AnisotropicSizeField {
17 /// Per-vertex minimum principal curvature direction.
18 pub k_min_dir: Vec<[f64; 3]>,
19 /// Per-vertex maximum principal curvature direction.
20 pub k_max_dir: Vec<[f64; 3]>,
21 /// Target edge length along minimum curvature direction.
22 pub len_min: Vec<f64>,
23 /// Target edge length along maximum curvature direction.
24 pub len_max: Vec<f64>,
25}
26/// Aggregate quality statistics over a whole mesh.
27#[derive(Debug, Clone)]
28pub struct MeshQualityStats {
29 /// Mean aspect ratio across all faces.
30 pub mean_aspect_ratio: f64,
31 /// Maximum aspect ratio (worst triangle).
32 pub max_aspect_ratio: f64,
33 /// Minimum angle (degrees) in the mesh.
34 pub min_angle_deg: f64,
35 /// Mean area quality score (0..1; 1 = equilateral).
36 pub mean_area_quality: f64,
37}
38/// A feature edge defined by its two endpoint vertex indices and the dihedral
39/// angle between the two adjacent faces.
40#[derive(Debug, Clone, Copy)]
41pub struct FeatureEdge {
42 /// First vertex index.
43 pub v0: usize,
44 /// Second vertex index.
45 pub v1: usize,
46 /// Dihedral angle between adjacent faces in radians.
47 pub dihedral_angle: f64,
48}
49/// A symmetric 4×4 quadric error matrix stored in compact upper-triangle form.
50/// Indices: Q\[0\]=q00, Q\[1\]=q01, Q\[2\]=q02, Q\[3\]=q03, Q\[4\]=q11, Q\[5\]=q12,
51/// Q\[6\]=q13, Q\[7\]=q22, Q\[8\]=q23, Q\[9\]=q33.
52#[derive(Debug, Clone, Copy, Default)]
53pub struct Quadric {
54 /// Upper-triangle elements of the 4×4 symmetric matrix.
55 pub q: [f64; 10],
56}
57impl Quadric {
58 /// Create a zero quadric.
59 pub fn zero() -> Self {
60 Self { q: [0.0; 10] }
61 }
62 /// Add another quadric to this one.
63 pub fn add(&self, other: &Quadric) -> Quadric {
64 let mut r = Quadric::zero();
65 for i in 0..10 {
66 r.q[i] = self.q[i] + other.q[i];
67 }
68 r
69 }
70 /// Build a fundamental error quadric for the plane (a,b,c,d) where
71 /// `ax + by + cz + d = 0` and `(a,b,c)` is the unit normal.
72 pub fn from_plane(a: f64, b: f64, c: f64, d: f64) -> Quadric {
73 Quadric {
74 q: [
75 a * a,
76 a * b,
77 a * c,
78 a * d,
79 b * b,
80 b * c,
81 b * d,
82 c * c,
83 c * d,
84 d * d,
85 ],
86 }
87 }
88 /// Evaluate Q(v) = váµ€Qv (cost of placing a vertex at `v`).
89 pub fn evaluate(&self, v: [f64; 3]) -> f64 {
90 let [x, y, z] = v;
91 let w = 1.0_f64;
92 let q = &self.q;
93 q[0] * x * x
94 + 2.0 * q[1] * x * y
95 + 2.0 * q[2] * x * z
96 + 2.0 * q[3] * x * w
97 + q[4] * y * y
98 + 2.0 * q[5] * y * z
99 + 2.0 * q[6] * y * w
100 + q[7] * z * z
101 + 2.0 * q[8] * z * w
102 + q[9] * w * w
103 }
104}
105/// Quality metrics for a single triangle.
106#[derive(Debug, Clone, Copy)]
107pub struct TriangleQuality {
108 /// Aspect ratio (circumradius / 2·inradius); perfect equilateral = 1.
109 pub aspect_ratio: f64,
110 /// Minimum interior angle in radians.
111 pub min_angle: f64,
112 /// Maximum interior angle in radians.
113 pub max_angle: f64,
114 /// Normalised area (0..1 relative to equilateral with same perimeter).
115 pub area_quality: f64,
116}
117/// A triangle mesh used as the primary data structure for all processing.
118#[derive(Debug, Clone)]
119pub struct ProcessMesh {
120 /// Vertex positions.
121 pub verts: Vec<Vertex>,
122 /// Triangular faces (vertex-index triples).
123 pub faces: Vec<Face>,
124 /// Per-vertex normals (optional).
125 pub normals: Option<Vec<Vertex>>,
126 /// Per-vertex UV coordinates (optional).
127 pub uvs: Option<Vec<Uv>>,
128}
129impl ProcessMesh {
130 /// Create a new mesh from vertices and faces.
131 pub fn new(verts: Vec<Vertex>, faces: Vec<Face>) -> Self {
132 Self {
133 verts,
134 faces,
135 normals: None,
136 uvs: None,
137 }
138 }
139 /// Return the number of vertices.
140 pub fn num_verts(&self) -> usize {
141 self.verts.len()
142 }
143 /// Return the number of faces.
144 pub fn num_faces(&self) -> usize {
145 self.faces.len()
146 }
147 /// Compute per-vertex normals by averaging adjacent face normals.
148 pub fn compute_normals(&mut self) {
149 let nv = self.verts.len();
150 let mut normals = vec![[0.0_f64; 3]; nv];
151 for &[a, b, c] in &self.faces {
152 let va = self.verts[a];
153 let vb = self.verts[b];
154 let vc = self.verts[c];
155 let ab = vec3_sub(vb, va);
156 let ac = vec3_sub(vc, va);
157 let n = vec3_cross(ab, ac);
158 for &i in &[a, b, c] {
159 normals[i] = vec3_add(normals[i], n);
160 }
161 }
162 for n in &mut normals {
163 *n = vec3_normalize(*n);
164 }
165 self.normals = Some(normals);
166 }
167 /// Build a map from each vertex to its list of neighbouring vertex indices.
168 pub fn build_adjacency(&self) -> Vec<Vec<usize>> {
169 let nv = self.verts.len();
170 let mut adj: Vec<HashSet<usize>> = vec![HashSet::new(); nv];
171 for &[a, b, c] in &self.faces {
172 adj[a].insert(b);
173 adj[a].insert(c);
174 adj[b].insert(a);
175 adj[b].insert(c);
176 adj[c].insert(a);
177 adj[c].insert(b);
178 }
179 adj.into_iter().map(|s| s.into_iter().collect()).collect()
180 }
181}
182/// UV parameterization result with per-vertex texture coordinates.
183#[derive(Debug, Clone)]
184pub struct UvParameterization {
185 /// Mesh after parameterization (same topology).
186 pub mesh: ProcessMesh,
187 /// Per-vertex UV coordinates in \[0,1\]².
188 pub uvs: Vec<Uv>,
189}
190/// A rectangular texture patch cut from the atlas.
191#[derive(Debug, Clone)]
192pub struct AtlasPatch {
193 /// Index of the original face group.
194 pub group_id: usize,
195 /// UV bounding box: \[umin, vmin, umax, vmax\].
196 pub bounds: [f64; 4],
197 /// Vertices (UVs) of the patch in atlas space.
198 pub uvs: Vec<Uv>,
199}
200/// Result of a boolean mesh operation.
201#[derive(Debug, Clone)]
202pub struct BooleanResult {
203 /// The combined / intersected / subtracted mesh.
204 pub mesh: ProcessMesh,
205 /// Whether the operation was exact (currently always false for this stub).
206 pub is_exact: bool,
207}