feat(kernel): modifiers report exact face and edge history
Fillets (local, loop, rolling ball, corner, variable, chord), chamfers (cutters, local corners, loops, two sides), shell, draft, offset faces, split face/body, delete face, patch/copy/stitch/trim/extend and transforms record their history over [body] while they build: faces rebuilt from the body's, blends in place of edges (corner patches in place of the edges at the corner), shell walls as offsets, edges as pieces of the body's or where two faces meet. Multi-step operations compose each step. The push-face offset fallback now has history, and the bore union composes its narrowed tool. A reflection reorders a body's edges, so transforms now match edges by identity (mirrored copies reported the wrong edges). Refs #136 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
This commit is contained in:
1 parent
d5cb276965
commit
08d7037176
19 files changed
+1146
-231
No files matched your search
@@ -55,7 +55,7 @@ fn key(p: Vec3, q: f64) -> Key {
|
||||
}
|
||||
|
||||
/// Delete faces (indices in the body's face order, as in its mesh's `tri_face`) and heal the
|
||||
/// gap by extending the neighbouring planes.
|
||||
/// gap by extending the neighbouring planes. The result's history is over `[body]`.
|
||||
pub fn delete_faces(body: &Body, faces: &[usize]) -> Result<Body> {
|
||||
body.require_brep("Delete Face")?;
|
||||
let all: Vec<mt::Face> = body.solid.face_iter().cloned().collect();
|
||||
@@ -194,6 +194,9 @@ pub fn delete_faces(body: &Body, faces: &[usize]) -> Result<Body> {
|
||||
lines.insert((ka, kb), e.clone());
|
||||
e
|
||||
};
|
||||
// Neighbours rebuilt from themselves, moved edges pieces of themselves; the edges that
|
||||
// close the gap are new.
|
||||
let mut rec = crate::record::Rebuild::default();
|
||||
let mut out: Vec<mt::Face> = Vec::new();
|
||||
for (fi, f) in all.iter().enumerate() {
|
||||
if del.contains(&fi) {
|
||||
@@ -256,7 +259,9 @@ pub fn delete_faces(body: &Body, faces: &[usize]) -> Result<Body> {
|
||||
new_edges.push(e.clone());
|
||||
} else if matches!(e.oriented_curve(), mt::Curve::Line(_)) {
|
||||
if a.dist(b) > q * 10.0 {
|
||||
new_edges.push(line(a, b, &mut verts));
|
||||
let moved = line(a, b, &mut verts);
|
||||
rec.piece(&moved, e);
|
||||
new_edges.push(moved);
|
||||
}
|
||||
} else {
|
||||
return Err(fail(format!("face {fi} has a curved edge that would have to stretch")));
|
||||
@@ -285,11 +290,12 @@ pub fn delete_faces(body: &Body, faces: &[usize]) -> Result<Body> {
|
||||
}
|
||||
_ => face,
|
||||
};
|
||||
rec.face(&face, f);
|
||||
out.push(face);
|
||||
}
|
||||
let shell: mt::Shell = out.into();
|
||||
let solid = Solid::try_new(vec![shell]).map_err(|e| fail(format!("the neighbouring faces do not close the gap ({e})")))?;
|
||||
Body::new(solid)
|
||||
crate::record::rebuilt(solid, &[&body.solid], &rec)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user