OpenSCAD User Manual/Other Language Features

From Wikibooks, open books for an open world
Jump to: navigation, search

Special variables[edit]

Special variables provide an alternate means of passing arguments to modules and functions. All user, or OpenSCAD, defined variables starting with a '$' are special variables, similar to special variables in lisp. Modules and function see all outside variables in addition to those passed as arguments or defined internally.

The value for a regular variable is assigned at compile time and is thus static for all calls.

Special variables pass along their value from within the scope (see scope of variables) from which the module or function is called. This means that special variables can potentially have a different value each time a module or function is called.

regular  = "regular global";
$special = "special global";
module show() echo("         in show    ", regular,"   ", $special );

echo ("         outside    ", regular,"   ", $special );
          // ECHO: "         outside    ", "regular global", "   ", "special global"
for ( regular = [0:1] ){ echo("in regular loop     ", regular,"   ", $special ); show();}
          // ECHO: "in regular loop     ", 0, "   ", "special global"
          // ECHO: "         in show    ", "regular global", "   ", "special global"
          // ECHO: "in regular loop     ", 1, "   ", "special global"
          // ECHO: "         in show    ", "regular global", "   ", "special global"

for ( $special = [5:6] ){ echo("in special loop     ", regular,"   ", $special ); show();}
          // ECHO: "in special loop     ", "regular global", "   ", 5
          // ECHO: "         in show    ", "regular global", "   ", 5
          // ECHO: "in special loop     ", "regular global", "   ", 6
          // ECHO: "         in show    ", "regular global", "   ", 6

          // ECHO: "         in show    ", "regular global", "   ", "special global"

This is useful when multiple arguments need to be passed thru several layers of module calls.

Several special variables are already defined by OpenSCAD.

$fa, $fs and $fn[edit]

The $fa, $fs and $fn special variables control the number of facets used to generate an arc:

$fa is the minimum angle for a fragment. Even a huge circle does not have more fragments than 360 divided by this number. The default value is 12 (i.e. 30 fragments for a full circle). The minimum allowed value is 0.01. Any attempt to set a lower value will cause a warning.

$fs is the minimum size of a fragment. Because of this variable very small circles have a smaller number of fragments than specified using $fa. The default value is 2. The minimum allowed value is 0.01. Any attempt to set a lower value will cause a warning.

$fn is usually 0. When this variable has a value greater than zero, the other two variables are ignored and full circle is rendered using this number of fragments. The default value is 0.

The higher the number of fragments, the more memory and CPU consumed, large values will bring many systems to their knees. Depending on the design, $fn values, and the corresponding results of $fa & $fs, should be kept small, at least until the design is finalised when it can be increased for the final result. A $fn over 100 is not recommended or only for specific circumstances, and below 50 would be advisable for performance.

TIP: If you want to create a circle/cylinder/sphere which has a axis aligned integer bounding box (i.e. a bounding box that has integral dimensions, and an integral position) use a value of $fn that is divisible by 4.

When $fa and $fs are used to determine the number of fragments for a circle, then OpenSCAD will never use fewer than 5 fragments.

This is the C code that calculates the number of fragments in a circle:

      int get_fragments_from_r(double r, double fn, double fs, double fa)
             if (r < GRID_FINE) return 3;
             if (fn > 0.0) return (int)(fn >= 3 ? fn : 3);
             return (int)ceil(fmax(fmin(360.0 / fa, r*2*M_PI / fs), 5));

Spheres are first sliced into as many slices as the number of fragments being used to render a circle of the sphere's radius, and then every slice is rendered into as many fragments as are needed for the slice radius. You might have recognized already that the pole of a sphere is usually a pentagon. This is why.

The number of fragments for a cylinder is determined using the greater of the two radii.

The method is also used when rendering circles and arcs from DXF files. The variables have no effect when importing STL files.

You can generate high resolution spheres by resetting the $fX values in the instantiating module:

      $fs = 0.01;

or simply by passing the special variable as parameter:

      sphere(2, $fs = 0.01);

You can even scale the special variable instead of resetting it:

      sphere(2, $fs = $fs * 0.01);


