Skip to main content

runmat_geometry_ops/
lib.rs

1//! Pure geometry operations.
2
3pub mod bounds;
4pub mod quality;
5pub mod queries;
6pub mod stats;
7pub mod triangulation;
8
9pub use bounds::{compute_axis_aligned_bounds, AxisAlignedBounds};
10pub use quality::{evaluate_quality, QualityReport};
11pub use queries::{find_region, QueryError};
12pub use stats::{compute_stats, GeometryStats};
13pub use triangulation::{
14    boundary_edges, delaunay_2d, nearest_neighbor_indices, point_locations, Delaunay2d,
15    TriangulationError,
16};
17
18#[cfg(test)]
19mod tests {
20    use runmat_geometry_core::{
21        GeometryAsset, GeometrySource, MeshDescriptor, MeshKind, SourceGeometry,
22        SourceGeometryKind, SurfaceMesh, TessellationProfile, UnitSystem,
23    };
24
25    use crate::{compute_axis_aligned_bounds, compute_stats, evaluate_quality};
26
27    fn sample() -> GeometryAsset {
28        GeometryAsset {
29            geometry_id: "geo".to_string(),
30            source: GeometrySource {
31                path: "/x.stl".to_string(),
32                sha256: "hash".to_string(),
33                importer_version: "stl/v1".to_string(),
34            },
35            source_geometry: SourceGeometry {
36                kind: SourceGeometryKind::Mesh,
37                assembly: None,
38                material_evidence: vec![],
39                cad_evaluators: Vec::new(),
40            },
41            tessellation_profile: TessellationProfile::default(),
42            units: UnitSystem::Meter,
43            revision: 1,
44            meshes: vec![MeshDescriptor {
45                mesh_id: "mesh".to_string(),
46                kind: MeshKind::Surface,
47                vertex_count: 3,
48                element_count: 1,
49            }],
50            surface_meshes: vec![SurfaceMesh::new(
51                "mesh",
52                vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
53                vec![[0, 1, 2]],
54            )],
55            regions: vec![],
56            region_entity_mappings: vec![],
57            diagnostics: vec![],
58        }
59    }
60
61    #[test]
62    fn stats_are_computed() {
63        let stats = compute_stats(&sample());
64        assert_eq!(stats.mesh_count, 1);
65        assert_eq!(stats.total_vertices, 3);
66        assert_eq!(stats.total_elements, 1);
67    }
68
69    #[test]
70    fn bounds_are_deterministic() {
71        let bounds = compute_axis_aligned_bounds(&sample());
72        assert_eq!(bounds.min, [0.0, 0.0, 0.0]);
73        assert_eq!(bounds.max, [1.0, 1.0, 0.0]);
74    }
75
76    #[test]
77    fn quality_reports_units_warning_when_unspecified() {
78        let mut asset = sample();
79        asset.units = UnitSystem::Unspecified;
80        let report = evaluate_quality(&asset);
81        assert!(report
82            .warnings
83            .iter()
84            .any(|message| message.contains("units")));
85    }
86}