Faceted boolean: a body's own mesh is closed once its faces' shared corners are one vertex

faceted_boolean took the tool mesh's triangles by vertex index and refused any edge not shared
by exactly two triangles. A body's mesh (Body::mesh) gives each face its own vertices, the faces
along an edge the very same points, so a box's mesh came in as six open patches: "the mesh is
not closed". Corners at the very same point are now one vertex first (triangles keep their order,
so the history's triangle faces are unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-29 01:02:38 -04:00
committed by Irakli Kourtis
parent e0d5ee4963
commit 39e1dcea03
+22
View File
@@ -39,6 +39,8 @@ fn faceted_boolean_untimed(a: &Body, b: &Mesh, op: BoolOp, tol: f64) -> Result<O
if b.triangles.len() > MAX_TRIANGLES {
return Err(failed(&format!("the mesh is too detailed ({} triangles, at most {MAX_TRIANGLES})", b.triangles.len())));
}
let welded = welded(b);
let b = &welded;
let groups = coplanar_groups(b, tol)?;
let mut faces = Vec::new();
let mut face_group = Vec::new();
@@ -60,6 +62,26 @@ fn faceted_boolean_untimed(a: &Body, b: &Mesh, op: BoolOp, tol: f64) -> Result<O
Ok(Some(result.with_checked_history(history, &counts)))
}
/// `m` with corners at the very same point made one vertex, triangles in their order: a body's
/// own mesh (Body::mesh) gives each face its own vertices, the faces along an edge its very
/// points, and is closed only once they are one.
fn welded(m: &Mesh) -> Mesh {
let mut at: BTreeMap<[u64; 3], u32> = BTreeMap::new();
let mut positions = Vec::with_capacity(m.positions.len());
let index: Vec<u32> = m
.positions
.iter()
.map(|p| {
*at.entry([p.x.to_bits(), p.y.to_bits(), p.z.to_bits()]).or_insert_with(|| {
positions.push(*p);
(positions.len() - 1) as u32
})
})
.collect();
let triangles = m.triangles.iter().map(|t| t.map(|i| index.get(i as usize).copied().unwrap_or(i))).collect();
Mesh { positions, triangles, ..Mesh::default() }
}
/// The mesh's triangles in runs that make one planar face each: triangles sharing an edge, on
/// one plane within `tol`, are one run.
fn coplanar_groups(m: &Mesh, tol: f64) -> Result<Vec<Vec<usize>>> {