Closed nerdfever closed 7 years ago
I don't have any bulletproof way to speed things up, but I agree with your diagnosis: very fine iteration and very smooth circles. The CGAL library OpenSCAD uses turns everything into polygons and gets slow really fast when you add more.
One thing I did check: when I first started using OpenSCAD (2011, so no guarantees for current versions). I could find no performance difference between native OpenSCAD loops and unrolled loops like SolidPython produces; a two-liner that evaluated into 10000 shapes took exactly as long to render as literally writing out/parsing each of those shapes in 10000 lines.
I assume you're going to 3D print this piece? I'd print a 5mm tall ring of the appropriate diameter with 'circle_segments' at 50, 100, 200, 500, and 1000. See if you really need all those segments at your intended size or if you could afford to go lower. The other trick I use is to have a CIRCLE_SEGMENTS constant I keep at something low during development and only crank up when I'm doing a final render.
There may be some extra tricks to get better performances out of CGAL, but I don't know them offhand. As far as I understand, it boils down to more polygons == more render time. Good luck!
see https://github.com/SolidCode/SolidPython/pull/65 If you have a lot of unions, it may speed up the render.
TL;DR if unioning a lot of things, shape += [a, b, c]
will currently be a lot faster than shape += a; shape+= b; shape += c
Good point! I'd forgotten that detail. In the current code, if you do something like:
shape += a
shape += b
shape += c
that translates to
union()(
union()(
union()(
shape
a,
),
b
),
c
)
as opposed to the much more optimal:
union()(
shape,
a,
b,
c
)
As @BarnacleDuck points out, there's a PR, #65, that would improve this behavior, but I haven't integrated it yet.
You may have better luck using $fa to set angular limits on the number of segments, and $fs to set minimum segment sizes - for my 3D printer there's no point in a segment less than 50 microns or an angle less than a degree. These settings generate large but not completely outrageous models.
Fundamentally, though, CGAL is incredibly demanding when handed complex polygon models. I had one heightmap, maybe a megapixel, that required more than my laptop's 16 GB of RAM to render. (Also OpenSCAD's heightmaps seem to make more polygons than necessary.) It's unclear to me whether any CSG library is capable of coping with such models, though I suspect if CGAL was smarter with spatial data structures to accelerate polygon intersection it could become much less demanding without losing desirable numerical properties. For smooth objects the OpenCascade kernel can work with NURBS, keeping objeect numbers small, but that won't help with heightmaps or other inherently-polygonal objects.
This is probably more of an OpenSCAD issue than a SolidPython issue, but SolidPython makes it easy (maybe too easy) to generate code that takes forever to render.
For example, the SolidPython script below took more than 30 minutes to render (on an i7 box).
I'm quite sure the problem is using "for offset in frange" (near the end of the script) together with $fs=1000.
Is there some general technique I ought to be using to reduce the render time? Somehow maybe merge objects, etc?