The $t variable is used for animation. If you enable the animation frame with view->animate and give a value for "FPS" and "Steps", the "Time" field shows the current value of $t. With this information in mind, you can animate your design. The design is recompiled every 1/"FPS" seconds with $t incremented by 1/"Steps" for "Steps" times, ending at either $t=1 or $t=1-1/steps.

If "Dump Pictures" is checked, then images will be created in the same directory as the .scad file, using the following $t values, and saved in the following files:

  • $t=0/Steps filename="frame00001.png"
  • $t=1/Steps filename="frame00002.png
  • $t=2/Steps filename="frame00003.png"
  • . . .
  • $t=1-3/Steps filename="frame<Steps-2>.png"
  • $t=1-2/Steps filename="frame<Steps-1>.png"
  • $t=1-1/Steps filename="frame00000.png"

Or, for other values of Steps, it follows this pattern:

  • $t=0/Steps filename="frame00001.png"
  • $t=1/Steps filename="frame00002.png
  • $t=2/Steps filename="frame00003.png"
  • . . .
  • $t=1-3/Steps filename="frame<Steps-2>.png"
  • $t=1-2/Steps filename="frame<Steps-1>.png"
  • $t=1-1/Steps filename="frame<Steps-0>.png"
  • $t=1-0/Steps filename="frame00000.png"

Which pattern it chooses appears to be an unpredictable, but consistent, function of Steps. For example, when Steps=4, it follows the first pattern, and outputs a total of 4 files. When Steps=3, it follows the second pattern, and also outputs 4 files. It will always output either Steps or Steps+1 files, though it may not be predictable which. When finished, it will wrap around and recreate each of the files, looping through and recreating them forever.

$vpr, $vpt and $vpd[edit]

