mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user