{
return Err(invalid("triangle refers to a missing vertex"));
};
let cross = (*pb - *pa).cross(*pc - *pa);
+ // `weld` dropped the triangles of no area, so none is left here.
let Some(mut n) = cross.normalized() else { return Err(invalid("degenerate triangle")) };
for (a, b) in [(a, b), (b, c), (c, a)] {
let entry = edges.entry((a.min(b), a.max(b))).or_default();
@@ -126,17 +127,39 @@ fn weld(mesh: &crate::meshbody::TriMesh, tolerance: f64) -> Result {
};
remap.push(i);
}
- let triangles = mesh
- .triangles
- .iter()
- .map(|t| {
- let (Some(&a), Some(&b), Some(&c)) = (remap.get(t[0] as usize), remap.get(t[1] as usize), remap.get(t[2] as usize)) else {
- return Err(invalid("missing triangle vertex"));
- };
- Ok([a, b, c])
- })
- .collect::>>()?;
- crate::mesh_body(&positions, &triangles)
+ // A triangle of no area (its corners on one line, or welded into one another) adds no
+ // surface, so it is dropped rather than refused (#4561); the closed-manifold check that
+ // follows still refuses a mesh that needed it to close. Only the vertices the kept triangles
+ // use stay, so a dropped triangle's corner cannot widen the part's extent.
+ let mut used: Vec