Ask anyone who has worked on a geometric modelling kernel what the hardest part is, and the answer is almost always the same: booleans. Union, subtraction and intersection look like the simplest operations a CAD system offers, and they are where kernels go to die.
Why it looks easy
The mathematical definition is trivial. To subtract solid B from solid A: find where their boundaries intersect, split both surfaces along those curves, discard the pieces of A inside B and the pieces of B outside A, then stitch what remains into a closed shell.
Every step in that sentence hides a numerical problem.
The four hard problems
1. Surface intersection has no closed form
For two general NURBS surfaces there is no formula giving the intersection curve. It must be computed numerically — marching along, solving iteratively, sampling. That produces an approximation with error, and every subsequent step inherits that error.
2. Continuous maths, discrete decisions
The algorithm must answer yes-or-no questions: is this point inside or outside? do these edges coincide? Floating-point arithmetic answers "the distance is 3.7 × 10⁻¹⁴", and you must choose a tolerance to convert that into a decision.
This is the root of the entire problem. Set the tolerance too tight and coincident geometry is treated as distinct, producing gaps. Too loose and distinct geometry is merged, destroying detail. There is no value that is correct for all models — which is why single-global-tolerance kernels fail on real data.
3. Degenerate configurations are common, not rare
In synthetic tests, solids intersect cleanly. In real models, engineers create exactly the awkward cases constantly:
- Tangency — a cylinder touching a plane along a line rather than crossing it.
- Coincident faces — two solids sharing a face exactly, as when parts are mated.
- Edge-on-edge contact — intersection collapsing to a single curve or point.
- Sliver faces — near-zero-area regions from earlier operations.
- Self-intersecting input — a solid that was already invalid before you started.
4. Errors compound silently
A slightly wrong intersection yields a slightly invalid solid. Feed that into another boolean and the error grows. By the fourth operation the model is badly broken — and the user sees the failure far from where it originated, which makes it extremely hard to diagnose.
The failure you see is rarely the failure that happened. Boolean robustness is largely about refusing to produce invalid output in the first place.
How production kernels actually cope
- Exact or adaptive-precision predicates For the decisions that must be right — orientation, in/out classification — use arithmetic that is exact, or that escalates precision until the sign is certain. Slower, but eliminates a whole class of wrong answers.
- Tolerant topology Store a tolerance per vertex and edge rather than one global value. Entities from a rough import carry a loose tolerance; precise ones stay tight. This is how imported geometry becomes usable.
- Keep analytic surfaces analytic Do not convert planes and cylinders to NURBS. Plane-plane intersection is exact and instant; NURBS-NURBS is neither. Most real intersections involve analytic surfaces, so this is a large robustness win.
- Explicit special-case handling Detect tangency and coincidence up front and handle them with dedicated code paths rather than hoping the general algorithm copes.
- Validate after every operation Check manifoldness, orientation and closure immediately. Failing loudly at the source beats corrupting silently.
- Fallback strategies If the exact path fails, retry with perturbed tolerance, or fall back to a mesh boolean and report reduced accuracy — better than refusing entirely.
Testing that actually finds these bugs: fuzz your boolean with randomly perturbed geometry near degenerate configurations — solids offset by nanometres, faces rotated by microradians. Clean test models pass trivially and prove nothing. The bugs live in the almost-degenerate cases.
What this means if you are building a product
- Do not write your own booleans unless your geometry domain is genuinely narrow. This is decades of accumulated engineering in commercial kernels.
- Budget for boolean failures even with a good kernel. Build repair paths and clear user messaging.
- Collect failing customer geometry as a regression suite. It is the most valuable test asset you will own.
- Constrain your input where you can. If you control how models are created, you avoid many degenerate cases entirely.
- Never present a failed boolean as success. A silent invalid solid is far worse than an honest error.
When a narrow custom implementation is reasonable
If your geometry is restricted — 2D polygons, 2.5D prismatic shapes, axis-aligned solids, or meshes rather than exact B-Rep — booleans become genuinely tractable. Polygon clipping is a solved problem with robust published algorithms; mesh booleans are well understood. The impossibility is specific to general trimmed-NURBS solids, and narrowing your domain is the single most effective engineering decision available.
Hitting boolean failures in a product, or scoping a geometry engine? Send us the geometry that breaks. See our CAD kernel service, and B-Rep vs NURBS for the underlying representation.