Using OpenSCAD to model 3D structures

Sergey Jarochkin, 123RF

Sergey Jarochkin, 123RF

Block & Slice

The program OpenSCAD makes it possible to construct 3D objects via just a few commands. STL Exporter makes the software interesting for users who have a 3D printer.

OpenSCAD makes you feel right at home once you know that a radius defines a sphere or that height and diameter define the surface of a cylinder. The OpenSCAD design software also lets you create structures for printing with a 3D printer. The tests performed for this article produced a cap for a USB stick, a model airplane, Lego bricks, and a replacement key.

Popular distributions offer OpenSCAD for installation, which is usually the 2104 version. The software homepage [1] explains how to download the updated version 2015.03-1. Downloading the newer version is worthwhile because it offers the possibility of directly incorporating text objects.

Introduction

Once the software starts, a window will open with an input area to the left, an output area to the right and a console. Various buttons offer basic functions. The icons to the left in the editor window are for common tasks such as opening and saving files, and typical editing actions, such as undoing, repeating and indenting.

The two cube icons start the program either for rapid CSG prototyping when you intend to do an STL export or for rendering via CGAL (see the "Vocabulary" box for more info). The same actions are started via the F5 and F6 function keys. You should try out the interfaces for the output window using a small program.

Vocabulary

  • CSG (which stands for Constructive Solid Geometry) is a technique used in solid modeling. The technique allows the user to build three dimensional objects by combining fundamental geometric structures.
  • STL is derived from stereolithography. STL denotes the standard file format for describing surfaces.
  • CGAL stands for Computational Geometry Algorithms Library. It is a library for rendering 3D surfaces.

To draw a sphere, enter the sphere(); command into the editor. Remember to always include the semicolon at the end of each command. Then, press the F5 function key or click on the cube icon with two prongs. This causes the software to execute the one-line program. In the output area on the right, you will see a blue, angular shape (Figure 1).

Figure 1: You can create the basis for a solid with a one-line command.

You can use the icon bar to change and rotate the viewing angle of the object. You can also change the view between orthographic, where the vanishing point is at infinity, and perspective projection, where distant objects appear smaller.

The easiest way to do this is to move the viewing angle with the mouse. The scroll wheel changes the distance, the left mouse button changes the viewing angle and the right button changes the position. The coordinates for the imaginary camera are shown in the status bar at the bottom.

This first program provides a glimpse into the idiosyncrasies of OpenSCAD. The program also assigns default values to most variables. If you do not enter a radius or position for the solid then the program will assume a sphere having a diameter of one unit at the origin of the coordinate system.

The software does not recognize any curved surfaces. Instead, it approximates the desired shape using a grid of triangles. The menu option View | show_edges this grid visible. Via the $fn variable, you can control the number of edges, as in the following example.

$fn=200;
sphere();

Although the rendering now takes longer, you will get an almost perfect sphere. Instead of globally modifying the variable, the application offers the possibility of restricting it to this one sphere.

sphere();
translate([2,0,0]) sphere(r=2, $fn=200);

At the coordinate center, you will see both a rough rendering of the sphere and a properly formed sphere with a radius of r=2 units (Figure 2). You can prevent the spheres from overlapping with translate() . This moves the sphere by the vector with the coordinates x , y , and z . In our case, the value for x is 2 units.

Figure 2: Using the translate() command lets you move the two objects next to one another without any overlap.

Many commands have an impact on the subsequent object. If a semicolon were to follow the translate command, then the instruction would not affect the subsequent sphere.

The next example involves the construction of a pencil. The object consists of a cylinder with a height of h=50 and a radius of r=5 . Because the pencil will have six edges, you should restrict the rendering to six surfaces via $fn=6 , as follows:

cylinder(h=50, r=5, $fn=6);

For this example, a cylinder with an upper radius of r2=5 , a lower radius of r1=0 , and a height of h=15 serves as the cone.

For the software to smooth out all objects thoroughly except the pencil, you should globally set the variable $fn to 50 by prefixing the assignment to the construction of the cylinder:

