feat(kernel): bodies joined apart report their history (#136)
union_apart joins bodies whose boxes are clearly apart (many pattern tools, #261) without any intersection work: their shells side by side. Each face and edge of the result is its piece's own, unchanged, and the result now says so (a history over the pieces), so a pattern's cut keeps the exact names of every copy's faces. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
This commit is contained in:
1 parent
08d797235d
commit
2bda050872
2 files changed
+33
-1
No files matched your search
@@ -484,3 +484,20 @@ fn bore_union_of_a_bore_in_two_arcs_has_no_history() {
|
||||
let r = crate::coplanar::bore_union(&floor, &ring, &|_| true).expect("the bores are recut");
|
||||
assert!(r.history().is_none());
|
||||
}
|
||||
|
||||
/// Bodies clearly apart, joined as one body of several pieces (`union_apart`): every face and
|
||||
/// edge is its piece's own, kept.
|
||||
#[test]
|
||||
fn bodies_apart_joined_keep_their_faces() {
|
||||
let pieces = [boxed(0.0, 0.0, 0.0, 2.0, 2.0, 2.0), boxed(5.0, 0.0, 0.0, 7.0, 2.0, 2.0), boxed(10.0, 0.0, 0.0, 12.0, 2.0, 2.0)];
|
||||
let r = crate::union_apart(&pieces).unwrap().unwrap();
|
||||
let operands: Vec<&Body> = pieces.iter().collect();
|
||||
let h = verified(&r, &operands, 0.01);
|
||||
assert_eq!(h.operands, 3);
|
||||
for (k, piece) in pieces.iter().enumerate() {
|
||||
for f in 0..piece.face_count() {
|
||||
assert_eq!(from(h, face(k, f)).len(), 1, "{}", show(h));
|
||||
}
|
||||
}
|
||||
assert!(faces_of(h).iter().all(|(change, origins)| *change == Change::Kept && origins.len() == 1), "{}", show(h));
|
||||
}
|
||||
@@ -672,7 +672,22 @@ pub fn union_apart(bodies: &[Body]) -> Result<Option<Body>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
join_pieces(bodies.to_vec())
|
||||
// The pieces stay as they are, side by side: each face and edge of the result is its piece's
|
||||
// own (the history over `bodies`).
|
||||
let Some(joined) = join_pieces(bodies.to_vec())? else { return Ok(None) };
|
||||
let operands: Vec<&Body> = bodies.iter().collect();
|
||||
let faces = bodies
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(operand, b)| {
|
||||
(0..b.face_count()).map(move |face| (std::collections::BTreeSet::from([crate::history::FaceOrigin::Face { operand, face }]), true))
|
||||
})
|
||||
.collect();
|
||||
let mut edges = HashMap::new();
|
||||
for (operand, b) in bodies.iter().enumerate() {
|
||||
edges.extend(record::edge_origins(&b.solid, operand));
|
||||
}
|
||||
Ok(Some(record::traced(joined, &record::counts(&operands), Some(record::regions(faces)), Some(&edges))))
|
||||
}
|
||||
|
||||
/// Bodies (apart from each other) as one body of several pieces.
|
||||
|
||||
Reference in new issue
Block a user