solidcraft-smlib: Brep::merge_faces, SMLib's removal of topological edges and vertices

The wrapper of the fork's smlib_merge_faces (SmBrep::RemoveTopologicalEdgesAndVertices): faces
on one surface meeting along an edge become one, edges on one curve meeting at a vertex nothing
else uses become one, and the edges under the given points stay. SMLIB_REV moves to the fork
commit that adds it.

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 00:52:47 -04:00
parent 9f71e93e28
commit 3bd1cc5349
3 changed files with 41 additions and 2 deletions
+1 -1
View File
@@ -1 +1 @@
e7522f4e7917fe817643ff691f2860c310038c27
c899502f2bdd0e8e21c25e69eca423f659c9da8f
+27 -1
View File
@@ -1,6 +1,6 @@
//! The operations block of `capi/include/smlib.h` (`smlib_boolean`, `smlib_fillet`,
//! `smlib_chamfer`, `smlib_blend`, `smlib_fillet_variable`, `smlib_chamfer_sides`, `smlib_shell`, `smlib_offset_faces`,
//! `smlib_thicken`, `smlib_draft`, `smlib_brep_solid_count`, `smlib_imprint`; the fork's `capi/src/smlib_ops.cpp`), declared by
//! `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`].
@@ -121,6 +121,14 @@ unsafe extern "C" {
out_failed_point: *mut i64,
) -> i32;
fn smlib_thicken(brep: *const RawBrep, thickness: f64, symmetric: i32, out: *mut *mut RawBrep) -> i32;
fn smlib_merge_faces(
brep: *const RawBrep,
keep: *const f64,
n_keep: i64,
tolerance: f64,
out: *mut *mut RawBrep,
out_failed_point: *mut i64,
) -> i32;
fn smlib_draft(
brep: *const RawBrep,
points: *const f64,
@@ -209,6 +217,24 @@ pub fn draft(_: &Handle, _: &[[f64; 3]], _: f64, _: &[f64; 3], _: &[f64; 3], _:
Err((NOT_BUILT, None))
}
/// `smlib_merge_faces`: the body's topological edges and vertices removed, the edges under
/// `keep` kept.
#[cfg(feature = "native")]
pub fn merge_faces(b: &Handle, keep: &[[f64; 3]], tolerance: f64) -> Result<Handle, PickError> {
let n = i64::try_from(keep.len()).map_err(|_| (ERR_ARG, None))?;
let flat = keep.as_ptr().cast::<f64>();
let mut failed = -1i64;
new_brep(|out| unsafe { smlib_merge_faces(b.raw(), flat, n, tolerance, out, &mut failed) }).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 merge_faces(_: &Handle, _: &[[f64; 3]], _: f64) -> Result<Handle, PickError> {
Err((NOT_BUILT, None))
}
/// `smlib_blend`: `sizes` holds one size per point (the caller checks the lengths match).
#[cfg(feature = "native")]
pub fn blend(kind: i32, b: &Handle, points: &[[f64; 3]], sizes: &[f64], tolerance: f64) -> Result<Handle, PickError> {
+13
View File
@@ -170,6 +170,19 @@ impl Brep {
ffi::ops::thicken(&self.0, thickness, symmetric).map(Brep).map_err(error)
}
/// This body with its topological edges and vertices removed (SMLib's
/// `SmBrep::RemoveTopologicalEdgesAndVertices`): faces on one surface meeting along an edge
/// become one, and two edges on one curve meeting at a vertex nothing else uses become one.
/// The edges nearest to `keep` (each within `tolerance`) stay. The shape is unchanged, and
/// SMLib's history tags follow the merge.
pub fn merge_faces(&self, keep: &[[f64; 3]], tolerance: f64) -> Result<Brep> {
init()?;
if keep.len() > MAX_POINTS {
return Err(Error::Argument);
}
ffi::ops::merge_faces(&self.0, keep, tolerance).map(Brep).map_err(pick_error)
}
/// The flat faces nearest to `faces` (each within `tolerance`) tilted by `angle` radians
/// (0 < |angle| < 89.94 degrees) about the line where each meets the neutral plane through
/// `neutral_origin` with normal `neutral_normal`, a positive angle leaning them in going along