These contain the current viewport rotation and translation and camera distance - at the time of doing the rendering. Moving the viewport does not update them. During an animation they are updated for each frame.

  • $vpr shows rotation
  • $vpt shows translation (i.e. won't be affected by rotate and zoom)
  • $vpd shows the camera distance [Note: Requires version 2015.03]


 cube([10, 10, $vpr[0] / 10]);

which makes the cube change size based on the view angle, if an animation loop is active (which does not need to use the $t variable)

You can also make bits of a complex model vanish as you change the view.

All three variables are writable but only assignments at the top-level of the main file will have an effect on the viewport. [Note: Requires version 2015.03]


 $vpr = [0, 0, $t * 360];

which allows a simple 360 degree rotation around the Z axis in animation mode.

The menu command Edit - Paste Viewport Rotation/Translation copies the current value of the viewport, but not the current $vpr or $vpt.

Echo Statements[edit]

This function prints the contents to the compilation window (aka Console). Useful for debugging code. Also see the String function str().

Numeric values are rounded to 5 significant digits.

The OpenSCAD console supports a subset of HTML markup language. See Qt Docs for details.

It can be handy to use 'variable=variable' as the expression to easily label the variables, see the example below.

Usage examples[edit]

Usage examples:

echo("This is a cylinder with h=", my_h, " and r=", my_r);
echo(my_h=my_h,my_r=my_r); // shortcut
cylinder(h=my_h, r=my_r);
echo("<b>Hello</b> <i>Qt!</i>");

Shows in the Console as

ECHO: "This is a cylinder with h=", 50, " and r=", 100
ECHO: my_h = 50, my_r = 100
ECHO: "Hello Qt!"

Rounding examples[edit]

An example for the rounding:


if(a==b){ //while echoed the same, the values are still distinct 
    echo ("a==b");
}else if(a>b){
    echo ("a>b");
}else if(a<b){
    echo ("a>b");
    echo ("???");

Small and large Numbers[edit]

echo(c); //1e+06
echo(d); //2e-06


Working HTML examples:

echo("<b>Bold</b> <i>italic</i> <big>big</big>");
echo("<font color='red'>red</font> <font color='green'>green</font> <font color='blue'>blue</font>");

not really working examples:

echo("<img src=''></img>");
echo("<a href=''>wikibooks</a>");

Note: the Output can be copy and pasted into OpenOffice, where both the image and the link work fine.


Forces the generation of a mesh even in preview mode. Useful when the boolean operations become too slow to track.

Needs description.

Usage examples:

render(convexity = 2) difference() {
 cube([20, 20, 150], center = true);
 translate([-10, -10, 0])
  cylinder(h = 80, r = 10, center = true);
 translate([-10, -10, +40])
  sphere(r = 10);
 translate([-10, -10, -40])
  sphere(r = 10);


Surface reads Heightmap information from text or image files.


String. The path to the file containing the heightmap data.
Boolean. This determines the positioning of the generated object. If true, object is centered in X- and Y-axis. Otherwise, the object is placed in the positive quadrant. Defaults to false.
Boolean. Inverts how the color values of imported images are translated into height values. This has no effect when importing text data files. Defaults to false. [Note: Requires version 2015.03]
Integer. The convexity parameter specifies the maximum number of front sides (back sides) a ray intersecting the object might penetrate. This parameter is only needed for correctly displaying the object in OpenCSG preview mode and has no effect on the final rendering.

Text file format[edit]

The format for text based heightmaps is a matrix of numbers that represent the height for a specific point. Rows are mapped to the Y-axis, columns to the X axis. The numbers must be separated by spaces or tabs. Empty lines and lines starting with a # character are ignored.


[Note: Requires version 2015.03]

Currently only PNG images are supported. Alpha channel information of the image is ignored and the height for the pixel is determined by converting the color value to Grayscale using the linear luminance for the sRGB color space (Y = 0.2126R + 0.7152G + 0.0722B). The gray scale values are scaled to be in the range 0 to 100.


Example 1:

surface(file = "surface.dat", center = true, convexity = 5);
%translate([0,0,5])cube([10,10,10], center =true);
10 9 8 7 6 5 5 5 5 5 
9 8 7 6 6 4 3 2 1 0 
8 7 6 6 4 3 2 1 0 0
7 6 6 4 3 2 1 0 0 0
6 6 4 3 2 1 1 0 0 0
6 6 3 2 1 1 1 0 0 0
6 6 2 1 1 1 1 0 0 0
6 6 1 0 0 0 0 0 0 0
3 1 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0


Openscad surface example x1.png

Example 2

 // example010.dat generated using octave:
 // d = (sin(1:0.2:10)' * cos(1:0.2:10)) * 10;
 // save("example010.dat", "d");
 intersection() {
   surface(file = "example010.dat", center = true, convexity = 5);
   rotate(45, [0, 0, 1]) surface(file = "example010.dat", center = true, convexity = 5); 

Openscad surface example x2.png

Example 3:

[Note: Requires version 2015.03]

// Example 3a
scale([1, 1, 0.1])
  surface(file = "smiley.png", center = true);
// Example 3b
scale([1, 1, 0.1])
  surface(file = "smiley.png", center = true, invert = true);
Input image
Input image
Surface output
Example 3a: surface(invert = false)
Surface output inverted
Example 3b: surface(invert = true)
Example 3: Using surface() with a PNG image as heightmap input.


The search() function is a general-purpose function to find one or more (or all) occurrences of a value or list of values in a vector, string or more complex list-of-list construct.

Search Usage[edit]

search( match_value , string_or_vector [, num_returns_per_match [, index_col_num ] ] );

Search Arguments[edit]

  • match_value
  • Can be a single value or vector of values.
  • Strings are treated as vectors-of-characters to iterate over; the search function does not search for substrings.
  • Note: If match_value is a vector of strings, search will look for exact string matches.
  • See Example 9 below.
  • string_or_vector
  • The string or vector to search for matches.
  • num_returns_per_match (default: 1)
  • By default, search only looks for one match per element of match_value to return as a list of indices
  • If num_returns_per_match > 1, search returns a list of lists of up to num_returns_per_match index values for each element of match_value.
  • See Example 8 below.
  • If num_returns_per_match = 0, search returns a list of lists of all matching index values for each element of match_value.
  • See Example 6 below.
  • index_col_num (default: 0)
  • When string_or_vector is a vector-of-vectors, multidimensional table or more complex list-of-lists construct, the match_value may not be found in the first (index_col_num=0) column.
  • See Example 5 below for a simple usage example.

Search Usage Examples[edit]

See example023.scad included with OpenSCAD for a renderable example.
Index values return as list[edit]
Example Code Result











data=[ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];

search("a", data, num_returns_per_match=0);

[[0,4]] (see also Example 6 below)

Search on different column; return Index values[edit]

Example 5:

 data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",3] ];
 search(3, data, num_returns_per_match=0, index_col_num=1);


Search on list of values[edit]

Example 6: Return all matches per search vector element.

 data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
 search("abc", data, num_returns_per_match=0);



Example 7: Return first match per search vector element; special case return vector.

 data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
 search("abc", data, num_returns_per_match=1);



Example 8: Return first two matches per search vector element; vector of vectors.

 data= [ ["a",1],["b",2],["c",3],["d",4],["a",5],["b",6],["c",7],["d",8],["e",9] ];
 search("abce", data, num_returns_per_match=2);


Search on list of strings[edit]

Example 9:

 lTable2=[ ["cat",1],["b",2],["c",3],["dog",4],["a",5],["b",6],["c",7],["d",8],["e",9],["apple",10],["a",11] ];
 echo(str("Default list string search (",lSearch2,"): ",l2));


 ECHO: "Default list string search (["b", "zzz", "a", "c", "apple", "dog"]): [1, [], 4, 2, 9, 3]"
Getting the right results[edit]
// workout which vectors get the results
v=[ ["O",2],["p",3],["e",9],["n",4],["S",5],["C",6],["A",7],["D",8] ];
echo(v[0]);                                     // -> ["O",2]
echo(v[1]);                                     // -> ["p",3]
echo(v[1][0],v[1][1]);                          // -> "p",3
echo(search("p",v));                            // find "p" -> [1]
echo(search("p",v)[0]);                         // -> 1
echo(search(9,v,0,1));                          // find  9  -> [2] 
echo(v[search(9,v,0,1)[0]]);                    // -> ["e",9]
echo(v[search(9,v,0,1)[0]][0]);                 // -> "e"
echo(v[search(9,v,0,1)[0]][1]);                 // -> 9
echo(v[search("p",v,1,0)[0]][1]);               // -> 3
echo(v[search("p",v,1,0)[0]][0]);               // -> "p"
echo(v[search("d",v,1,0)[0]][0]);               // "d" not found -> undef
echo(v[search("D",v,1,0)[0]][1]);               // -> 8

OpenSCAD Version[edit]

version() and version_num() will return OpenSCAD version number.

  • The version() function will return the OpenSCAD version as a vector, e.g. [2011, 09, 23]
  • The version_num() function will return the OpenSCAD version as a number, e.g. 20110923

parent_module(n) and $parent_modules[edit]

$parent_modules contains the number of modules in the instantiation stack. parent_module(i) returns the name of the module i levels above the current module in the instantiation stack. The stack is independent of where the modules are defined. It's where they're instantiated that counts. This can be used to e.g. build BOMs.


 module top() {
 module middle() {
 top() middle() echo(parent_module(0)); // prints "middle"
 top() middle() echo(parent_module(1)); // prints "top"


[Note: Requires version 2017.01 Experimental Build]

see also Assertion (software development)

Assert evaluates a logical expression. If the logical expression evaluates to false, the generation of the preview/render is stopped with an error.

Assertion can be used for e.g. in modules to make sure, that the parameters are valid.

Currently (2017.01 Experimental Build), OpenSCAD does not output the file name in which the assertion failed. This can be an issue when writing libraries. (see Issue #1910)

failing example[edit]

The simplest example is a simple assert(false);.

Source Code Console output
Compiling design (CSG Tree generation)...
ERROR: Assertion 'false' failed, line 2 
Compiling design (CSG Products generation)...
Geometries in cache: 0
Geometry cache size in bytes: 0
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 0 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 0 seconds

This example has little use, but the simple assert(false); has.

assert(false); can be used code sections that should be unreachable.

checking parameters[edit]

A useful example is checking the validity of input parameters:

module row(cnt=1){
    assert(cnt>0); //Error: Count has to be a positive integer greater 0
    for(i = [1 : cnt]){


combining assert with echo[edit]

If you write a library containing modules, it could be useful to output additional information to the user in case of an failed assertion. This can be done by using echo.

module row(cnt=1){
        echo("<font color='red'>Error: Count has to be a positive integer greater 0</font>");
    for(i = [1 : cnt]){


assert vs. echo[edit]

The benefit of using assert over echo are:

  • assert stops the execution, forcing the user to resolve the issue

Benefit of echo over assert:

  • with echo, you (for e.g. as library creator) can output a meaning full error message