Site Information


 Loading... Please wait...

OpenSCAD Personal Library and Tips

Posted by Alex R English on

This is a library file I put together to make routine tasks easier in OpenSCAD. Features include some often-used constants, divisions of 360 degrees into different numbers of sections, chain hull, hex rod, and some features for working with 80/20 10-Series T-Slot. I'll provide some explanations and examples below to demonstrate how I use some of the items.

//Standard library of useful constants and some utility functions.
//Alex English - ProtoParadigm LLC
//Published under the CC BY-SA 4.0 license

IN = 25.4;
PI = 3.14159265359;
PHI = 1.61803398875;
E = 2.71828;
ROOT2 = 1.41421;
ROOT3 = 1.73205;
HEX = 2/ROOT3; //proportion of the radius of a circle inscribed in a hexagon with that of a circle that inscribes a hexagon (diameter or radius of points vs flats on a hexagon)

// Equal divisions of 360 into sections, mainly for use in for loops to iterate a rotation in even divisions. Latin and Greek prefixes both defined so either can be used.
d_bi = [0, 180];
d_duo = d_bi;
d_tri = [0, 120, 240];
d_quad = [0, 90, 180, 270];
d_tetra = d_quad;
d_quint = [0, 72, 144, 216, 288];
d_penta = d_quint;
d_sex = [0, 60, 120, 180, 240, 300];
d_hex = d_sex;
d_sept = [0, 360/7, 360/7*2, 360/7*3, 360/7*4, 360/7*5, 360/7*6]; //expressed as fractions because the numbers are messy
d_hept = d_sept;
d_oct = [0, 45, 90, 135, 180, 225, 270, 315];
d_non = [0, 40, 80, 120, 160, 200, 240, 280, 320];
d_ennea = d_non;
d_dec = [0, 36, 72, 108, 144, 180, 216, 252, 288, 324];
//11 omitted
d_dodec = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330];

//chains multiple child elements together with discreet hull operations, useful for complex and organic(ish) geometries - concept and implementation originally from Whosa Whatsis on G+ (as far as I'm aware)
module chain_hull() for (i = [0 : $children - 2]) hull() for(j = [i, i+1]) children(j);

//makes a hexagonal projection using the dimension of the diameter on flats of a hexagon; particularly useful for making the cutouts for captive nuts
module hex_rod(d, h) cylinder(d=d*HEX, h=h, $fn=6);

//makes a geometry that can be subtracted from a part to make a hole with the countersink needed for 80/20 t-slot bolts
module tslot_hole()
	translate([0, 0, -1]) cylinder(d=IN/4+1, h=50, $fn=16); //through-hole
	translate([0, 0, 3/16*IN+1]) cylinder(d=IN/2, h=50, $fn=24); //countersink

//makes a nub of the desired length to go on the bottom of a part to engage with t-slot to keep a part from rotating - this makes it possible for a part to be relatively secure with a single bolt mounting it. It should be shallow enough to not interfere with a t-slot nut
module tslot_nub(l)
	translate([0, -6.4/2, -2]) cube([l, 6.4, 2.1]);

//Update: 4/1/16 - Additions below

//translate child elements down 1 unit in the z-axis - this is a really common operation I use to avoid clipping issues that happen with coincident faces - typing down1() is faster than typing translate([0, 0, -1])
module down1() translate([0, 0, -1]) children();

//boolean xor module - credit goes to reddit user roman_fyseek in this post:
module xor(){

How to Use This (or any other) Library

Save the contents to a .scad file in the location where you save your other .scad files (or in a subdirectory - I use a subdirectory called library, and save mine as standard.scad).

Include the file in new projects using this code (with the filename you saved the library as, of course):

include <standard.scad>;

Or, if you put it in a subdirectory:

include <library/standard.scad>;

Protip: Keep in mind that you won't be able to render or compile a project and utilize anything from included files until you've saved it, since the file paths are relative to where the document you're working in is saved. It should be possible to specify absolute file paths (something like /home/alex/documents/scad/library/standard.scad on linux, or d:\docs\scad\library\standard.scad on windows, etc. [sorry Mac users, I don't know what your paths look like]), but this is often more trouble than just saving your document - and frequent saving is good practice anyway.

Now that your new design has access to the library you can call the modules or reference the variables from it. Here are some examples.

Use Cases and Examples



