OpenSCAD User Manual/General

From Wikibooks, open books for an open world
< OpenSCAD User Manual
Jump to: navigation, search

Comments[edit]

OpenSCAD uses a programming language to create the models that are later displayed on the screen. Comments are a way of leaving notes within the code (either to yourself or to future programmers) describing how the code works, or what it does. Comments are not evaluated by the compiler, and should not be used to describe self-evident code.

OpenSCAD uses C++-style comments:

// This is a comment
 
myvar = 10; // The rest of the line is a comment
 
/*
    Multi-line comments
    can span multiple lines.
*/

Values and Data Types[edit]

A value in OpenSCAD is either a Number (like 42), a Boolean (like true), a String (like "foo"), 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. Functions are not values. In fact, variables and functions occupy disjoint namespaces.]

Numbers[edit]

Numbers are the most important type of value in OpenSCAD, and they are written in the familiar decimal notation used in other languages. Eg, -1, 42, 0.5, 2.99792458e+8. [OpenSCAD does not support octal or hexadecimal notation for numbers.]

In additional to decimal numerals, the following names for special numbers are defined:

  • PI

OpenSCAD has only a single kind of number, which is an IEEE floating point number. [OpenSCAD does not distinguish integers and floating point numbers as two different types, nor does it support complex numbers.] Because OpenSCAD uses the IEEE floating point standard, there are a few deviations from the behaviour of numbers in mathematics:

  • The largest representable number is about 1e308. If a numeric result is too large, then the result can be infinity (printed as inf by echo).
  • The smallest representable number is about -1e308. If a numeric result is too small, then the result can be -infinity (printed as -inf by echo).
  • If a numeric result is invalid, then the result can be Not A Number (printed as nan by echo).
  • If a non-zero numeric result is too close to zero to be representable, then the result will be -0 if the result is negative, otherwise it will be 0. Zero (0) and negative zero (-0) are treated as two distinct numbers by some of the math operations, and are printed differently by 'echo', although they compare equal.

Note that 'inf' and 'nan' are not supported as numeric constants by OpenSCAD, even though you can compute numbers that are printed this way by 'echo'. You can define variables with these values by using:

inf = 1e200 * 1e200;
nan = 0 / 0;
echo(inf,nan);

Note that 'nan' is the only OpenSCAD value that is not equal to any other value, including itself. Although you can test if a variable 'x' has the undefined value using 'x == undef', you can't use 'x == 0/0' to test if x is Not A Number. Instead, you must use 'x != x' to test if x is nan.

Boolean Values[edit]

Boolean values are truth values. There are two Boolean values, named 'true' and 'false'. A Boolean value is passed as the 'center' argument to the 'cube' and 'cylinder' primitives, as the argument to 'if', and as the arguments to the logical operators '!' (not), '&&' (and), and '||' (or).

In all of these contexts, you can actually pass any type of value. Most values, when used in a Boolean context, are equivalent to 'true', but there are a few that are equivalent to 'false'. The values that count as false are:

  • false
  • 0 and -0
  • ""
  • []
  • undef

Note that nan (Not A Number) counts as true.

Strings[edit]

A string is a sequence of zero or more unicode characters. String values are used to specify file names when importing a file, and to display text for debugging purposes when using 'echo

