# OpenSCAD User Manual/Other Language Features

### Special variables

All variables starting with a '\$' are special variables. The semantic is similar to the special variables in lisp: they have dynamic instead of lexical scoping.

#### \$fa, \$fs and \$fn

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.

When \$fa and \$fs are used to determine the number of fragments for a circle, then OpenSCAD will never use less 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 (fn > 0.0)
return (int)fn;
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.

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

```      \$fs = 0.01;
sphere(2);
```

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);
```

#### \$t

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 and \$vpt

These contain the current viewport rotation and translation - at the time of doing the rendering. Moving he 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)

It's not possible to write to them and thus change the viewport parameters (although that could be a decent enough idea).

Example

``` cube([10,10,\$vpr/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.

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

### User-Defined Functions

Define a function for code readability and re-use.

Usage examples:

```my_d=20;
function r_from_dia(my_d) = my_d / 2;
echo("Diameter ", my_d, " is radius ", r_from_dia(my_d));
```

### Echo Statements

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

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

Usage examples:

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

Shows in the Console as

```ECHO:Hello Qt!
```

### Render

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

Example 1:

```//surface.scad
surface(file = "surface.dat", center = true, convexity = 5);
%translate([0,0,5])cube([10,10,10], center =true);
```
```#surface.dat
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
```

Result:

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);
}
```

### Search

Usage Pattern:

``` "search" "(" ( match_value | list_of_match_values ) "," vector_of_vectors
("," num_returns_per_match
("," index_col_num )? )?
")";
match_value : ( Value::NUMBER | Value::STRING );
list_of_match_values : "[" match_value ("," match_value)* "]";
vector_of_vectors : "[" ("[" Value ("," Value)* "]")+ "]";
num_returns_per_match : int;
index_col_num : int;
```

The following are some usage examples.

#### Index values return as list

Example Code Result

1

`search("a","abcdabcd");`

[0,4]

2

`search("a","abcdabcd",1);`



3

`search("e","abcdabcd",1);`

[]

4

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

[0,4]

#### Search on different column; return Index values

Example 5:

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

Returns:

```   [2,8]
```

#### Search on list of values

Example 6: Return all matches per search vector element.

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

Returns:

```   [[0,4],[1,5],[2,6]]
```

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

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

Returns:

```   [0,1,2]
```

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

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

Returns:

``` [[0,4],[1,5],[2,6],]
```

#### Search on list of strings

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] ];
lSearch2=["b","zzz","a","c","apple","dog"];
l2=search(lSearch2,lTable2);
echo(str("Default list string search (",lSearch2,"): ",l2));
```

Returns

``` ECHO: "Default list string search ([\"b\", \"zzz\", \"a\", \"c\", \"apple\", \"dog\"]): [1, [], 4, 2, 9, 3]"
```