mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 10:35:58 +00:00
smlib: Brep::blend_setback, blends with corner setbacks (smlib_blend_setback)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//! The operations block of `capi/include/smlib.h` (`smlib_boolean`, `smlib_boolean_union_all`, `smlib_boolean2d`, `smlib_fillet`,
|
||||
//! `smlib_chamfer`, `smlib_blend`, `smlib_fillet_variable`, `smlib_chamfer_sides`, `smlib_shell`, `smlib_offset_faces`,
|
||||
//! `smlib_chamfer`, `smlib_blend`, `smlib_blend_setback`, `smlib_fillet_variable`, `smlib_chamfer_sides`, `smlib_shell`, `smlib_offset_faces`,
|
||||
//! `smlib_thicken`, `smlib_draft`, `smlib_merge_faces`, `smlib_brep_solid_count`, `smlib_imprint`; the fork's `capi/src/smlib_ops.cpp`), declared by
|
||||
//! hand. Part of the FFI boundary, like its parent: called only through
|
||||
//! [`crate::ops`].
|
||||
@@ -81,6 +81,20 @@ unsafe extern "C" {
|
||||
out: *mut *mut RawBrep,
|
||||
out_failed_point: *mut i64,
|
||||
) -> i32;
|
||||
fn smlib_blend_setback(
|
||||
brep: *const RawBrep,
|
||||
kind: i32,
|
||||
points: *const f64,
|
||||
sizes: *const f64,
|
||||
n_points: i64,
|
||||
corners: *const f64,
|
||||
setbacks: *const f64,
|
||||
n_corners: i64,
|
||||
tolerance: f64,
|
||||
out: *mut *mut RawBrep,
|
||||
out_failed_point: *mut i64,
|
||||
out_failed_corner: *mut i64,
|
||||
) -> i32;
|
||||
fn smlib_fillet_variable(
|
||||
brep: *const RawBrep,
|
||||
point: *const f64,
|
||||
@@ -265,6 +279,54 @@ pub fn blend(kind: i32, b: &Handle, points: &[[f64; 3]], sizes: &[f64], toleranc
|
||||
})
|
||||
}
|
||||
|
||||
/// `smlib_blend_setback`: `sizes` holds one size per point and `setbacks` one distance per
|
||||
/// corner (the caller checks the lengths match). A failed pick names its point; a corner that
|
||||
/// picks no vertex or several comes back with no index.
|
||||
#[cfg(feature = "native")]
|
||||
pub fn blend_setback(
|
||||
kind: i32,
|
||||
b: &Handle,
|
||||
points: &[[f64; 3]],
|
||||
sizes: &[f64],
|
||||
corners: &[[f64; 3]],
|
||||
setbacks: &[f64],
|
||||
tolerance: f64,
|
||||
) -> Result<Handle, PickError> {
|
||||
let n = i64::try_from(points.len()).map_err(|_| (ERR_ARG, None))?;
|
||||
let nc = i64::try_from(corners.len()).map_err(|_| (ERR_ARG, None))?;
|
||||
if sizes.len() != points.len() || setbacks.len() != corners.len() {
|
||||
return Err((ERR_ARG, None));
|
||||
}
|
||||
let flat = points.as_ptr().cast::<f64>();
|
||||
let flat_corners = corners.as_ptr().cast::<f64>();
|
||||
let (mut failed, mut failed_corner) = (-1i64, -1i64);
|
||||
new_brep(|out| unsafe {
|
||||
smlib_blend_setback(
|
||||
b.raw(),
|
||||
kind,
|
||||
flat,
|
||||
sizes.as_ptr(),
|
||||
n,
|
||||
flat_corners,
|
||||
setbacks.as_ptr(),
|
||||
nc,
|
||||
tolerance,
|
||||
out,
|
||||
&mut failed,
|
||||
&mut failed_corner,
|
||||
)
|
||||
})
|
||||
.map_err(|s| {
|
||||
let at = (s == ERR_PICK_NONE || s == ERR_PICK_AMBIGUOUS).then(|| usize::try_from(failed).ok()).flatten();
|
||||
(s, at)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "native"))]
|
||||
pub fn blend_setback(_: i32, _: &Handle, _: &[[f64; 3]], _: &[f64], _: &[[f64; 3]], _: &[f64], _: f64) -> Result<Handle, PickError> {
|
||||
Err((NOT_BUILT, None))
|
||||
}
|
||||
|
||||
/// `smlib_fillet_variable`.
|
||||
#[cfg(feature = "native")]
|
||||
pub fn fillet_variable(
|
||||
|
||||
@@ -150,6 +150,31 @@ impl Brep {
|
||||
ffi::ops::blend(kind, &self.0, edges, sizes, tolerance).map(Brep).map_err(pick_error)
|
||||
}
|
||||
|
||||
/// [`Brep::blend`] with corner setbacks: each of `corners` picks the vertex nearest it
|
||||
/// (within `tolerance`), a corner where every edge is blended, and that corner's patch starts
|
||||
/// `setbacks[j]` along each of its edges from the vertex (one distance per corner, as SMLib
|
||||
/// keeps it). A corner SMLib builds no setback on (some edge there not blended, a chamfer) is
|
||||
/// [`Error::Unsupported`]; a setback as long as an edge there, [`Error::NoRoom`].
|
||||
pub fn blend_setback(&self, kind: Blend, edges: &[[f64; 3]], sizes: &[f64], corners: &[[f64; 3]], setbacks: &[f64], tolerance: f64) -> Result<Brep> {
|
||||
init()?;
|
||||
if edges.len() > MAX_POINTS
|
||||
|| edges.is_empty()
|
||||
|| sizes.len() != edges.len()
|
||||
|| corners.is_empty()
|
||||
|| corners.len() > MAX_POINTS
|
||||
|| setbacks.len() != corners.len()
|
||||
{
|
||||
return Err(Error::Argument);
|
||||
}
|
||||
let kind = match kind {
|
||||
Blend::Round => ffi::ops::BLEND_ROUND,
|
||||
Blend::Curvature => ffi::ops::BLEND_CURVATURE,
|
||||
Blend::Chord => ffi::ops::BLEND_CHORD,
|
||||
Blend::Chamfer => ffi::ops::BLEND_CHAMFER,
|
||||
};
|
||||
ffi::ops::blend_setback(kind, &self.0, edges, sizes, corners, setbacks, tolerance).map(Brep).map_err(pick_error)
|
||||
}
|
||||
|
||||
/// The one edge nearest to `edge` (within `tolerance`) rounded with a radius
|
||||
/// that varies along it: a clamped B-spline of `degree` (1 to 3) with `knots` and control
|
||||
/// `radii` over the position along the edge, 0 at its end nearest `start` and 1 at the other
|
||||
|
||||
Reference in New Issue
Block a user