mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 18:45:55 +00:00
SMLib history: a split line between two pieces of one face comes from nothing
An edge SMLib reports as new was given the origin "where its two faces meet", each side what
that face came from. A split line lies between two pieces of one face, so both sides are that
face and the edge read EdgeOrigin::Meet { top, top }: a face meeting itself, which no two faces
did. Such an edge now has no origin, as the history's EdgeProv documents for a new edge between
faces new to the operation (the doc now names the split line too).
New test: a_split_line_comes_from_nothing (one face split in two, its new edge has no origin).
modify_history_tests::split_a_face checks this at its last line; it still fails earlier, on its
counts ([3, 2, 2, 0, 0] for [5, 0, 2, 0, 0]) on develop's SMLib pin, until SMLib batch 3's
history fix (03bbc88) is pinned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -119,7 +119,8 @@ pub enum EdgeOrigin {
|
||||
}
|
||||
|
||||
/// A result edge: the result faces it separates and what it came from (empty when it is new
|
||||
/// and lies between faces new to the operation).
|
||||
/// and lies between faces new to the operation, or between two pieces of one face: a split
|
||||
/// line).
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct EdgeProv {
|
||||
pub faces: Vec<usize>,
|
||||
|
||||
@@ -178,10 +178,11 @@ impl Raw {
|
||||
}
|
||||
};
|
||||
let origins = if e.origins.is_empty() {
|
||||
// New: where its two faces meet, each side what that face came from.
|
||||
// New: where its two faces meet, each side what that face came from. Between two
|
||||
// pieces of one face (a split line) nothing met: it comes from nothing.
|
||||
let side = |f: usize| faces.get(f).and_then(|p| Side::new(p.origins.iter().copied()));
|
||||
match bounds.as_slice() {
|
||||
[a, b] => side(*a).zip(side(*b)).map(|(a, b)| EdgeOrigin::meet(a, b)).into_iter().collect(),
|
||||
[a, b] => side(*a).zip(side(*b)).filter(|(a, b)| a != b).map(|(a, b)| EdgeOrigin::meet(a, b)).into_iter().collect(),
|
||||
_ => Vec::new(),
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -55,6 +55,17 @@ fn new_edges_are_where_their_faces_meet() {
|
||||
h.check_counts((3, 3), &[(3, 8), (5, 4)]).unwrap();
|
||||
}
|
||||
|
||||
/// A face split in two (a split line across operand 0's face 0): the new edge lies between two
|
||||
/// pieces of one face, where nothing met, so it comes from nothing.
|
||||
#[test]
|
||||
fn a_split_line_comes_from_nothing() {
|
||||
let raw = Raw::decode(&[1, 2, 1, 2, 1, 0, 0, 2, 1, 0, 0, 2, 0, 1, 0]).unwrap();
|
||||
let h = raw.history(&[Order::default()], &Order::default()).unwrap();
|
||||
assert_eq!(h.faces.iter().map(|f| (f.origins.clone(), f.change)).collect::<Vec<_>>(), vec![(vec![face(0, 0)], Change::Split); 2]);
|
||||
assert_eq!(h.edges[0].faces, vec![0, 1]);
|
||||
assert!(h.edges[0].origins.is_empty(), "{:?}", h.edges[0].origins);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renumbers_into_canonical_order() {
|
||||
let raw = Raw::decode(RECORDS).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user