OpenSCAD User Manual/General

Scripts in the OpenSCAD language are functional descriptions of how a designer's intent may realized in a solid model.

Program Structure

The statement is the basis of the language:

<perform named operations>;

The end of a statement is marked by a literal semi-colon (';').

Each statement either results in a value, which is assigned to a variable, instantiates a solid object that appears in the preview panel, or modifies the script's flow of execution.

Evaluating Expressions

An expression always results in a value with a specific type and may replace a single variable or literal value anywhere anyplace that such are allowed or required as syntactic items in a statement or function call.

When used in a statement the result must be assigned to a variable

<Named Variable> = <expression>;

but in general the result of an expression is used immediately as a script runs; as the condition in a flow of control statement or as a parameter to a module that creates geometry.

Constructing Solid Geometry

The normal operation of Constructive Solid Geometry (CSG) is to form complex shapes by combining primitive and derived shapes and performing operations on them.

To create a shape an Object Module is called:

 object();

Only one object may be created in a statement and its module call must be last in it.

To manipulate or modify an object any number of Operator Modules may be called before the object():

 operator() object();
 operator() operator() object();

Note: An operator() call may not be the last operation in a statement

2D Shapes and Extrusion

Any of the 2 Dimensional Primitives, Polygons, Text, and Imported 2D shapes may be the basis for extrusions that create 3D shapes.

3D Shapes and Combinations

Any of the 3 Dimensional Primitives, Polyhedrons, and Imported 3D Shapes may be the basis for Boolean Combinations that create 3D shapes.

How Convexity Affects Rendering

Convexity is a rendering issue

Structure and Scope

It is possible to create a block of statements using braces to mark the beginning and end of the block:

{
operator() object();
operator() object();
}

This simple block is not much use as such but offers as important benefit:

Note: anywhere the language syntax puts an Object Module it may be replaced by a block

In 2D/3D modelling it is often necessary/desired to apply an operation to a group of objects, thus:

operator() {
  object();
  operator() object();
  }

The "target" module of an operation may be a block.

Also, as will be seen in the section on flow of control statements, only single statements are in the syntax of if-then-else and for-loops.

Note: anywhere a single statement appears in the language syntax it may be replaced by a block

Flow Of Control

As with any structured programming language decision making and looping statements are critical features of OpenSCAD scripts. In a functional language the path, or flow, of execution through the code is controlled by the FoC statements.

The statements available are the if(cond)-else and the for([range]) loop. FoC statements are written to operate on single statements, thusly:

if(<condition>) <when true do this statement>;
else <when false do this statement>;

and with looping

for(i=[0:9]) object(); // make 10 objects

A more readable example:

if( is_string(s) )
    operator() object(file=s); // do this when <condition> == true
else
    object(file="default.dat"); // otherwise do this

Of course a single statement is often not enough. Different statement types and use cases have these coping mechanisms:

  • When the statement is an assignment expression the calculation may be written into a function as calling a function is a valid expression.
  • A sequence of actions may be written into a user-defined module as calling that is a single statement.
  • in every case a block "{}" can replace a statement
if( is_string(s) )
    { // <condition> == true
    operator() object(file=s);
    if(<condition>)
        answer = MyOwnFunction();
    else
        answer = 12;
    }
else // <condition> == false
       // no block - the for() loop is the single statement
    for()
        { // but the target of the for loop is this block
        object(file="default.dat");
        operator() My_Own_Object();
        }

Other Uses of If and For

The for() and if() statements have an important secondary role in vector initialization, though it is not technically flow of control.

A third use of the for loop concept is special iteration_for() Operator Module for intersecting multiple instances of an object into a composite. Again, not technically not flow of control.

Language Components

Most of the other commonly available components of a structured programming language are included in OpenSCAD, namely

Named Objects and Scope
variables, functions, and modules
Data Types, Values, and Constants
64-bit floating point, boolean, string, and vector (or list)
Data Structures
Vectors
Expressions
arithmetic, string, bitwise, and logical
Built-In Functions
all the standard functions for use in expressions of all types
User Defined Objects
custom modules and functions

Language Elements particularly needed for modelling are

