Boolean: a point at a boundary curve's end is that end, whatever its parameter (text cuts, #391) (#1195)

A point within the point tolerance of a boundary curve's end is that end in the boolean, whatever its parameter, so text cuts no longer leave unmatched sliver vertices (#391). Robustness goldens re-recorded for seeds 0, 34, 39, 41 and 57 with reasons.
This commit is contained in:
phanoob authored and GitHub committed 2026-10-15 13:31:37 -04:00
1 parent aa31e56477
commit 56747edb46
5 files changed
+69 -9

No files matched your search

+4
View File
@@ -17,6 +17,10 @@ Changes:
- `transversal/integrate/mod.rs`: the result's shells and faces keep the order of the shell
they come from (truck's connected components followed hash order of face addresses, so a
boolean's faces came out in a different order on every run).
- `transversal/loops_store/mod.rs`: a point at an end of a boundary curve (within the point
tolerance) is that end, whatever its parameter: a polyline's parameter counts segments, so
an intersection curve ending 2e-7 mm from another's end could read as inside it, cut it
into a sliver with a vertex of its own, and leave the result's shell open (#391).
- `transversal/loops_store/mod.rs`: an intersection edge added to a face at a vertex that more
than one wire visits (several curves end on it: the touching point of two equal cylinders) goes
into the corner that holds its direction, swept counterclockwise about the face's normal from
+13 -2
View File
@@ -158,7 +158,7 @@ impl ParameterKind {
}
}
impl<P: Copy, C: Clone> Loops<P, C> {
impl<P: Copy + Tolerance, C: Clone> Loops<P, C> {
fn search_parameter(&self, pt: P) -> Option<(usize, usize, ParameterKind)>
where C: BoundedCurve<Point = P> + SearchParameter<D1, Point = P> {
self.iter()
@@ -167,7 +167,18 @@ impl<P: Copy, C: Clone> Loops<P, C> {
.find_map(|(i, j, edge)| {
let curve = edge.curve();
curve.search_parameter(pt, None, 1).and_then(|t| {
let kind = ParameterKind::try_new(t, curve.range_tuple())?;
// SolidCraft: a point at an end of the curve is that end, however far its
// parameter is from the end's. The parameter alone is no distance: on a
// polyline it counts segments, and an intersection curve ending 2e-7 mm from
// another's end (two walls of a glyph meeting a face) read 1.4e-6 before it,
// so it was cut into a sliver and the result's shell never closed (#391).
let kind = if pt.near(&curve.front()) {
ParameterKind::Front
} else if pt.near(&curve.back()) {
ParameterKind::Back
} else {
ParameterKind::try_new(t, curve.range_tuple())?
};
Some((i, j, kind))
})
})