Not just that but it also positions everything in absolute coordinates and does not have the ability to reason about solids, just surfaces. Basically if you want to model something like a bolt you need to create a cylinder for the shaft, a separate head of the bolt, and then a thread profile you can rotate around the cylinder. You must ensure there is enough overlap between these three separate parts so the resultant object is a single surface and not three separate ones.
You can use modules to create a semblance of relative measurements but you still cannot do things like “attach this surface of object A to that surface of object B)”. In practice this means that if you want to create something like a spacer or a bracket you can do that easily enough. But if you want to make a part that matches some real world design you are stuck doing a lot of caliper measurements and math to try to create a part that lines up correctly. The you 3D print it and find that you positioned some hole based on its edge and not center and so nothing quite fits.
OpenSCAD is easy to start but difficult to scale because of these limitations and because once you hard-code any measurement you are stuck with it. The “proper” way to do this is to give everything a variable but honestly that makes reasoning about how to line things up even more difficult. “Does base_width include the width of the vertical walls? What about the margin to make the parts fit together?”
I have never been able to understand how things like FreeCAD lay out their UI. TinkerCAD is relatively simple but clearly a lot less powerful. I did try cadquery which solved a lot of OpenSCAD’s issues by having all offsets be relative by default but also introduces a few issues of its own.
One tip I will give about OS: grab a copy of the latest beta/dev release. The renderer is several orders of magnitude faster.
> but you still cannot do things like “attach this surface of object A to that surface of object B)”
Sure you can, but openscad is an imperative language so you need to do it in an imperative manner.
a_cube_loc = [10, 5, 5];
a_cube_size = [2, 4, 1];
b_cube_loc = [a_cube_loc[0], a_cube_loc[1] + a_cube_size[1], a_cube_loc[2] ];
b_cube_size = [2, 4, 1];
translate(a_cube_loc) cube(a_cube_size);
translate(b_cube_loc) cube(b_cube_size);
It would be nice to have more declarative constraints. The solvespace file format is plain text and it almost feels like you could write it by hand, but that would be a lot of manual record keeping. and you would loose all that imperative goodness. Perhaps you could have an imperative layer(say python or lisp or forth) that outputs the declarative layer(solvespace) and then solvespace renders(picture or stl) the declarative layer.BOSL2 allows attaching when you define attachment points or something with attachment points defined for you (most everything in BOSL2).
Manifold backend also eliminates the need to avoid coincident faces.
Let me introduce to the awesomness of the BOSL2 screw module:
> I have never been able to understand how things like FreeCAD lay out their UI.
I'm 100% with you there. One of the most utterly confusing UI I've had to deal with.
And I suspect the answer is : the FreeCAD devs don't either.
> You must ensure there is enough overlap between these three separate parts so the resultant object is a single surface and not three separate ones.
(Post author here.)
This was a very weird thing to me I ran into and have thus far just sort of... accepted.
In Fusion, and other CAD software, if I have two faces end at the same point, unless I've specifically said to create them as separate bodies, they are joined, because they share a plane.
In OpenSCAD, in the tutorial, it has you extend an object 0.001 to ensure they overlap. To quote:
> In the example above, the second cube sits exactly on top of the first cube. This is something that should be avoided, as it’s not clear to OpenSCAD whether the two cubes form one object together. This issue can be easily solved by always maintaining a small overlap of about 0.001 - 0.002 between the corresponding objects. One way to do so is by decreasing the amount of translation along the Z axis from 10 unit to 9.999 units.
This struck me when making the example in my post. In line 47 I specifically add 1 to heightCompartment to ensure the opening extends past the top of the main body. If I didn't do that, this happens during preview: https://imgur.com/a/Amc1dK6 (That's an exported image from the latest nightly of OpenSCAD.)
But it doesn't happen during the actual render?
Still, that just feels... like there's something going on with a floating point value or something which, programatically, is probably correct... But from the perspective of someone trying to design something feels Very Wrong. Because I have a 20mm high box, I subtract a 19mm high box from it, starting 1mm up from the base. Why shouldn't the top be open? Why is it acceptable for it to be maybe kinda open but broken by design?