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