cadquery
cadquery copied to clipboard
STL export of object with twistExtrude through-hole produces spatially-varying geometric inaccuracy
The problem:
Hi,
I am attempting to produce a cylinder with one or more helical through-holes. Please consult the following MWE:
import cadquery as cq
from cadquery import exporters
G_RADIUS = 0.25
G_LENGTH = 1.0
T = 6
P_RADIUS = 0.1 # Fraction of radius
P_OFFSET = 0.5 # Fraction of radius
FILLET_RADIUS = 0.01
CENTER_PUNCH = True
abs_p_radius = P_RADIUS*G_RADIUS
abs_p_offset = P_OFFSET*G_RADIUS
cyl = cq.Workplane("XY").circle(G_RADIUS).extrude(G_LENGTH)
cut1 = cq.Workplane("XY").center(abs_p_offset,0).circle(abs_p_radius).center(-abs_p_offset,0).twistExtrude(1,180)
cut2 = cq.Workplane("XY").circle(abs_p_radius).extrude(1)
cyl = cyl.cut(cut1)
for i in range(0, T):
cyl = cyl.cut(cut1.rotate(axisStartPoint=(0,0,-1), axisEndPoint=(0,0,1), angleDegrees=360/T*i))
if CENTER_PUNCH:
cyl = cyl.cut(cut2)
result = cyl
result = cyl.clean().fillet(FILLET_RADIUS)
exporters.export(result, '/tmp/test.stl')
This code defines a cylinder, a series of radially offset twistExtruded cylinders and a non-twisted central cylinder, the latter two of which are subtracted from the first.
This geometry looks good in CQ-editor:

However inspection of the derived STL file shows that the cross section of the helical through-holes deviates from circular towards the center of the cylinder, with the holes eventually vanishing:

n.b. These cross sections are from PrusaSlicer. the wavy red stuff is a non-solid gyroidal infill for 3D printing and not part of the STL geometry proper, hopefully you get the idea.
Things I've tested:
- Linear through-holes do not exhibit this.
- Increasing the hole diameter, decreasing the helical pitch, or shortening the cylinder ameliorate the problem. Under some circumstances I get holes that go all the way through but again exhibit spatially-varying deviations from circularity in the hole cross-section. Geometries with a sufficiently large hole radius or low pitch do not exhibit the problem. I therefore suspect this has something to do with the total angle of the twistExtrude, rather than the pitch directly.
- Removing the fillet does not help.
- Decreasing the STL export tolerance does not help.
Questions:
I would like to be able to parametrically generate geometries like this, but with consistent helical holes of circular cross section (within reason of course). If this is known or expected behaviour, what is its root cause and how do I fix/predict/avoid it?
Thanks for any help anyone can provide.
Version: cadquery 2.1
I first checked with sections to see if the holes are correct in CQ-editor, and they stay consistent at 0.2, 0.25, 0.5, 0.75 heights.
section = result.section(height=0.5)
show_object(section)

I then tried exporting with different tolerances using the following code, without any luck at fixing the issue.
result.val().exportStl('/tmp/test.stl', tolerance=0.0005, angularTolerance=0.05)
Be careful if you try this code though, some tolerance settings will lead to extremely long export times. When imported in Prusa Slicer the STL had between 48 and 96 errors that had to be repaired, depending on the tolerance settings, so something is not working correctly with the export.
I also tried exporting to STEP and then exported that to STL from FreeCAD. The STL still had the same problems. You can see artifacts in the STEP import that would be consistent with the problems in the STL with the transparency set to 50% on the object in FreeCAD.

The only way I was able to get a good result was by switching the circle profile for the twistExtrudes to rectangles.
cut1 = cq.Workplane("XY").center(abs_p_offset,0).rect(abs_p_radius * 2, abs_p_radius * 2).center(-abs_p_offset,0).twistExtrude(1,180)
Looks like some tessellation bug of OCCT. Take a look here for a possible workaround: https://github.com/CadQuery/cadquery/issues/367 .
Hi,
I did some experimentation with netgen.occ as per #367 . This obtains through-holes that go all the way through and retain approximately circular cross section:

The mesh here has some slight irregularities which I suppose are due to the tessellation algorithm (hmax=0.01, optsteps2d=4), however these are hopefully not significant for my purposes.
Unfortunately cq-editor does not carry netgen along with it so I had to construct a miniconda environment but within that context it seems to work. More generally, is it (in principle) possible to configure a cq/netgen stack as a collection of site packages? I'd like to run cq programmatically using a batch system I don't control and it's unlikely that I'll have the flexibility to create and activate conda environments in that context. If not, no big deal.
Otherwise, my problem is solved, thanks for your help.
Not related to the issue itself, but you could try using tools like https://conda.github.io/conda-pack/ or https://github.com/conda/constructor .
Fixed in OCCT/OCP 7.7.0.
OCP7.6.3 on left, OCP7.7.0 on right (PR #1215):
