Skip to main content

ifc_lite_processing/types/
response.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Shared response types for the IFC processing API.
6
7use super::mesh::MeshData;
8use crate::georeferencing::Georeferencing;
9use crate::symbolic::SymbolicData;
10use serde::{Deserialize, Serialize};
11
12/// Full parse response with all meshes.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct ParseResponse {
15    /// Cache key for this result (SHA256 of file content).
16    pub cache_key: String,
17    /// All meshes extracted from the IFC file.
18    pub meshes: Vec<MeshData>,
19    /// Declares the coordinate space used by serialized mesh vertices:
20    /// * `site_local` — vertices are relative to the IfcSite placement
21    ///   translation (small floats in a meaningful, relatable frame).
22    /// * `model_rtc`  — a model-level detected RTC anchor was subtracted.
23    /// * `raw_ifc`    — no RTC anchor was applied; vertices are in raw IFC space.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub mesh_coordinate_space: Option<String>,
26    /// IfcSite ObjectPlacement as a column-major 4x4 matrix (16 f64 values, in meters).
27    /// Used by clients to relocate geometry between global and site-local coordinate systems.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub site_transform: Option<Vec<f64>>,
30    /// IfcBuilding ObjectPlacement as a column-major 4x4 matrix (16 f64 values, in meters).
31    /// Used by clients to relocate geometry between global and building-local coordinate systems.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub building_transform: Option<Vec<f64>>,
34    /// Model metadata.
35    pub metadata: ModelMetadata,
36    /// Processing statistics.
37    pub stats: ProcessingStats,
38    /// 2D symbol data extracted from `IfcAnnotation` and `IfcGrid`
39    /// entities. Always emitted (potentially empty); see issue #843 for
40    /// the parity rationale with the browser-side parser.
41    #[serde(default, skip_serializing_if = "SymbolicData::is_empty")]
42    pub symbolic_data: SymbolicData,
43}
44
45/// Model metadata extracted from the IFC file.
46#[derive(Debug, Clone, Default, Serialize, Deserialize)]
47pub struct ModelMetadata {
48    /// IFC schema version (e.g., "IFC2X3", "IFC4", "IFC4X3").
49    pub schema_version: String,
50    /// Total number of entities in the file.
51    pub entity_count: usize,
52    /// Number of geometry-bearing entities.
53    pub geometry_entity_count: usize,
54    /// Coordinate system information.
55    pub coordinate_info: CoordinateInfo,
56    /// Length unit scale to convert model length values to metres (e.g. `0.001`
57    /// for millimetres). `None` when not yet computed; consumers treat it as
58    /// `1.0`. Brings the server to parity with the browser parser's
59    /// `extractLengthUnitScale` (issue #900).
60    #[serde(default, skip_serializing_if = "Option::is_none")]
61    pub length_unit_scale: Option<f64>,
62    /// Georeferencing (`IfcMapConversion` + `IfcProjectedCRS`). `None` when the
63    /// model carries no map-conversion data. Mirrors the browser parser's
64    /// `extractGeoreferencing` (issue #900).
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub georeferencing: Option<Georeferencing>,
67}
68
69/// Coordinate system information.
70#[derive(Debug, Clone, Default, Serialize, Deserialize)]
71pub struct CoordinateInfo {
72    /// Origin shift applied to coordinates (for RTC rendering).
73    pub origin_shift: [f64; 3],
74    /// Whether the model is geo-referenced.
75    pub is_geo_referenced: bool,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct QuickMetadataEntitySummary {
80    pub express_id: u32,
81    pub type_name: String,
82    pub name: String,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub global_id: Option<String>,
85    pub kind: String,
86    pub has_children: bool,
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub element_count: Option<usize>,
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub elevation: Option<f64>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct QuickMetadataSpatialNode {
95    #[serde(flatten)]
96    pub summary: QuickMetadataEntitySummary,
97    pub children: Vec<QuickMetadataSpatialNode>,
98    pub elements: Vec<QuickMetadataEntitySummary>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct QuickMetadataBootstrap {
103    pub schema_version: String,
104    pub entity_count: usize,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub spatial_tree: Option<QuickMetadataSpatialNode>,
107}
108
109/// Processing statistics.
110#[derive(Debug, Clone, Default, Serialize, Deserialize)]
111pub struct ProcessingStats {
112    /// Total number of meshes generated.
113    pub total_meshes: usize,
114    /// Total number of vertices.
115    pub total_vertices: usize,
116    /// Total number of triangles.
117    pub total_triangles: usize,
118    /// Time spent parsing entities (ms).
119    pub parse_time_ms: u64,
120    /// Time spent scanning entities and building initial job lists (ms).
121    pub entity_scan_time_ms: u64,
122    /// Time spent resolving lookups, styles, and optional metadata (ms).
123    pub lookup_time_ms: u64,
124    /// Time spent in geometry preprocessing before the extraction loop begins (ms).
125    pub preprocess_time_ms: u64,
126    /// Time spent processing geometry (ms).
127    pub geometry_time_ms: u64,
128    /// Total processing time (ms).
129    pub total_time_ms: u64,
130    /// Whether result was from cache.
131    pub from_cache: bool,
132    /// Total CSG boolean failures recorded during geometry extraction
133    /// (mirrors the browser console diagnostics — see `BoolFailureReason`).
134    #[serde(default)]
135    pub total_csg_failures: u64,
136    /// Number of distinct products with at least one CSG failure.
137    #[serde(default)]
138    pub products_with_failures: u64,
139}