Built-in 2D Object Modules
circle(), square(), polygon(), etc.
2D file import
Adding drawn shapes from SVG, DXF, image, and text data files
3D File Import
adding geometry from external sources
Built-In 3D Object Modules
sphere(), cube(), polyhedron(), etc.
Built-In Operator Modules
  • 3D boolean operations: intersection(), difference(), union()
  • Shape Modifications : linear_extrude(), rotate_extrude(), hull(), etc.
  • Transformations : translate(), rotate(), etc.
  • Color
Customizer
Compile time user input

Values and data types

A value in OpenSCAD is either a Number (like 42), a Boolean (like true), a String (like "foo"), a Range (like [0: 1: 10]), a Vector (like [1,2,3]), or the Undefined value (undef). Values can be stored in variables, passed as function arguments, and returned as function results.

[OpenSCAD is a dynamically typed language with a fixed set of data types. There are no type names, and no user defined types.]

The undefined value

The undefined value is a special value written as undef. It is the initial value of a variable that hasn't been assigned a value, and it is often returned as a result by functions or operations that are passed illegal arguments. Finally, undef can be used as a null value, equivalent to null or NULL in other programming languages.

All arithmetic expressions containing undef values evaluate as undef. In logical expressions, undef is equivalent to false. Relational operator expressions with undef evaluate as false except for undef==undef, which is true.

Note that numeric operations may also return 'nan' (not-a-number) to indicate an illegal argument. For example, 0/false is undef, but 0/0 is 'nan'. Relational operators like < and > return false if passed illegal arguments. Although undef is a language value, 'nan' is not.

Variables cannot be changed

The simplest description of OpenSCAD variables is that an assignment creates a new variable in the current scope, and that it's not legal to set a variable that has already been set in the current scope. In a lot of ways, it's best to think of them as named constants, calculated on entry to the scope.

That's not quite accurate. If you set a variable twice in the same scope, the second assignment triggers a warning (which may abort the program, depending on preferences settings). It does *not* then replace the value of the variable - rather, it replaces the original assignment, at its position in the list of assignments. The original assignment is never executed.

a = 1;   // never executed
echo(a); // 2
a = 2;   // executed at the position of the original assignment
echo(a); // 2

That's still not the complete story. There are two special cases that do not trigger warnings:

  • if the first assignment is in the top level of an `include` file, and the second assignment is in the including file.
  • If the first assignment is in the top level of the program source, and the second assignment comes from a `-D` option or from the Customizer.

While this appears to be counter-intuitive, it allows you to do some interesting things: for instance, if you set up your shared library files to have default values defined as variables at their root level, when you include that file in your own code you can 're-define' or override those constants by simply assigning a new value to them - and other variables based on that variable are based on the value from the main program.

// main.scad
include <lib.scad>
a = 2;
echo(b);
// lib.scad
a = 1;
b = a + 1;

will produce 3.

Run-Time Data Sources

An OpenSCAD program cannot prompt the user for interactive input while running, but it is possible to access data from files, the Customizer Panel, and the command line.

  • the Customizer may be used to set values that modify the parsing and rendering of an .scad program
  • If the app is opened from the command line a -D at the -D value argument
  • read data from .stl, .dxf, or .png files.

Import Objects from STL Files

OpenSCAD can import objects from STL files to be manipulated (translation, clipping, etc.) and rendered. The data in the STL file cannot be accessed.

Access Data in DXF Files

Data in a DXF file may be accessed using this functions:

[X,Y,Z] = dxf_cross( file="name.dxf", layer="a.layer", origin=[0,0], scale=1.0 )
This function returns the intersection of two lines on the given layer.
N= dxf_dim( file="name.dxf", name="namedDimension", layer="a.layer", origin=[0, 0], scale=1);

Function dxf_cross()

The function looks for two lines on the given layer and calculates their intersection. The intersection may not be defined as a point entity.

OriginPoint = dxf_cross(file="drawing.dxf", layer="SCAD.Origin", 
                        origin=[0, 0], scale=1);

Function dxf_dim()

Dimensions in a DXF file that are named may be accessed for use in an OpenSCAD program using a call to dxf_dim();

TotalWidth = dxf_dim(file="drawing.dxf", name="TotalWidth",
                        layer="SCAD.Origin", origin=[0, 0], scale=1);

DXF File Data Access Example

For a nice example of both functions, see Example009 and the image on the homepage of OpenSCAD.