pub(crate) mod analyse;
pub(crate) mod arc_joint;
pub(crate) mod assemble;
pub(crate) mod data;
pub mod error;
pub(crate) mod inter2d;
pub(crate) mod inter3d;
pub(crate) mod loops;
pub(crate) mod offset;
pub(crate) mod self_int;
pub use data::{JointType, OffsetOptions};
pub use error::OffsetError;
use brepkit_topology::Topology;
use brepkit_topology::face::FaceId;
use brepkit_topology::solid::SolidId;
use crate::data::OffsetData;
pub fn offset_solid(
topo: &mut Topology,
solid: SolidId,
distance: f64,
options: OffsetOptions,
) -> Result<SolidId, OffsetError> {
thick_solid(topo, solid, distance, &[], options)
}
#[allow(clippy::too_many_lines)]
pub fn thick_solid(
topo: &mut Topology,
solid: SolidId,
distance: f64,
exclude: &[FaceId],
options: OffsetOptions,
) -> Result<SolidId, OffsetError> {
if !distance.is_finite() || distance.abs() < options.tolerance.linear {
return Err(OffsetError::InvalidInput {
reason: "offset distance must be non-zero and finite".into(),
});
}
let mut data = OffsetData::new(distance, options, exclude.to_vec());
analyse::analyse_edges(topo, solid, &mut data)?;
offset::build_offset_faces(topo, solid, &mut data)?;
inter3d::intersect_faces_3d(topo, solid, &mut data)?;
inter2d::intersect_pcurves_2d(topo, solid, &mut data)?;
if data.options.joint == JointType::Arc {
arc_joint::build_arc_joints(topo, &mut data)?;
}
loops::build_wire_loops(topo, &mut data)?;
let result = assemble::assemble_solid(topo, &data)?;
if data.options.remove_self_intersections {
return self_int::remove_self_intersections(topo, result);
}
Ok(result)
}