A string literal is written as a sequence of characters enclosed in quotation marks ("), like this: "", or "this is a string".

To include a " character in a string literal, use \". To include a \ character in a string literal, use \\. The following escape sequences beginning with \ can be used within string literals:

  • \" → "
  • \\ → \
  • \t → tab
  • \n → newline
  • \r → carriage return

Note: This behavior is new since OpenSCAD-2011.04. You can upgrade old files using the following sed command: sed 's/\\/\\\\/' non-escaped.scad > escaped.scad

Example:

 echo("The quick brown fox \tjumps \"over\" the lazy dog.\rThe quick brown fox.\nThe \\lazy\\ dog.");

Output:
ECHO: "The quick brown fox jumps "over" the lazy dog.
The quick brown fox.
The \lazy\ dog."

Output: in OpenSCAD version 2013.02.28
ECHO: "The quick brown fox \tjumps \"over\" the lazy dog.
The quick brown fox.\nThe \\lazy\\ dog."

Vectors[edit]

A vector is a sequence of zero or more OpenSCAD values. Vectors are most commonly used to represent points in 3-space (as [x,y,z] triples), to represent lists of points, and to represent the size of a cuboid (also as an [x,y,z] triple).

A vector is written as a list of zero or more expressions, separated by commas, and enclosed in square brackets, Eg, [] or [10,20,30].

Example

deck = [64, 89, 18];
cube(deck);

Output A cube with the sizes: X = 64, Y = 89, Z = 18.

Vectors selection[edit]

You can also refer to individual values in a vector with vector[number]. number starts from 0.

Example

deck = [64, 89, 18];
translate([0,0,deck[2]]) cube(deck);

Output The same cube as the previous example would be raised by 18 on the Z axis, since vector indices are numbered [0,1,2] for [X,Y,Z] respectively.

Matrix[edit]

A matrix is a vector of vectors.

Example

mr = [
      [cos(angle), -sin(angle)],
      [sin(angle),  cos(angle)]
     ];

Output Define a 2D rotation matrix.

Ranges[edit]

Ranges define a series of numerical values.

Range: [<start>:<end>] - iterate from start to end inclusive with a fixed increment of 1. Both start and end can be fractions. It also works if end is smaller than start but as of Version 2014.03 this usage is deprecated and will produce a warning message.

Range: [<start>:<increment>:<end>] - iterate from start to end with the given increment. The increment can be a fraction.
It's valid to use a negative increment, in this case end must be smaller than (or equal to) start.

Warning: If the increment is not an even divider of <end>-<start>, the iterator value for the last iteration will be <end>-(<end>-<start> mod <increment>).

Note for Version < 2014.03: The increment is given as an absolute value and cannot be negative. If <end> is smaller than <start> the increment should remain unchanged.

Example

r = [0.5 : 2.5];
for (n = r) echo(n);

Output
ECHO: 0.5
ECHO: 1.5
ECHO: 2.5

The Undefined Value[edit]

The undefined value is a special value written as 'undef'. It's 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.

Note that numeric operations may also return nan 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.

Variables[edit]

Variables in OpenSCAD are simply a name followed by an assignment via an expression (but see below for an important note about variables!)

Example:

myvar = 5 + 4;

Currently it's not possible to do assignments at any place (the only places are file top-level and module top-level). If you need it inside the for loop, for example, you need to use the assign() module.

Undefined variable[edit]

A non assigned variable has the special value undef. It could be tested in conditional expression, and returned by a function. Example

echo("Variable a is ", a); // output 'Variable a is undef'
if (a==undef) {
   echo("Variable a is tested undefined");
}

Output Variable a is undef Variable a is tested undefined

Variables are set at compile-time, not run-time[edit]

Because OpenSCAD calculates its variable values at compile-time, not run-time, the last variable assignment will apply everywhere the variable is used (with some exceptions, mentioned below). It may be helpful to think of them as override-able constants rather than as variables.

Example:

 // The value of 'a' reflects only the last set value
    a = 0;
    echo(a);
 
    a = 5;
    echo(a);

Output

ECHO: 5
ECHO: 5

This also means that you can not reassign a variable inside an "if" block:

Example:

a=0;
if (a==0) 
  {
  a=1; // <- this line will generate an error.
  }

Output Compile Error

Exception #1[edit]

This behavior is scoped to either the root or to a specific call to a module, meaning you can re-define a variable within a module without affecting its value outside of it. However, all instances within that call will behave as described above with the last-set value being used throughout.

Example:

p = 4;
test(5);
echo(p);
/*
 * we start with p = 4.  We step to the next command 'test(5)', which calls the 'test' module.
 * The 'test' module calculates two values for 'p', but the program will ONLY display the final value. 
 * There will be two executions of echo(p) inside 'test' module, but BOTH will display '9' because it is the FINAL
 * calculated value inside the module. ECHO: 9   ECHO: 9
 *
 * Even though the 'test' module calculated value changes for 'p', those values remained inside the module.  
 * Those values did not continue outside the 'test' module.  The program has now finished 'test(5)' and moves to the next command 'echo(p)'.
 * The call 'echo(p)' would normally display the original value of 'p'=4.  
 * Remember that the program will only show the FINAL values.  It is the next set of commands that produce the final values....which is ECHO: 6
 */
p = 6;
test(8);
echo(p);
/*
 * We now see 'p=6', which is a change from earlier.  We step to the next command 'test(8)', which calls the 'test' module.
 * Again, the 'test' module calculates two values for 'p', but the program will ONLY display the final value.
 * There will be two executions of echo(p) inside 'test' module, but BOTH will display '12' because it is the FINAL
 * compiled value that was calculated inside the module.  
 * Therefore, both echo(p) statements will show the final value of '12' ;
 * Remember that the 'test' module final values for 'p' will remain inside the module.  They do not continue outside the 'test' module.
 * ECHO:12   ECHO:  12
 *
 * The program has now finished 'test(8)' and moves to the next command 'echo(p)'.
 * Remember at compile that the pgm will show the FINAL values.  The first value of 'echo(p)' would have showed a value of '4'...
 * However, at compile time the final value of 'echo(p)' was actually '6'.  Therefore, '6' will be shown on both echo(p) statements.
 * ECHO 6
 */
 
module test(q)
{
    p = 2 + q;
    echo(p);
 
    p = 4 + q;
    echo(p);
}

Output

ECHO: 9
ECHO: 9
ECHO: 6
ECHO: 12
ECHO: 12
ECHO: 6

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.

Exception #2[edit]

See the assign, which provides for a more tightly scoped changing of values.

Getting input[edit]

Now we have variables, it would be nice to be able to get input into them instead of setting the values from code. There are a few functions to read data from DXF files, or you can set a variable with the -D switch on the command line.

Getting a point from a drawing

Getting a point is useful for reading an origin point in a 2D view in a technical drawing. The function dxf_cross will read the intersection of two lines on a layer you specify and return the intersection point. This means that the point must be given with two lines in the DXF file, and not a point entity.

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

Getting a dimension value

You can read dimensions from a technical drawing. This can be useful to read a rotation angle, an extrusion height, or spacing between parts. In the drawing, create a dimension that does not show the dimension value, but an identifier. To read the value, you specify this identifier from your script:

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

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