$fn=50;
cylinder(h=15, r1=0, r2=60);

The pencil point is created with the cone. The command intersection() restricts the view to elements belonging to both the cone and the pencil shaft. The rotate() command tilts the pencil (Figure 3). As with translate() , this command also affects the element that follows. Therefore, it does not end with a semicolon.

Figure 3: You can create the basic shape of a pencil using a cone and a cylinder.

If you pass only one vector into the rotate() function as shown in the example, then the first value designates the angle of rotation around the X axis, and the second value is used for the subsequent rotation around the Y and Z axis. If you also pass to rotate() and also a value for an angle, then it interprets the vector as a rotational axis.

Since its 2015 version, the program has had a text() command, which generates 2D text. The text really only becomes visible in the CGAL renderer because the quick view has as kludge that extrudes the text with a thickness of one unit. The text actually looks plastic when the linear_extrude() command is used.

Print Template

You can create the software objects using just a few program lines. These objects are suitable for use with a 3D printer. Here I use a cap for a USB stick as an example. It requires commands for only three objects. These include commands for a cuboid, which determines the outer measurements of the cap, commands for a second cuboid corresponding to the size of the USB plug, and finally the difference() command, which subtracts the two cuboids. Listing 1 shows these commands. Figure 4 shows the results.

Listing 1

A USB Stick

difference(){
 translate([0,0,5]) color("red", 0.8) cube([5.5, 13, 12], center=true);
 translate([0,0,15]) color("grey", 1) cube([4.5, 12, 30], center=true);
}
Figure 4: It is possible to create a cap for a USB stick from two cuboids.

The file format STL is understood by most Slice programs for 3D printers. Saving a file with a corresponding template requires that the CGAL renderer finishes successfully. The color information will get lost in the process. Then, you should save the result either via the STL icon or via File | Export | Export_STL .

The software does not understand physical dimensions – only units. The program that further processes the data therefore expects an instruction indicating whether the opening of the cap is 4.5x12 inches or millimeters, and whether a scaling factor for adapting the contraction will be employed. If you put the projection(cut=true) command first, then OpenSCAD defines the cross-sectional area inside of the X/Y plane. This is how you control the thickness of the wall of the cap.

To illustrate the intended use of the cap, you should add a schematic drawing of the USB stick to the script. The color() command colors the object. It understands the names of colors in English and in the form of an RGB vector where the three components determine the red, green, and blue amounts. This is how the color([1,1,0]) command creates the color yellow. You can add transparency as a fourth coordinate or as an individual number when you name the colors. An example here would be color("yellow", 0.5) .

Building a Plane

A model airplane also consists of basic elements. A wing is made when you create a separate module and name it wing . A module is similar in principle to a function. It accepts parameter and delivers an object in return, in this case a wing (Listing 2, line 24).

Listing 2

An Airplane

01 $fn=100;
02 sep() airplane();
03
04 module airplane(){
05 // Wings
06 wing(0.7);
07 translate([18,0,0]) wing(1);
08 translate([0,0,2.1]) rotate([90,-20,0]) wing(0.45);
09 // Hull
10 hull(){
11  translate([-3,0,0]) sphere(1.5);
12  translate([24,0,0]) sphere(3);
13 };
14 // Cockpit
15 translate([19,0,2]) scale([2,1,1]) color("red",0.6) sphere(2);
16 //Propeller
17 translate([26.5,0,0]) scale([2,1,1]) color("grey") sphere(1);
18 translate([27.3,0,0]) rotate([0,90,0]) color("grey",0.5) cylinder(h=0.5, r=5);
19 // Wing Module
20 module wing(s=1){
21  rotate([90,0,0])
22  scale([3*s,0.4*s,1*s*s])
23  cylinder(h=35,r=1,center=true);
24  };
25 };
26
27 module sep(){
28  translate([0,0,-0.5]) difference(){
29  children();
30  translate([-40,-40,0]) cube(100);
31  };
32  translate([0,0,0.5]) intersection(){
33  children();
34  translate([-40,-40,0]) cube(100);
35  };
36 };

