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
-Dat the-D valueargument - 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.