fj_operations/
shape_processor.rs

1//! API for processing shapes
2
3use 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
16/// Processes an [`fj::Shape`] into a [`ProcessedShape`]
17pub struct ShapeProcessor {
18    /// The tolerance value used for creating the triangle mesh
19    pub tolerance: Option<Tolerance>,
20}
21
22impl ShapeProcessor {
23    /// Process an [`fj::Shape`] into [`ProcessedShape`]
24    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                // Compute a reasonable default for the tolerance value. To do
30                // this, we just look at the smallest non-zero extent of the
31                // bounding box and divide that by some value.
32                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/// A shape processing error
59#[derive(Debug, thiserror::Error)]
60pub enum Error {
61    /// Error converting to shape
62    #[error("Error converting to shape")]
63    ToShape(#[from] Box<ValidationError>),
64
65    /// Model has zero size
66    #[error("Model has zero size")]
67    Extent(#[from] InvalidTolerance),
68}