The curly braces are necessary because a module typically contains more than one object. Here, I will show how to make the wings from a deformed cylinder.

scale([3,0.4,1]) cylinder(h=35,r=1)

The command stretches the X axis by a factor of 3, compresses the Y axis by a factor of 0.4, and leaves the Z axis alone. The call wing(1) creates the hydrofoils, wings(0.7) the elevator assembly. The translate() command, which is found in the script as a prefix, moves the components into the correct position.

The fuselage here consists of two spheres – one in front and one in back. The hull() command encircles both objects with a shell and connects them to a new object. You should add the other elements according to the pattern presented above (Figure 5).

Figure 5: To prepare the small airplane for 3D printing, you should divide the drawing to obtain a smooth surface.

One way to print the model with a 3D printer is to divide the object into two parts to achieve a smooth bottom layer. The module sep() performs the separation. The object given by children() , or child() in case you are using a pre 2015 version, is the object that sep() works on. The difference() command subtracts the upper part of the airplane and intersection() precisely describes the space shared in common with the cube.

Modularizing Code

The program is more manageable when you store the main part of the program in its own file. An example using Lego bricks can clarify this method. Building these bricks functions just like the construction of the airplane from individual geometric objects. It is tiresome to measure and place the elements, so I relied on one of the numerous libraries for assistance [2].

Given the file name for the Lego bricks data lego_brici_builder.scad , then two lines are enough to display one 6x2 brick.

use <lego_brici_builder.scad>
brick(6,2,3);

Additional commands can even make it possible to build a tower. The loop for (i=[0:1:6]) iterates the variable i from 0 up to 6 inclusively in increments of one. Because the loop contains only one object, curly braces are not required. The rotate() and translate() commands rotate and raise the bricks with each iteration (Figure 6).

Figure 6: When code is moved to a module in a separate file, you can produce models by looping over several instances of the module.

If you would like to look at the construction of the bricks, replace the number 6 in the loop definition by the variable $t*10 and select the menu option View | animate . This creates a new input line underneath the output window. In this line, enter the number 10 for Steps and a 1 for FPS (frames per second) .

The internal variable $t rises by increments of one tenth every second with these settings. Once it reaches 1 , it will start over again with 0 . The loop rebuilds the tower every second, each time just a bit more of it. Images are saved when you activate the checkbox on the right next to the Steps field.

A program like Ffmpeg makes a video of the images. Because the software controls the position of the observer via an internal variable, it is even possible to take tracking shots.

Leaving keys lying about, even in digital image form can create security problems. In this example, I demonstrate this state of affairs with the image of a key found on Wikimedia Commons [3]. I used a straightforward digitizing program to define 25 reference points on the key bit. These values function as the vector with the 2D points serving as components. You should convert the points into a polygon chain via the following command. Afterward, you can convert the chain into a key bit that has a thickness of 0.2 centimeters:

linear_extrude(height=0.2) polygon(points);

Four additional commands via difference() cut two slots in the upper side and two slots into the underside of the key. Then, comes a ring for holding the key and the 3D print template is ready to use (Figure 7).

Figure 7: It is possible to easily create duplicates for simple keys.

Visualization

OpenSCAD is also suitable for visualizing larger volumes of data. This would include things like the location for all magnitude 5 earthquakes and stronger which occurred in the previous year [4].

The graphic displays the geographical location of the earthquake, the strength expressed in relationship to the diameter of a sphere, and the depth of the earthquake focus, which appears in the arrangement underneath the coordinate grid and also by means of color (Figure 8).

Figure 8: The program is suitable for infographics as shown by the example involving the distribution of earthquakes of at least magnitude 5.

The coordinates and strength of the earthquakes are found in two arrays in the eq03.scad file. The code used for the example uses the coordinates of several cities for purposes of orientation. Coordinates and names are found in the plock and plockname arrays.

