CadQuery / CadQuery/cadquery

CadQuery `Workplane.cut()` produces degenerate results for overlapping spheres

Open
#2,020 2 comments 0 reactions 0 assignees View on GitHub
bug ShapeUpgrade_UnifySameDomain
Dominant language
Python
Stars
5.8k
Forks
541
Avg merge
3d 2h
Merged PRs (30d)
5

Description

### Description

I've run into an issue where a boolean cut between two overlapping spheres using `Workplane.cut()` appears to produce incorrect geometry. The resulting solid retains the volume of the original uncut sphere, and the cut face has zero area. I noticed that performing the same operation with `OCP.BRepAlgoAPI.BRepAlgoAPI_Cut` directly gives the expected result, so I wanted to flag this in case it's helpful.

It's possible I'm using the API incorrectly happy to be corrected if so!

### Reproduction

```python
import cadquery as cq
from OCP.BRepPrimAPI import BRepPrimAPI_MakeSphere
from OCP.BRepAlgoAPI import BRepAlgoAPI_Cut
from OCP.gp import gp_Pnt

d, r = 3, 5 5

# Via CadQuery
sphere1 = cq.Workplane().transformed(offset=(-d, 0, 0)).sphere(r)
sphere2 = cq.Workplane().transformed(offset=(d, 0, 0)).sphere(r)
crescent_cq = sphere2.cut(sphere1)

print(f"CadQuery volume: {crescent_cq.val().Volume():.2f}")
# 523.60 — same as the original sphere, expected ~414.69

for f in crescent_cq.val().Faces():
print(f" Face area: {f.Area():.4f}")
# Face 0: 314.1593 (full sphere surface area)
# Face 1: 0.0000 (cut face appears degenerate)

# Via OCC directly
s1 = BRepPrimAPI_MakeSphere(gp_Pnt(-d, 0, 0), r).Shape()
s2 = BRepPrimAPI_MakeSphere(gp_Pnt(d, 0, 0), r).Shape()
crescent_occ = BRepAlgoAPI_Cut(s2, s1).Shape()

print(f"OCC volume: {cq.Solid(crescent_occ).Volume():.2f}")
# 414.69 — expected crescent volume

for f in cq.Shape(crescent_occ).Faces():
print(f" Face area: {f.Area():.4f}")
# Three faces, all with non-zero area
```

Expected behaviour

sphere2.cut(sphere1) should produce a crescent-shaped solid with volume ~414.69 and faces with non-zero area at the cut boundary.

Actual behaviour

The result has the same volume as the uncut sphere (523.60). The cut boundary face has zero area and receives no mesh triangles from BRepMesh_IncrementalMesh, which leaves the solid effectively unclosed.

Context

@jmwright and I came across this while working on CAD-to-DAGMC neutronics geometry conversion. The degenerate face prevents the mesh from being watertight, which causes particle transport failures. Using BRepAlgoAPI_Cut directly works around the issue for now. I think this is related to the errors we saw [on the model-benchmark-zoo PR](https://github.com/fusion-energy/model_benchmark_zoo/pull/64) today

Environment

Tested on both CadQuery 2.7.0 and 2.8.0.dev0 (installed from main today) — same behaviour on both.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.