mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 10:35:58 +00:00
kernel: a body SMLib walks some loops of the other way keeps its order
smlib_body_ordered keeps SMLib's face and edge order for history only where SMLib's export numbers the body as its record does, and compared each loop edge for edge in the same order and direction. SMLib walks a face whose surface it turned (a hole's wall, a concave cylinder) the other way round and may start the loop elsewhere, so a plate with a hole lost its history through every SMLib boolean and shell although its faces and edges are numbered alike. A loop now matches when it walks the same edges in the same cyclic order, or in the opposite order with every edge reversed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
This commit is contained in:
@@ -240,9 +240,7 @@ fn same_numbering(a: &solidcraft_geom::brep::Brep, b: &solidcraft_geom::brep::Br
|
||||
let loops_alike = a.faces.iter().zip(&b.faces).all(|(fa, fb)| {
|
||||
fa.loops.len() == fb.loops.len()
|
||||
&& fa.loops.iter().zip(&fb.loops).all(|pair| match pair {
|
||||
(Loop::Edges { edges: x }, Loop::Edges { edges: y }) => {
|
||||
x.len() == y.len() && x.iter().zip(y).all(|(u, w)| u.edge == w.edge && u.forward == w.forward)
|
||||
}
|
||||
(Loop::Edges { edges: x }, Loop::Edges { edges: y }) => same_cycle(x, y),
|
||||
(Loop::Vertex { vertex: x }, Loop::Vertex { vertex: y }) => x == y,
|
||||
_ => false,
|
||||
})
|
||||
@@ -255,6 +253,25 @@ fn same_numbering(a: &solidcraft_geom::brep::Brep, b: &solidcraft_geom::brep::Br
|
||||
loops_alike && ends_alike && at_same_place
|
||||
}
|
||||
|
||||
/// Whether two loops walk the same edges: in the same order from some edge on, or in the
|
||||
/// opposite order with each edge the other way round. SMLib walks a face whose surface it turned
|
||||
/// (a hole's wall) the other way, starting where it likes; its faces and edges are numbered
|
||||
/// alike all the same.
|
||||
#[cfg(feature = "smlib")]
|
||||
fn same_cycle(x: &[solidcraft_geom::brep::OrientedEdge], y: &[solidcraft_geom::brep::OrientedEdge]) -> bool {
|
||||
let n = x.len();
|
||||
if n != y.len() {
|
||||
return false;
|
||||
}
|
||||
let Some(first) = x.first() else { return true };
|
||||
let at = |k: usize| y.get(k % n);
|
||||
(0..n).filter(|k| at(*k).is_some_and(|e| e.edge == first.edge)).any(|k| {
|
||||
let ahead = x.iter().enumerate().all(|(i, u)| at(k + i).is_some_and(|w| w.edge == u.edge && w.forward == u.forward));
|
||||
let back = x.iter().enumerate().all(|(i, u)| at(k + n - i).is_some_and(|w| w.edge == u.edge && w.forward != u.forward));
|
||||
ahead || back
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_topology(saved: &SavedBody) -> Result<()> {
|
||||
saved.solid.validate().map_err(invalid)?;
|
||||
let (faces, edges) = (saved.solid.faces.len(), saved.solid.edges.len());
|
||||
|
||||
Reference in New Issue
Block a user