Kernel: an extrusion's wall seed marks only the edges nearest it

Each wall of a swept body is known by a seed on its piece's edge in the start plane; every
start-plane edge within `near` of a seed took its piece, `near` sized to the body
(3 x 2e-4 of its size). On a side shorter than that the neighbours' edges are near too: a
0.3 mm wall of a 1 m label is 0.15 mm from them, near 0.65 mm, so the long walls got two
pieces, had no source, and box_solid refused "box role correspondence" (gpu depth
at_ten_metres..., engine component_clone boundary_material_proof); a ring of radii 10 and
9.999 lost its side certificates (ui configuration_annulus_picker...). A seed now marks only
the edges nearest it (within the flatness tolerance of the nearest), still within `near`.
Regression case: a 1000 x 0.3 x 400 box in box_certificates_are_six_construction_roles...

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-28 22:27:39 -04:00
committed by Irakli Kourtis
parent 5547cd98ad
commit 1cb713c966
2 changed files with 19 additions and 6 deletions
+3
View File
@@ -27,6 +27,9 @@ fn box_certificates_are_six_construction_roles_with_dimension_stable_axes() {
(Vec3::new(2., 3., 4.), Vec3::new(12., 23., 34.)),
(Vec3::new(12., 23., 34.), Vec3::new(2., 3., 4.)),
(Vec3::new(2., -8., 4.), Vec3::new(22., 43., 54.)),
// A side far shorter than the body (a 0.3 mm label of a metre): its walls' edges lie
// closer together than the sweep's body-sized nearness, and each keeps its own role.
(Vec3::new(500., -0.3, 1400.), Vec3::new(1500., 0., 1800.)),
] {
let body = crate::box_solid(a, b).unwrap().with_box_certificate(42).unwrap();
let mut roles = std::collections::HashSet::new();
+16 -6
View File
@@ -289,12 +289,22 @@ mod imp {
let end_cap: Vec<bool> = (0..n).map(|f| end.is_some_and(|e| flat(f, e))).collect();
let cap = |f: usize| start_cap.get(f).copied().unwrap_or(false) || end_cap.get(f).copied().unwrap_or(false);
let mut swept: Vec<BTreeSet<usize>> = vec![BTreeSet::new(); n];
for (poly, fs) in m.edges.iter().zip(&m.edge_faces) {
if poly.len() < 2 || !poly.iter().all(|q| start.height(*q).abs() <= flat_tol) {
continue;
}
for s in edges {
if poly.windows(2).any(|w| s.at.dist_to_segment(w[0], w[1]) <= near) {
// Each seed lies on its own piece's edge (within the mesh's sag on a curve); `near` is
// sized to the body, so on a side shorter than it (a 0.3 mm wall of a 1 m label) the
// neighbours' edges are near too. The seed marks only the edges nearest it: the one it
// lies on, or both pieces of an edge split at its middle.
let start_edges: Vec<(&Vec<Vec3>, &Vec<u32>)> = m
.edges
.iter()
.zip(&m.edge_faces)
.filter(|(poly, _)| poly.len() >= 2 && poly.iter().all(|q| start.height(*q).abs() <= flat_tol))
.collect();
for s in edges {
let dist = |poly: &[Vec3]| poly.windows(2).map(|w| s.at.dist_to_segment(w[0], w[1])).fold(f64::INFINITY, f64::min);
let ds: Vec<f64> = start_edges.iter().map(|(poly, _)| dist(poly)).collect();
let nearest = ds.iter().copied().fold(f64::INFINITY, f64::min);
for ((_, fs), d) in start_edges.iter().zip(&ds) {
if *d <= near && *d <= nearest + flat_tol {
for f in fs.iter().map(|f| *f as usize).filter(|f| !cap(*f)) {
if let Some(set) = swept.get_mut(f) {
set.insert(s.piece);