fj_operations/
shape_processor.rs1use fj_interop::{debug::DebugInfo, processed_shape::ProcessedShape};
4use fj_kernel::{
5 algorithms::{
6 approx::{InvalidTolerance, Tolerance},
7 triangulate::Triangulate,
8 },
9 services::Services,
10 validate::ValidationError,
11};
12use fj_math::Scalar;
13
14use crate::Shape as _;
15
16pub struct ShapeProcessor {
18 pub tolerance: Option<Tolerance>,
20}
21
22impl ShapeProcessor {
23 pub fn process(&self, shape: &fj::Shape) -> Result<ProcessedShape, Error> {
25 let aabb = shape.bounding_volume();
26
27 let tolerance = match self.tolerance {
28 None => {
29 let mut min_extent = Scalar::MAX;
33 for extent in aabb.size().components {
34 if extent > Scalar::ZERO && extent < min_extent {
35 min_extent = extent;
36 }
37 }
38
39 let tolerance = min_extent / Scalar::from_f64(1000.);
40 Tolerance::from_scalar(tolerance)?
41 }
42 Some(user_defined_tolerance) => user_defined_tolerance,
43 };
44
45 let mut services = Services::new();
46 let mut debug_info = DebugInfo::new();
47 let shape = shape.compute_brep(&mut services, &mut debug_info);
48 let mesh = (&shape, tolerance).triangulate();
49
50 Ok(ProcessedShape {
51 aabb,
52 mesh,
53 debug_info,
54 })
55 }
56}
57
58#[derive(Debug, thiserror::Error)]
60pub enum Error {
61 #[error("Error converting to shape")]
63 ToShape(#[from] Box<ValidationError>),
64
65 #[error("Model has zero size")]
67 Extent(#[from] InvalidTolerance),
68}