Press Pull on a fillet's or chamfer's face edits that feature's size by the distance (found through the face's persistent name); on another curved face it offsets the face, with the rest of its surface (both halves of a hole's wall)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 13:39:34 +00:00
1 parent 59b59a83e6
commit 06186be555
5 files changed
+106

No files matched your search

+40
View File
@@ -647,3 +647,43 @@ pub(crate) fn draft_walls(b: &Body, chosen: &[usize], neutral: &solvecraft_geom:
Body::new(solid)
})
}
/// The chosen faces and every face on the same surface joined to them (the halves of a hole's
/// wall), as face indices.
pub(crate) fn with_same_surface(b: &Body, chosen: &[usize]) -> Vec<usize> {
let faces: Vec<mt::Face> = b.solid.face_iter().cloned().collect();
let size = b.size();
let tol = (size * 1e-7).max(1e-9) * 100.0;
let surfs: Vec<Option<Surf>> = faces.iter().map(|f| surf_of(f, tol)).collect();
let same = |x: &Surf, y: &Surf| match (*x, *y) {
(Surf::Plane { n, d }, Surf::Plane { n: m, d: e }) => n.dot(m) > 1.0 - 1e-9 && (d - e).abs() < tol,
(Surf::Cylinder { o, a, r, convex }, Surf::Cylinder { o: o2, a: a2, r: r2, convex: c2 }) => {
a.dot(a2).abs() > 1.0 - 1e-9 && (r - r2).abs() < tol && convex == c2 && { (o2 - o - a * (o2 - o).dot(a)).len() < tol }
}
(Surf::Sphere { c, r, convex }, Surf::Sphere { c: c2, r: r2, convex: k2 }) => c.dist(c2) < tol && (r - r2).abs() < tol && convex == k2,
(Surf::Cone { v, a, half, convex }, Surf::Cone { v: v2, a: a2, half: h2, convex: k2 }) => {
v.dist(v2) < tol && a.dot(a2) > 1.0 - 1e-9 && (half - h2).abs() < 1e-9 && convex == k2
}
_ => false,
};
let mut out: Vec<usize> = chosen.to_vec();
let mut grew = true;
while grew {
grew = false;
for (i, f) in faces.iter().enumerate() {
if out.contains(&i) {
continue;
}
let Some(Some(si)) = surfs.get(i) else { continue };
let joins = out.iter().any(|j| {
surfs.get(*j).and_then(|x| x.as_ref()).is_some_and(|sj| same(si, sj))
&& faces.get(*j).is_some_and(|g| g.edge_iter().any(|e| f.edge_iter().any(|x| x.id() == e.id())))
});
if joins {
out.push(i);
grew = true;
}
}
}
out
}
+1
View File
@@ -442,5 +442,6 @@ pub fn offset_faces(b: &Body, at: &[Vec3], distance: f64) -> Result<Body> {
_ => return Err(KernelError::Invalid(format!("no face at {:?}", [p.x, p.y, p.z]))),
}
}
let chosen = crate::offset::with_same_surface(&healed, &chosen);
offset_planar(&healed, |fi, _| if chosen.contains(&fi) { distance } else { 0.0 })
}