diff --git a/crates/smlib/src/ffi/measure.rs b/crates/smlib/src/ffi/measure.rs index 2761b2458f..7c90fd2d96 100644 --- a/crates/smlib/src/ffi/measure.rs +++ b/crates/smlib/src/ffi/measure.rs @@ -1,4 +1,5 @@ -//! `smlib_brep_mass_properties`, `smlib_brep_area` and `smlib_brep_bounds` (the fork's `capi/src/smlib_measure.cpp`), declared by +//! `smlib_brep_mass_properties`, `smlib_brep_area`, `smlib_brep_bounds` and +//! `smlib_brep_edge_face_distance` (the fork's `capi/src/smlib_measure.cpp`), declared by //! hand. Part of the FFI boundary, like its parent: called only through [`crate::measure`]. #![allow(unsafe_code)] @@ -14,6 +15,7 @@ unsafe extern "C" { pub fn smlib_brep_mass_properties(brep: *const RawBrep, relative_accuracy: f64, out: *mut f64) -> i32; pub fn smlib_brep_area(brep: *const RawBrep, relative_accuracy: f64, out: *mut f64) -> i32; pub fn smlib_brep_bounds(brep: *const RawBrep, lo: *mut f64, hi: *mut f64) -> i32; + pub fn smlib_brep_edge_face_distance(brep: *const RawBrep, edge: i64, face: i64, out: *mut f64) -> i32; } #[cfg(feature = "native")] @@ -43,6 +45,20 @@ pub fn bounds(b: &Handle) -> Result<([f64; 3], [f64; 3]), i32> { } } +#[cfg(feature = "native")] +pub fn edge_face_distance(b: &Handle, edge: i64, face: i64) -> Result { + let mut d = 0.0; + match unsafe { smlib_brep_edge_face_distance(b.raw(), edge, face, &mut d) } { + OK => Ok(d), + s => Err(s), + } +} + +#[cfg(not(feature = "native"))] +pub fn edge_face_distance(_: &Handle, _: i64, _: i64) -> Result { + Err(NOT_BUILT) +} + #[cfg(not(feature = "native"))] pub fn bounds(_: &Handle) -> Result<([f64; 3], [f64; 3]), i32> { Err(NOT_BUILT) diff --git a/crates/smlib/src/measure.rs b/crates/smlib/src/measure.rs index f44d4c655a..ec470c9671 100644 --- a/crates/smlib/src/measure.rs +++ b/crates/smlib/src/measure.rs @@ -1,5 +1,5 @@ //! Exact mass properties from SMLib: area, volume, centroid and inertia, integrated on the exact -//! surfaces rather than a tessellation, and the exact box. +//! surfaces rather than a tessellation; the exact box; how far an edge lies from a face's surface. use crate::{Brep, Result, error, ffi}; @@ -48,6 +48,17 @@ impl Brep { ffi::measure::bounds(&self.0).map_err(error) } + /// How far edge `edge` (its curve over its interval) lies from the surface of face `face`, + /// over that surface's own domain and not beyond it, in mm: SMLib's own edge/face gap, the + /// one it sizes an edge's tolerance by. Indices are in the body's edge and face order (as + /// it was imported and is exported). An edge run past its face's patch measures how far it + /// goes; SMLib keeps such an edge whole when making its UV trim only when its zone tolerance + /// (half the flat arrays' `EDGE_TOLERANCE`) covers this. + pub fn edge_face_distance(&self, edge: usize, face: usize) -> Result { + let (Ok(e), Ok(f)) = (i64::try_from(edge), i64::try_from(face)) else { return Err(error(ffi::ERR_ARG)) }; + ffi::measure::edge_face_distance(&self.0, e, f).map_err(error) + } + /// Total area of every face, each counted once, so sheets and open shells too. pub fn area(&self, relative_accuracy: f64) -> Result { ffi::measure::area(&self.0, relative_accuracy).map_err(error)