Skip to content

Allow skipping SimplifyResult in boolean operations - #273

Open
PawelPisarek wants to merge 1 commit into
sgenoud:mainfrom
PawelPisarek:allow-skipping-simplify-result
Open

PawelPisarek wants to merge 1 commit into
sgenoud:mainfrom
PawelPisarek:allow-skipping-simplify-result

Conversation

@PawelPisarek

Copy link
Copy Markdown
Contributor

Fixes #272.

Booleans end with an unconditional newBody.SimplifyResult(true, true, 1e-3). On some shapes that step turns a valid solid into an invalid one, and the damage is silent — a later boolean on it returns an empty result while reporting HasErrors() === false and IsDone() === true. #272 has a self-contained reproduction.

This adds a simplify option to fuse, cut and intersect. It defaults to true, so nothing changes for existing callers; it only gives people hitting the problem a way out.

const blank = half.fuse(half.mirror("YZ", [382.2, 0, 0]), { simplify: false });

Measurements

Taken on the affected shapes (a lofted picture-frame moulding, 23 shape/size combinations):

with simplification without
solid valid 14 / 23 23 / 23
volume unchanged (largest difference 0.00213 %, usually 0.00000 %)
face count baseline +4–5 % on curved shapes, +89 % on a straight one
time of the union baseline 9–16 % faster

Why not verify and fall back instead

Checking the simplified result and reverting when it is invalid would fix everyone without an API change, so I measured it. BRepCheck_Analyzer costs 16–38 % of the boolean itself (29 ms against a 77 ms union; 269 ms against 1626 ms; 367 ms against 2341 ms), which makes the safe variant 7–22 % more expensive on every boolean for every user — to rescue a minority of shapes.

That trade-off felt like yours to make rather than mine, so this PR takes the cheap route. Happy to switch to the verify-and-fall-back version, or to make it a third mode (simplify: "safe"), if you prefer.

Checks

  • tsc --noEmit clean
  • vitest run in packages/replicad: 53 passed (49 existing + 4 new in __tests__/boolean-simplify.test.ts)

Booleans end with an unconditional newBody.SimplifyResult(true, true, 1e-3).
On some shapes that step turns a valid solid into an invalid one, and the
damage is silent: a later boolean on it returns an empty result while
reporting HasErrors() === false and IsDone() === true.

This adds a simplify option (default true, so behaviour is unchanged) to
fuse, cut and intersect, so callers hitting the problem have a way out.

Measured on the affected shapes: skipping the step keeps the volume
identical, makes every solid valid, and is 9-16% faster; the face count
grows by 4-5% on curved shapes.

Verifying the result instead and falling back was measured too, but it
costs 7-22% on every boolean for every user, so it is not offered as a
default here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SimplifyResult in boolean operations can turn a valid solid into an invalid one (silent empty results downstream)

1 participant