use fj_interop::{debug::DebugInfo, processed_shape::ProcessedShape};
use fj_kernel::{
algorithms::{
approx::{InvalidTolerance, Tolerance},
triangulate::Triangulate,
},
services::Services,
validate::ValidationError,
};
use fj_math::Scalar;
use crate::Shape as _;
pub struct ShapeProcessor {
pub tolerance: Option<Tolerance>,
}
impl ShapeProcessor {
pub fn process(&self, shape: &fj::Shape) -> Result<ProcessedShape, Error> {
let aabb = shape.bounding_volume();
let tolerance = match self.tolerance {
None => {
let mut min_extent = Scalar::MAX;
for extent in aabb.size().components {
if extent > Scalar::ZERO && extent < min_extent {
min_extent = extent;
}
}
let tolerance = min_extent / Scalar::from_f64(1000.);
Tolerance::from_scalar(tolerance)?
}
Some(user_defined_tolerance) => user_defined_tolerance,
};
let mut services = Services::new();
let mut debug_info = DebugInfo::new();
let shape = shape.compute_brep(&mut services.objects, &mut debug_info);
let mesh = (&shape, tolerance).triangulate();
Ok(ProcessedShape {
aabb,
mesh,
debug_info,
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Error converting to shape")]
ToShape(#[from] Box<ValidationError>),
#[error("Model has zero size")]
Extent(#[from] InvalidTolerance),
}