Lips on rounded, shelled rims: the band along the rim's edge is raised from the body's own faces (kernel::raise_band: the rim face split along the band's exact offset edge, the band's walls swept up from the walls below, a top), since a join can't merge walls that continue each other; grooves cut with a band reaching into the free side so no wall coincides; tests against the band's area times its height

Fixes #29

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-10 00:04:37 +00:00
1 parent 80f5a58806
commit 67c79ec91c
6 files changed
+297 -4

No files matched your search

+20 -3
View File
@@ -783,11 +783,28 @@ pub(super) fn plastic_eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &F
return Err(DocError::Invalid("pick the rim face of a shelled body (a face with an inner and an outer edge)".into()));
};
let bw = if *groove { w + g } else { w };
// The band along the chosen edge, inside the rim face.
// A lip: the band raised from the rim's own faces (its walls continue the walls
// below, which a join can't do: they would coincide).
if !*groove
&& let Ok(b) = kernel::raise_band(&mb.body, *face, w, h, *outside)
&& let Some(slot) = st.bodies.iter_mut().find(|x| x.name == target)
{
*slot = ModelBody::new(target.clone(), b, slot.feature);
return Ok(());
}
// The band along the chosen edge, inside the rim face. A groove's cutter reaches past
// the edge into the free side (the cavity, or outside), so no wall coincides.
let free = if *groove { bw } else { 0.0 };
let band = if *outside {
Region2 { outer: Loop2::polygon(&outer).ccw(), holes: vec![Loop2::polygon(&offset_left(&outer, bw)).ccw().reversed()] }
Region2 {
outer: Loop2::polygon(&offset_left(&outer, -free)).ccw(),
holes: vec![Loop2::polygon(&offset_left(&outer, bw)).ccw().reversed()],
}
} else {
Region2 { outer: Loop2::polygon(&offset_left(&inner, -bw)).ccw(), holes: vec![Loop2::polygon(&inner).ccw().reversed()] }
Region2 {
outer: Loop2::polygon(&offset_left(&inner, -bw)).ccw(),
holes: vec![Loop2::polygon(&offset_left(&inner, free)).ccw().reversed()],
}
};
let delta = (h * 0.05).clamp(1e-3, 0.5);
if *groove {