lib3mf_core/model/
core.rs

1use super::units::Unit;
2use crate::model::{Build, ResourceCollection};
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Root element of a 3MF document.
7///
8/// The `Model` contains all information required to describe a 3D model, including:
9/// - Resources (Meshes, Materials, Textures)
10/// - Build instructions (Item positioning)
11/// - Metadata (Authors, Copyright, etc.)
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Model {
14    /// The unit of measurement for geometry coordinates.
15    #[serde(default)]
16    pub unit: Unit,
17
18    /// The language of the model content (e.g., "en-US").
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub language: Option<String>,
21
22    /// Arbitrary metadata key-value pairs.
23    #[serde(default)]
24    pub metadata: HashMap<String, String>,
25
26    /// Collection of all resources (objects, materials) used in the build.
27    #[serde(default)]
28    pub resources: ResourceCollection,
29
30    /// The build definition, containing instances of objects to be printed.
31    #[serde(default)]
32    pub build: Build,
33
34    /// Binary attachments (Textures, Thumbnails, etc.) stored by package path.
35    /// Key: Path in archive (e.g., "Metadata/thumbnail.png", "3D/Textures/diffuse.png")
36    /// Value: Binary content
37    #[serde(skip)]
38    pub attachments: HashMap<String, Vec<u8>>,
39
40    /// Existing OPC relationships loaded from the archive.
41    /// Key: Relationship file path (e.g., "3D/_rels/3dmodel.model.rels")
42    /// Value: Parsed relationships
43    #[serde(skip)]
44    pub existing_relationships: HashMap<String, Vec<crate::archive::opc::Relationship>>,
45}
46
47impl Model {
48    /// Validates the 3MF model at the specified validation level.
49    ///
50    /// The validation system is progressive, with four levels of increasing strictness:
51    ///
52    /// - **Minimal**: Basic structural checks (required attributes, valid XML structure)
53    /// - **Standard**: Reference integrity checks (resource IDs exist, build references valid objects)
54    /// - **Strict**: Full spec compliance (metadata presence, no unknown attributes)
55    /// - **Paranoid**: Deep geometry analysis (manifoldness, self-intersection, orientation consistency)
56    ///
57    /// # Parameters
58    ///
59    /// - `level`: The [`ValidationLevel`](crate::validation::ValidationLevel) to apply. Higher levels
60    ///   include all checks from lower levels.
61    ///
62    /// # Returns
63    ///
64    /// A [`ValidationReport`](crate::validation::ValidationReport) containing all errors, warnings,
65    /// and info messages found during validation. Check [`has_errors()`](crate::validation::ValidationReport::has_errors)
66    /// to determine if the model passed validation.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use lib3mf_core::{Model, validation::ValidationLevel};
72    ///
73    /// let model = Model::default();
74    ///
75    /// // Quick structural check
76    /// let report = model.validate(ValidationLevel::Minimal);
77    /// assert!(!report.has_errors());
78    ///
79    /// // Recommended for production use
80    /// let report = model.validate(ValidationLevel::Standard);
81    /// if report.has_errors() {
82    ///     for item in &report.items {
83    ///         eprintln!("Error: {}", item.message);
84    ///     }
85    /// }
86    ///
87    /// // Deep inspection (expensive, for critical applications)
88    /// let report = model.validate(ValidationLevel::Paranoid);
89    /// ```
90    ///
91    /// # Performance
92    ///
93    /// - **Minimal**: Very fast, suitable for quick checks
94    /// - **Standard**: Fast, recommended for most use cases
95    /// - **Strict**: Moderate, includes metadata and attribute checks
96    /// - **Paranoid**: Slow, performs O(n²) geometry checks with BVH acceleration
97    pub fn validate(
98        &self,
99        level: crate::validation::ValidationLevel,
100    ) -> crate::validation::ValidationReport {
101        use crate::validation::{ValidationLevel, displacement, geometry, schema, semantic};
102
103        let mut report = crate::validation::ValidationReport::new();
104
105        // Minimal: Schema validation (placeholders usually checked by parser, but explicit invariants here)
106        if level >= ValidationLevel::Minimal {
107            schema::validate_schema(self, &mut report);
108        }
109
110        // Standard: Semantic validation (integrity)
111        if level >= ValidationLevel::Standard {
112            semantic::validate_semantic(self, &mut report);
113        }
114
115        // All levels: Displacement validation (progressive checks)
116        displacement::validate_displacement(self, level, &mut report);
117
118        // Paranoid: Geometry validation
119        if level >= ValidationLevel::Paranoid {
120            geometry::validate_geometry(self, level, &mut report);
121        }
122
123        report
124    }
125}
126
127impl Default for Model {
128    fn default() -> Self {
129        Self {
130            unit: Unit::Millimeter,
131            language: None,
132            metadata: HashMap::new(),
133            resources: ResourceCollection::default(),
134            build: Build::default(),
135            attachments: HashMap::new(),
136            existing_relationships: HashMap::new(),
137        }
138    }
139}
140
141// Unit enum moved to definition in units.rs