ifc_lite_geometry/router/
mod.rs1mod caching;
10mod clipping;
11mod processing;
12mod transforms;
13mod voids;
14mod voids_2d;
15
16#[cfg(test)]
17mod tests;
18
19use crate::processors::{
20 AdvancedBrepProcessor, BooleanClippingProcessor, ExtrudedAreaSolidProcessor,
21 FaceBasedSurfaceModelProcessor, FacetedBrepProcessor, MappedItemProcessor,
22 PolygonalFaceSetProcessor, RevolvedAreaSolidProcessor, ShellBasedSurfaceModelProcessor,
23 SweptDiskSolidProcessor, TriangulatedFaceSetProcessor,
24};
25use crate::{Mesh, Result};
26use ifc_lite_core::{DecodedEntity, EntityDecoder, IfcSchema, IfcType};
27use nalgebra::Matrix4;
28use rustc_hash::FxHashMap;
29use std::cell::RefCell;
30use std::collections::HashMap;
31use std::sync::Arc;
32
33pub trait GeometryProcessor {
36 fn process(
38 &self,
39 entity: &DecodedEntity,
40 decoder: &mut EntityDecoder,
41 schema: &IfcSchema,
42 ) -> Result<Mesh>;
43
44 fn supported_types(&self) -> Vec<IfcType>;
46}
47
48pub struct GeometryRouter {
50 schema: IfcSchema,
51 processors: HashMap<IfcType, Arc<dyn GeometryProcessor>>,
52 mapped_item_cache: RefCell<FxHashMap<u32, Arc<Mesh>>>,
55 faceted_brep_cache: RefCell<FxHashMap<u32, Mesh>>,
59 geometry_hash_cache: RefCell<FxHashMap<u64, Arc<Mesh>>>,
63 unit_scale: f64,
66 rtc_offset: (f64, f64, f64),
70}
71
72impl GeometryRouter {
73 pub fn new() -> Self {
75 let schema = IfcSchema::new();
76 let schema_clone = schema.clone();
77 let mut router = Self {
78 schema,
79 processors: HashMap::new(),
80 mapped_item_cache: RefCell::new(FxHashMap::default()),
81 faceted_brep_cache: RefCell::new(FxHashMap::default()),
82 geometry_hash_cache: RefCell::new(FxHashMap::default()),
83 unit_scale: 1.0, rtc_offset: (0.0, 0.0, 0.0), };
86
87 router.register(Box::new(ExtrudedAreaSolidProcessor::new(
89 schema_clone.clone(),
90 )));
91 router.register(Box::new(TriangulatedFaceSetProcessor::new()));
92 router.register(Box::new(PolygonalFaceSetProcessor::new()));
93 router.register(Box::new(MappedItemProcessor::new()));
94 router.register(Box::new(FacetedBrepProcessor::new()));
95 router.register(Box::new(BooleanClippingProcessor::new()));
96 router.register(Box::new(SweptDiskSolidProcessor::new(schema_clone.clone())));
97 router.register(Box::new(RevolvedAreaSolidProcessor::new(
98 schema_clone.clone(),
99 )));
100 router.register(Box::new(AdvancedBrepProcessor::new()));
101 router.register(Box::new(ShellBasedSurfaceModelProcessor::new()));
102 router.register(Box::new(FaceBasedSurfaceModelProcessor::new()));
103
104 router
105 }
106
107 pub fn with_units(content: &str, decoder: &mut EntityDecoder) -> Self {
110 let mut scanner = ifc_lite_core::EntityScanner::new(content);
111 let mut scale = 1.0;
112
113 while let Some((id, type_name, _, _)) = scanner.next_entity() {
115 if type_name == "IFCPROJECT" {
116 if let Ok(s) = ifc_lite_core::extract_length_unit_scale(decoder, id) {
117 scale = s;
118 }
119 break;
120 }
121 }
122
123 Self::with_scale(scale)
124 }
125
126 pub fn with_units_and_rtc(
134 content: &str,
135 decoder: &mut ifc_lite_core::EntityDecoder,
136 rtc_offset: (f64, f64, f64),
137 ) -> Self {
138 let mut scanner = ifc_lite_core::EntityScanner::new(content);
139 let mut scale = 1.0;
140
141 while let Some((id, type_name, _, _)) = scanner.next_entity() {
143 if type_name == "IFCPROJECT" {
144 if let Ok(s) = ifc_lite_core::extract_length_unit_scale(decoder, id) {
145 scale = s;
146 }
147 break;
148 }
149 }
150
151 Self::with_scale_and_rtc(scale, rtc_offset)
152 }
153
154 pub fn with_scale(unit_scale: f64) -> Self {
156 let mut router = Self::new();
157 router.unit_scale = unit_scale;
158 router
159 }
160
161 pub fn with_rtc(rtc_offset: (f64, f64, f64)) -> Self {
164 let mut router = Self::new();
165 router.rtc_offset = rtc_offset;
166 router
167 }
168
169 pub fn with_scale_and_rtc(unit_scale: f64, rtc_offset: (f64, f64, f64)) -> Self {
171 let mut router = Self::new();
172 router.unit_scale = unit_scale;
173 router.rtc_offset = rtc_offset;
174 router
175 }
176
177 pub fn set_rtc_offset(&mut self, offset: (f64, f64, f64)) {
179 self.rtc_offset = offset;
180 }
181
182 pub fn rtc_offset(&self) -> (f64, f64, f64) {
184 self.rtc_offset
185 }
186
187 #[inline]
189 pub fn has_rtc_offset(&self) -> bool {
190 self.rtc_offset.0 != 0.0 || self.rtc_offset.1 != 0.0 || self.rtc_offset.2 != 0.0
191 }
192
193 pub fn unit_scale(&self) -> f64 {
195 self.unit_scale
196 }
197
198 #[inline]
201 fn scale_mesh(&self, mesh: &mut Mesh) {
202 if self.unit_scale != 1.0 {
203 let scale = self.unit_scale as f32;
204 for pos in mesh.positions.iter_mut() {
205 *pos *= scale;
206 }
207 }
208 }
209
210 #[inline]
213 fn scale_transform(&self, transform: &mut Matrix4<f64>) {
214 if self.unit_scale != 1.0 {
215 transform[(0, 3)] *= self.unit_scale;
216 transform[(1, 3)] *= self.unit_scale;
217 transform[(2, 3)] *= self.unit_scale;
218 }
219 }
220
221 pub fn register(&mut self, processor: Box<dyn GeometryProcessor>) {
223 let processor_arc: Arc<dyn GeometryProcessor> = Arc::from(processor);
224 for ifc_type in processor_arc.supported_types() {
225 self.processors.insert(ifc_type, Arc::clone(&processor_arc));
226 }
227 }
228
229 pub fn preprocess_faceted_breps(&self, brep_ids: &[u32], decoder: &mut EntityDecoder) {
233 if brep_ids.is_empty() {
234 return;
235 }
236
237 let processor = FacetedBrepProcessor::new();
239 let results = processor.process_batch(brep_ids, decoder);
240
241 let mut cache = self.faceted_brep_cache.borrow_mut();
243 cache.reserve(results.len());
244 for (brep_idx, mesh) in results {
245 let brep_id = brep_ids[brep_idx];
246 cache.insert(brep_id, mesh);
247 }
248 }
249
250 #[inline]
253 pub fn take_cached_faceted_brep(&self, brep_id: u32) -> Option<Mesh> {
254 self.faceted_brep_cache.borrow_mut().remove(&brep_id)
255 }
256
257 pub fn schema(&self) -> &IfcSchema {
259 &self.schema
260 }
261}
262
263impl Default for GeometryRouter {
264 fn default() -> Self {
265 Self::new()
266 }
267}