ifc_lite_geometry/router/
mod.rs1mod caching;
10mod clipping;
11mod layers;
12mod processing;
13mod transforms;
14mod voids;
15mod voids_2d;
16
17#[cfg(test)]
18mod tests;
19
20use crate::material_layer_index::MaterialLayerIndex;
21use crate::processors::{
22 AdvancedBrepProcessor, BooleanClippingProcessor, ExtrudedAreaSolidProcessor,
23 FaceBasedSurfaceModelProcessor, FacetedBrepProcessor, MappedItemProcessor,
24 PolygonalFaceSetProcessor, RevolvedAreaSolidProcessor, ShellBasedSurfaceModelProcessor,
25 SweptDiskSolidProcessor, TriangulatedFaceSetProcessor,
26};
27use crate::{Mesh, Result};
28use ifc_lite_core::{DecodedEntity, EntityDecoder, IfcSchema, IfcType};
29use nalgebra::Matrix4;
30use rustc_hash::FxHashMap;
31use std::cell::RefCell;
32use std::collections::HashMap;
33use std::sync::Arc;
34
35pub trait GeometryProcessor {
38 fn process(
40 &self,
41 entity: &DecodedEntity,
42 decoder: &mut EntityDecoder,
43 schema: &IfcSchema,
44 ) -> Result<Mesh>;
45
46 fn supported_types(&self) -> Vec<IfcType>;
48}
49
50pub struct GeometryRouter {
52 schema: IfcSchema,
53 processors: HashMap<IfcType, Arc<dyn GeometryProcessor>>,
54 mapped_item_cache: RefCell<FxHashMap<u32, Arc<Mesh>>>,
57 faceted_brep_cache: RefCell<FxHashMap<u32, Mesh>>,
61 geometry_hash_cache: RefCell<FxHashMap<u64, Arc<Mesh>>>,
65 unit_scale: f64,
68 rtc_offset: (f64, f64, f64),
72 material_layer_index: Option<Arc<MaterialLayerIndex>>,
76}
77
78impl GeometryRouter {
79 pub fn new() -> Self {
81 let schema = IfcSchema::new();
82 let schema_clone = schema.clone();
83 let mut router = Self {
84 schema,
85 processors: HashMap::new(),
86 mapped_item_cache: RefCell::new(FxHashMap::default()),
87 faceted_brep_cache: RefCell::new(FxHashMap::default()),
88 geometry_hash_cache: RefCell::new(FxHashMap::default()),
89 unit_scale: 1.0, rtc_offset: (0.0, 0.0, 0.0), material_layer_index: None,
92 };
93
94 router.register(Box::new(ExtrudedAreaSolidProcessor::new(
96 schema_clone.clone(),
97 )));
98 router.register(Box::new(TriangulatedFaceSetProcessor::new()));
99 router.register(Box::new(PolygonalFaceSetProcessor::new()));
100 router.register(Box::new(MappedItemProcessor::new()));
101 router.register(Box::new(FacetedBrepProcessor::new()));
102 router.register(Box::new(BooleanClippingProcessor::new()));
103 router.register(Box::new(SweptDiskSolidProcessor::new(schema_clone.clone())));
104 router.register(Box::new(RevolvedAreaSolidProcessor::new(
105 schema_clone.clone(),
106 )));
107 router.register(Box::new(AdvancedBrepProcessor::new()));
108 router.register(Box::new(ShellBasedSurfaceModelProcessor::new()));
109 router.register(Box::new(FaceBasedSurfaceModelProcessor::new()));
110
111 router
112 }
113
114 pub fn with_units(content: &str, decoder: &mut EntityDecoder) -> Self {
117 let mut scanner = ifc_lite_core::EntityScanner::new(content);
118 let mut scale = 1.0;
119
120 while let Some((id, type_name, _, _)) = scanner.next_entity() {
122 if type_name == "IFCPROJECT" {
123 if let Ok(s) = ifc_lite_core::extract_length_unit_scale(decoder, id) {
124 scale = s;
125 }
126 break;
127 }
128 }
129
130 Self::with_scale(scale)
131 }
132
133 pub fn with_units_and_rtc(
141 content: &str,
142 decoder: &mut ifc_lite_core::EntityDecoder,
143 rtc_offset: (f64, f64, f64),
144 ) -> Self {
145 let mut scanner = ifc_lite_core::EntityScanner::new(content);
146 let mut scale = 1.0;
147
148 while let Some((id, type_name, _, _)) = scanner.next_entity() {
150 if type_name == "IFCPROJECT" {
151 if let Ok(s) = ifc_lite_core::extract_length_unit_scale(decoder, id) {
152 scale = s;
153 }
154 break;
155 }
156 }
157
158 Self::with_scale_and_rtc(scale, rtc_offset)
159 }
160
161 pub fn with_scale(unit_scale: f64) -> Self {
163 let mut router = Self::new();
164 router.unit_scale = unit_scale;
165 router
166 }
167
168 pub fn with_rtc(rtc_offset: (f64, f64, f64)) -> Self {
171 let mut router = Self::new();
172 router.rtc_offset = rtc_offset;
173 router
174 }
175
176 pub fn with_scale_and_rtc(unit_scale: f64, rtc_offset: (f64, f64, f64)) -> Self {
178 let mut router = Self::new();
179 router.unit_scale = unit_scale;
180 router.rtc_offset = rtc_offset;
181 router
182 }
183
184 pub fn set_rtc_offset(&mut self, offset: (f64, f64, f64)) {
186 self.rtc_offset = offset;
187 }
188
189 pub fn rtc_offset(&self) -> (f64, f64, f64) {
191 self.rtc_offset
192 }
193
194 #[inline]
196 pub fn has_rtc_offset(&self) -> bool {
197 self.rtc_offset.0 != 0.0 || self.rtc_offset.1 != 0.0 || self.rtc_offset.2 != 0.0
198 }
199
200 pub fn unit_scale(&self) -> f64 {
202 self.unit_scale
203 }
204
205 pub fn set_material_layer_index(&mut self, index: Arc<MaterialLayerIndex>) {
209 self.material_layer_index = Some(index);
210 }
211
212 #[inline]
213 pub(crate) fn material_layer_index(&self) -> Option<&MaterialLayerIndex> {
214 self.material_layer_index.as_deref()
215 }
216
217 #[inline]
220 fn scale_mesh(&self, mesh: &mut Mesh) {
221 if self.unit_scale != 1.0 {
222 let scale = self.unit_scale as f32;
223 for pos in mesh.positions.iter_mut() {
224 *pos *= scale;
225 }
226 }
227 }
228
229 #[inline]
232 fn scale_transform(&self, transform: &mut Matrix4<f64>) {
233 if self.unit_scale != 1.0 {
234 transform[(0, 3)] *= self.unit_scale;
235 transform[(1, 3)] *= self.unit_scale;
236 transform[(2, 3)] *= self.unit_scale;
237 }
238 }
239
240 pub fn register(&mut self, processor: Box<dyn GeometryProcessor>) {
242 let processor_arc: Arc<dyn GeometryProcessor> = Arc::from(processor);
243 for ifc_type in processor_arc.supported_types() {
244 self.processors.insert(ifc_type, Arc::clone(&processor_arc));
245 }
246 }
247
248 pub fn preprocess_faceted_breps(&self, brep_ids: &[u32], decoder: &mut EntityDecoder) {
252 if brep_ids.is_empty() {
253 return;
254 }
255
256 let processor = FacetedBrepProcessor::new();
260 let rtc_file_units = (
261 self.rtc_offset.0 / self.unit_scale,
262 self.rtc_offset.1 / self.unit_scale,
263 self.rtc_offset.2 / self.unit_scale,
264 );
265 let large_coord_threshold_file_units = 10000.0 / self.unit_scale;
266 let results = processor.process_batch(
267 brep_ids,
268 decoder,
269 rtc_file_units,
270 large_coord_threshold_file_units,
271 );
272
273 let mut cache = self.faceted_brep_cache.borrow_mut();
275 cache.reserve(results.len());
276 for (brep_idx, mesh) in results {
277 let brep_id = brep_ids[brep_idx];
278 cache.insert(brep_id, mesh);
279 }
280 }
281
282 #[inline]
285 pub fn take_cached_faceted_brep(&self, brep_id: u32) -> Option<Mesh> {
286 self.faceted_brep_cache.borrow_mut().remove(&brep_id)
287 }
288
289 pub fn resolve_scaled_placement(
295 &self,
296 entity: &DecodedEntity,
297 decoder: &mut EntityDecoder,
298 ) -> Result<[f64; 16]> {
299 let mut transform = self.get_placement_transform_from_element(entity, decoder)?;
300 self.scale_transform(&mut transform);
301 let mut result = [0.0f64; 16];
302 result.copy_from_slice(transform.as_slice());
303 Ok(result)
304 }
305
306 pub fn schema(&self) -> &IfcSchema {
308 &self.schema
309 }
310}
311
312impl Default for GeometryRouter {
313 fn default() -> Self {
314 Self::new()
315 }
316}