The loop iterates over all elements. The number of elements is given by the len() command. The self-defined function ku2ka determines the cartesian coordinates x , y , and z from the length, width, and depth of the spherical coordinates. The function accepts one vector and returns the computed vector.

The most complex task is building the grid. OpenSCAD does not have one-dimensional lines without filling. As a result, you should construct these in the form of 3D objects from extruded slices of circles. The small black sphere in the graphic represents the city of Honolulu in Hawaii. The text is not readable in the reproduction. To the southwest, there are the Pacific and Australian plates that collide against one another. The earthquakes on the surface are represented by the color green, and the deep earthquakes can be recognized by the color red.

Search for Errors

The most important document for OpenSCAD is found in Help | Cheat_sheet . This is a complete list of commands recognized by the software [5]. Error messages that appear during script compilation appear in the console.

You will notice that a semicolon is missing when the program stumbles when switching to a succeeding command. The actual error is therefore to be found in the line that occurs before the program is interrupted. It becomes more difficult to locate semicolons that are syntactically correct but logically false. For instance, if the transformation translate([0,0,1]) is concluded with a character, this is not an error but the transformation does not produce output.

When dividing geometric objects, it can be important to maintain an overview of which portion comes from which object. Placing the pound symbol (# ) in front of the command gives you this overview. The software will show the object as half transparent.

Placing an asterisk (* ) in front blocks a command line. An exclamation mark (! ) blocks the execution of all other lines, which in effect only shows the result of the line under consideration. The echo command writes the values of variables or also results of expressions (echo(3 * 4) ) to the console.

Conclusions

It only takes a few lines to generate complex geometric structures with OpenSCAD. Thanks to the STL transformation, other programs can also understand the results. Most of the Slicer programs can successfully implement the results for a 3D print provided the user specifies the dimensions for the length.

The 3D renderer Blender dresses up the SLT models with lighting effects and reflections and in doing so utilizes the dimensional accuracy of the models. If you are thinking of trying OpenSCAD out online without installing it, you should take a look at Openjscad [6].

Listing 3

Plotting Earthquakes

$fn=100;
$vpd=5500; // camera distance
$vpr=[88,0,300]; // camera orientation
r=1000; // Radius
// The file eq03.scad contains two arrays
// with the positions (eqlock) and the derivative
// sizes for earthquake magnitude and depth (eqspec).
include <eq03.scad>
// coordinates of some selected points
plock=[
[52, 13, 0], // Berlin
[48, 11, 0], // Munich
[35, 139, 0], // Tokyo
[21, -157, 0] // Honolulu
];
// Designation of the selected points
plockname=["Berlin", "Munich", "Tokyo", "Honolulu"];
// Output for eqlock and eqspec
for (i=[0:len(eqlock)-1]){
 translate(ku2ka(eqlock[i])) color([eqspec[i][0],1-eqspec[i][0],0]) sphere(eqspec[i][1]);
}
// Output of the selected points
for (i=[0:len(plock)-1]){
 translate(ku2ka(plock[i])) color("black") sphere(10);
 translate(ku2ka(plock[i])) color("black") text(text=plockname[i], size=30);
}
sphere(450); //draws inner sphere
grid(15); //draws grid
// transforms sphere coordinates into
function ku2ka(v)= [
 cos(v.y) * (r-v.z) * sin(90-v.x),
 sin(v.y) * (r-v.z) * sin(90-v.x),
 (r-v.z) * cos(90-v.x)];
// draws a height and width grid
module grid(d=30){
 mirrorc()
 rotate_extrude(){
 for (i=[0:d:85]){
 a= ku2ka([0,i,0]);
 translate(a) circle(5);
 };
 };
 for (i=[0:d:185])
 rotate([0,0,i])
 rotate([90,0,0])
 rotate_extrude()
 translate([r,0,0]) circle(5);
}
// Help module, for mirroring a block
module mirrorc(v=[0,0,1]){
 children();
 mirror(v) children();
};