solidcraft-smlib: face sections as SMLib's B-splines

Brep::face_section (smlib_face_section: one face cut by a plane) hands back
the NURBS SMLib made with their intervals, through one reader of smlib_curves
(take_curves) shared with project_curves. The face-pick errors map to
NoMatch/Ambiguous in one place (picked). SMLIB_REV at fork eedfa51.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
This commit is contained in:
jyviko
2026-10-22 07:29:27 -04:00
parent 814475f4f3
commit d803285955
3 changed files with 65 additions and 8 deletions
+1 -1
View File
@@ -1 +1 @@
9dcfcd6f581eff5d37a038910fdc5296f8354743
eedfa514371f80697c66472b40bda7d0e30146f5
+39 -2
View File
@@ -1,5 +1,5 @@
//! The sweeps block of `capi/include/smlib.h` (`smlib_extrude`, `smlib_revolve`, `smlib_sweep`,
//! `smlib_sweep_placed`, `smlib_project_curves` (with `smlib_curves_*`), `smlib_loft`, `smlib_loft_to_point`, `smlib_screw_sweep`,
//! `smlib_sweep_placed`, `smlib_project_curves`, `smlib_face_section` (with `smlib_curves_*`), `smlib_loft`, `smlib_loft_to_point`, `smlib_screw_sweep`,
//! `smlib_sweep_stations`, `smlib_planar_faces`; the fork's
//! `capi/src/smlib_sweeps.cpp`), declared by hand.
//! Part of the FFI boundary, like its parent: called only through [`crate::sweeps`], which builds
@@ -117,6 +117,15 @@ unsafe extern "C" {
tolerance: f64,
out: *mut *mut RawCurves,
) -> i32;
fn smlib_face_section(
brep: *const RawBrep,
face_point: *const f64,
pick_tolerance: f64,
plane_point: *const f64,
plane_normal: *const f64,
tolerance: f64,
out: *mut *mut RawCurves,
) -> i32;
fn smlib_curves_size(curves: *const RawCurves, n_kinds: *mut i64, n_reals: *mut i64, n_curves: *mut i64) -> i32;
fn smlib_curves_read(
curves: *const RawCurves,
@@ -234,8 +243,31 @@ pub fn project_curves(
tolerance: f64,
) -> Result<OutCurves, i32> {
let (k, nk, r, nr) = raw(curves)?;
take_curves(|out| unsafe {
smlib_project_curves(brep.raw(), face_point.as_ptr(), pick_tolerance, k, nk, r, nr, direction.as_ptr(), tolerance, out)
})
}
/// `smlib_face_section`: the face of `brep` at `face_point` cut by a plane.
#[cfg(feature = "native")]
pub fn face_section(
brep: &Handle,
face_point: &[f64; 3],
pick_tolerance: f64,
plane_point: &[f64; 3],
plane_normal: &[f64; 3],
tolerance: f64,
) -> Result<OutCurves, i32> {
take_curves(|out| unsafe {
smlib_face_section(brep.raw(), face_point.as_ptr(), pick_tolerance, plane_point.as_ptr(), plane_normal.as_ptr(), tolerance, out)
})
}
/// Runs a call that makes an `smlib_curves`, reads it out and frees it.
#[cfg(feature = "native")]
fn take_curves(call: impl FnOnce(*mut *mut RawCurves) -> i32) -> Result<OutCurves, i32> {
let mut out: *mut RawCurves = std::ptr::null_mut();
let s = unsafe { smlib_project_curves(brep.raw(), face_point.as_ptr(), pick_tolerance, k, nk, r, nr, direction.as_ptr(), tolerance, &mut out) };
let s = call(&mut out);
if s != super::OK {
return Err(s);
}
@@ -322,6 +354,11 @@ pub fn project_curves(_: &Handle, _: &[f64; 3], _: f64, _: &List, _: &[f64; 3],
Err(NOT_BUILT)
}
#[cfg(not(feature = "native"))]
pub fn face_section(_: &Handle, _: &[f64; 3], _: f64, _: &[f64; 3], _: &[f64; 3], _: f64) -> Result<OutCurves, i32> {
Err(NOT_BUILT)
}
#[cfg(not(feature = "native"))]
pub fn loft(_: &List, _: &[i64], _: i32, _: bool) -> Result<Handle, i32> {
Err(NOT_BUILT)
+25 -5
View File
@@ -204,11 +204,22 @@ impl Brep {
) -> Result<Vec<(Curve, [f64; 2])>> {
init()?;
let l = List::of(curves)?;
let out = ffi::sweeps::project_curves(&self.0, &face_point, pick_tolerance, &l.raw(), &direction, tolerance).map_err(|s| match s {
ffi::ops::ERR_PICK_NONE => Error::NoMatch { point: 0 },
ffi::ops::ERR_PICK_AMBIGUOUS => Error::Ambiguous { point: 0 },
s => error(s),
})?;
let out = ffi::sweeps::project_curves(&self.0, &face_point, pick_tolerance, &l.raw(), &direction, tolerance).map_err(picked)?;
nurbs_list(&out)
}
/// The section of the face nearest `face_point` by the plane through `plane_point` square to
/// `plane_normal`, as the NURBS SMLib made with their intervals. None is [`Error::Empty`].
pub fn face_section(
&self,
face_point: [f64; 3],
pick_tolerance: f64,
plane_point: [f64; 3],
plane_normal: [f64; 3],
tolerance: f64,
) -> Result<Vec<(Curve, [f64; 2])>> {
init()?;
let out = ffi::sweeps::face_section(&self.0, &face_point, pick_tolerance, &plane_point, &plane_normal, tolerance).map_err(picked)?;
nurbs_list(&out)
}
@@ -261,6 +272,15 @@ impl Brep {
}
}
/// The error of a call that picks faces by points.
fn picked(s: i32) -> Error {
match s {
ffi::ops::ERR_PICK_NONE => Error::NoMatch { point: 0 },
ffi::ops::ERR_PICK_AMBIGUOUS => Error::Ambiguous { point: 0 },
s => error(s),
}
}
/// The NURBS curves of a curve list the C API made, each with its interval.
fn nurbs_list(out: &ffi::sweeps::OutCurves) -> Result<Vec<(Curve, [f64; 2])>> {
let (mut k, mut r) = (0usize, 0usize);