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}