Skip to main content

runmat_geometry_core/
lib.rs

1//! Canonical geometry domain model for RunMat.
2
3pub mod diagnostics;
4pub mod model;
5pub mod selection;
6
7pub use diagnostics::{Diagnostic, DiagnosticSeverity};
8pub use model::{
9    AssemblyNode, CadColorEvidence, CadCurveEvaluationSample, CadCurveEvaluationSampleSource,
10    CadCurveEvaluator, CadEvaluatorSet, CadFaceEvaluationSample, CadFaceEvaluationSampleSource,
11    CadFaceEvaluator, CadLabelRef, CadPhysicalMaterialEvidence, CadRegionOwnership,
12    CadSemanticKind, EntityIdRange, GeometryAsset, GeometrySource, MaterialEvidence,
13    MaterialEvidenceConfidence, MeshDescriptor, MeshKind, Region, RegionEntityMapping,
14    SourceGeometry, SourceGeometryKind, SurfaceMesh, TessellationProfile, UnitSystem,
15};
16pub use selection::{EntityKind, EntityRef};
17
18#[cfg(test)]
19mod tests {
20    use super::*;
21
22    fn sample_asset() -> GeometryAsset {
23        GeometryAsset {
24            geometry_id: "geo_test".to_string(),
25            source: GeometrySource {
26                path: "/models/part.stl".to_string(),
27                sha256: "abc123".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                cad_evaluators: Vec::new(),
35            },
36            tessellation_profile: TessellationProfile::default(),
37            units: UnitSystem::Meter,
38            revision: 1,
39            meshes: vec![MeshDescriptor {
40                mesh_id: "mesh_1".to_string(),
41                kind: MeshKind::Surface,
42                vertex_count: 3,
43                element_count: 1,
44            }],
45            surface_meshes: vec![SurfaceMesh::new(
46                "mesh_1",
47                vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
48                vec![[0, 1, 2]],
49            )],
50            regions: vec![Region {
51                region_id: "region_a".to_string(),
52                name: "body".to_string(),
53                tag: None,
54                cad_ownership: None,
55            }],
56            region_entity_mappings: vec![RegionEntityMapping::all_faces("region_a", "mesh_1", 1)],
57            diagnostics: vec![],
58        }
59    }
60
61    #[test]
62    fn entity_identity_stable_within_revision() {
63        let first = EntityRef {
64            geometry_id: "geo_test".to_string(),
65            geometry_revision: 1,
66            mesh_id: "mesh_1".to_string(),
67            entity_kind: EntityKind::Face,
68            entity_id: 42,
69        };
70        let second = EntityRef { ..first.clone() };
71        assert_eq!(first, second);
72    }
73
74    #[test]
75    fn geometry_asset_round_trips_via_json() {
76        let asset = sample_asset();
77        let json = serde_json::to_string(&asset).expect("serialize");
78        let decoded: GeometryAsset = serde_json::from_str(&json).expect("deserialize");
79        assert_eq!(decoded, asset);
80    }
81
82    #[test]
83    fn unit_metadata_must_be_present() {
84        let mut asset = sample_asset();
85        asset.units = UnitSystem::Unspecified;
86        let error = asset
87            .validate()
88            .expect_err("expected unspecified units to fail");
89        assert_eq!(error, "geometry units must be specified");
90    }
91}