The constant I find myself using most often is IN. Whenever possible I try to work in metric (because it's clearly better), but I often find myself having to mate with imperial parts, or I'm using measurements someone gave me and I'm too lazy (efficient?) to do the conversion. To be honest there are also contexts in which I think in inches (mostly when making stuff for around the house, etc.).

The IN constant is the number of millimeters in an inch. So, say I want a 1 inch cube. I can just write:

cube([IN, IN, IN]);

Or say I want that cube to be half an inch tall:

cube([IN, IN, IN/2]);

Or maybe I want to make a 2 inch long cylinder as a stand-in for a 5/16 bolt:

cylinder(d=IN*5/16, h=IN*2);


Phi as a character can be used to represent different things in different contexts, but I use it here as a representation of the Golden Ratio. This number is useful for defining spirals, describing features from the natural world, and (as I use it) for finding aesthetic proportions.

For instance if I'm creating a box, like a housing for some electronics, and the exact dimensions can be arbitrary, but I need it to be at least 5 inches wide, I might define it like this:

cube([5*IN, 5*IN*PHI, 2*IN]);

This will create a cube (from which I can subtract geometries to make a box) that is 2 inches tall, 5 inches wide, and 8.09 inches (roughly) long, which looks like this:

Box (cube) in OpenSCAD, proportioned by the golden ratio.

While this may not seem very exciting, it's handy to have a convenient way to get nice-looking proportions for non-mechanical design work.


We do a lot of work with hex shapes - the dies for our filament production are machined from hex-stock, we work with a lot of nuts and bolts, for which it is useful to have matching entrapments or countersinks in printed parts. We also make assemblies that sometimes utilize hex geometries for angular alignment. It's dang convenient to have this ratio on hand to convert between the point-to-point and flat-to-flat (which is the dimension used to specify size for hex-stock, hex shafts, nuts, and bolt heads, among other things, undoubtedly) dimensions. An example of how this is used can be seen in the hex_rod module, which we'll look at down below.


In brief, the other constants provided are:

  • PI: the ratio of the circumference to the diameter of a circle - useful in a variety of contexts, mostly for conversions between diameters and circumferences, some trigonometry work, etc. 
  • E: Euler's number - useful when working with logarithms and exponentiation, some trig operations, probability distributions, and other areas. This might be the one value in here I've not actually used in OpenSCAD, but it's there anyway for that dark day when I need it.
  • Root2, Root3: The square root of two and the square root of three. These can also be obtained using the POW() function in OpenSCAD, but I've included them here both for convenience and because roots tend to be computationally intensive, so precomputing the value and saving it here might save me a few microseconds when compiling some part that uses a bunch of these roots. In general, these are mostly useful for doing geometrical calculations (such as for calculating the value for HEX, above), especially vector operations and volumetric calculations.


The divisions are fun ones. Say you want a pattern repeated so many times around a circle. You could do the math, or you could be a good, lazy coder and use some pre-baked arrays to do the work for you. As a simple example, lets consider a disk with 3 holes near the edge, evenly spaced. For the holes, you could manually place each one with coordinates (don't do this), or you could create three distinct holes, each placed with the same translation and then a distinct rotation... or you can use a for-loop. This is the intended use-case.

This can be done without the divisions in the include file, by doing something like this:

for(r=[0, 120, 240]) rotate([0, 0, r]) translate([50, 0, 0]) cylinder(r=5, h=10);

The divisions allow us to skip the step of having to figure out how to divide 360 degrees into however many equal parts are needed. The above, using the divisions in the include file looks like this:

for(r=d_tri) rotate([0, 0, r]) translate([50, 0, 0]) cylinder(r=5, h=10);

OpenSCAD code and rendering of three holes spaced with even divisions around a disk.

Nothing here changed other than the array of angles in the for-loop definition, but this is a handy shortcut. It's even handier when you want to change the number of divisions or use a number of divisions for which it would take a moment to type out all the angles. Given the above, what if we want six divisions instead of three? Just change d_tri to d_hex (or d_sex if you prefer Latin prefixes over Greek).

for(r=d_hex) rotate([0, 0, r]) translate([50, 0, 0]) cylinder(r=5, h=10);

OpenSCAD code and rendering of six holes spaced with even divisions around a disk.

Ok, going for broke, here's what twelve divisions looks like:

for(r=d_dodec) rotate([0, 0, r]) translate([50, 0, 0]) cylinder(r=5, h=10);

OpenSCAD code and rendering of twelve holes spaced with even divisions around a disk.

There may be other uses for the divisions of 360, but this was the use case I created them for.

Chain Hull

As far as I'm aware, the idea and implementation for chain_hull came from this Google+ post by Whosa whatsis (implementation in comments). I'm going to quote Whosa whatsis on his explanation since it's as straightforward as it gets:

That's where I have a series of shapes, say circles A-F, and I do a hull of A and B, a hull of B and C, a hull of C and D, etc. They can be different sizes, and they can be arranged in a crescent, S, or in 3d even a helical shape. If I did a hull of all of them at once, it would fill in the concave spaces inside those shapes, but chain-hulling allows you to preserve that interior space.

The idea here is to make more complex arbitrary shapes by hulling together consecutive pairs of shapes. Here is what a set of three cylinders looks like before the chain hull:

OpenSCAD cylinders before chain-hull

And the results after adding the chain_hull:

OpenSCAD cylinders with chain-hull applied

You can see that the syntax for using the module is the same as for the standard hull module or boolean operations (difference, union, and intersection) (and others).

Note how chain_hull is different from a regular hull operation:

OpenSCAD hull operation (as opposed to chain-hull)

Also note that the order of the elements matters because each pair of elements is hulled together in order. Switching the last two elements gives us this result:

OpenSCAD demonstration showing that order of the children matters when applying chain_hull.

There is also an important limitation to the chain_hull module. It needs a list of "child" elements to act on, and acts on each pair in turn. Because of the "implicit union" applied to the output of for-loops, the output is a single element even if the geometries in its output are not connected. Here is an example showing some cylinders plotted along an exponential curve using a for loop, along with the result of applying chain_hull to the same.

Problems with chain_hull on the output of a for-loop in OpenSCAD

We can see that the result from the chain-hull looks just like what we would expect is we applied a regular convex hull (hull()) - it treated all of the elements as one element and drew us the shape that bounds them all.

The solution to this is not particularly straightforward. You more or less have to perform the chain-hull in the context of the for-loop without the benefit of the module, and with a little extra thought. The idea is to take whatever would have been in the for loop and add an additional layer of loop to encompass pairs. So, if a for loop created elements A, B, C, D, E, and F, you would need one for loop that establishes the values to create those elements, and another that can create them in pairs.

Here is an example of a for loop creating the same cylinders as in the above example.

for(a = [0:5]) translate([10*a, 2*pow(a,2), 0]) cylinder(r=5, h=2);

Remember, the output of that loop is a single element, as though they had been unioned together, even though there are six distinct shapes. Those shapes (A through F) have to be generated as pairs, A and B, B and C, C and D, D and E, E and F. There are always going to be one fewer pairs than elements (five pairs for six elements). In this case, the original loop iterated from 0 to 5. Since we have one fewer pair than elements, we will now iterate from 0 to 4 to generate the five pairs. Each of those pairs goes through its own hull operation. The pairs are created (in this case) by doing the same operation as the original, but using the current index and the current index plus one to generate the two geometries.

Here is what the code looks like:

for(a = [0:4]) hull() for(b = [a:(a+1)]) translate([10*b, 2*pow(b,2), 0]) cylinder(r=5, h=2);

And the result:

Workaround for problems using chain_hull with for-loops.

Unfortunately, while the principle of this method should be able to be applied in many circumstances, its implementation is not generalizable and cannot be made into a module (as far as I can tell).

Hex Rod

Hex rod is pretty straightforward, it makes a hex rod/shaft. It's just a cylinder with $fn=6 (only six sides). The key here is that it does the math for you to let you specify the hex dimension as a flat-to-flat measurement. As for syntax, use it just like you would the cylinder() primitive, just don't specify $fn, $fa, etc.

A hex rod made with the following code:

hex_rod(d=IN/2, h=IN*2);

Looks like this:

Hex Rod / Shaft / Cylinder in OpenSCAD

T-Slot Hole

This creates the inverse of a hole to use with 1/2 inch (length) 1/4-20 pan head bolts on 80/20 10-series T-slot aluminum extrusion - though there might be other hardware that it works well with. The geometry this cuts out will provide clearance for getting the bolt down to the end of the countersink, with a proper thickness of material for the screw to sinch down before bottoming out on the other side of the T-slot nut.

Here is what it looks like with the subtracted geometry highlighted (debug modifier, #).

Countersunk hole (with highlighting) for t-slot bolt in OpenSCAD

And here it is without the highlighting:

Countersunk hole (without highlighting) for t-slot bolt in OpenSCAD

T-Slot Nub

The idea behind this nub (for lack of a better word - really, if you have a better word I'd love to rename it) is that it can slip into the slot of T-Slot to secure it from rotation or translation perpendicular to the direction of the slot. On parts with low load this allows a single bolt to hold the part in place without it being able to rotate (and potentially allow the bolt to unscrew itself).

Here is what the nub looks like attached to the bottom of a cube (viewed upside down, note the axis markers):

OpenSCAD nub / nibblet / protrusion / track as a rotational constraint for a part to mount on t-slot.

And here is what it looks like on that cube with a tslot_hole() in it (also upside down):

OpenSCAD nub / nibblet / protrusion / track as a rotational constraint for a part to mount on t-slot - shown with hole for mounting bolt.

Other Libraries

There are a few libraries others have written that I keep around and find myself using now and again. They're definitely worth a look.

  • MCAD - Extremely useful library featuring common shapes, hardware, and components; very useful for designing things to mate with bearings, motors, and common hardware. There's a lot to explore here.
  • Wedge - A small library I wrote for making wedge shapes. It's fairly narrow in focus, but handy to have when you need it.
  • Mesh Screen - Handy for making filters, strainers, etc. A good example is a mason jar sprout strainer lid I designed.

These libraries can be included in a main library file so you can include a single library and have access to your entire suite of library files, but I suspect this would have an impact on performance (maybe not, I don't know) and I don't use any of these other libraries consistently enough to worry about not having to include them individually when I need them.

What libraries do you use? What constants, functions, modules, or other shortcuts do you use in your include file(s)? Give a shout and let me know what you find useful.

comments powered by Disqus