OpenSCAD Benutzerhandbuch/Schleifen und Bedingungen
For-Schleife
[Bearbeiten]Wertet jeden Wert in einem Bereich oder Vektor (bzw. jeden Namen in einem Objekt) aus und wendet ihn auf die folgende Aktion an.
for(variable = [start : increment : end])
for(variable = [start : end])
for(variable = [vector])
for(variable = object)
Für jeden Wert in einem Bereich
[Bearbeiten]for (variable = [ start : increment : end ])
for (variable = [ start : end ])
Hinweis: In Bereichen werden Werte durch Doppelpunkte getrennt – nicht durch Kommas wie in Vektoren!
Die Aktion wird für jeden Wert im Bereich ausgeführt.
- start – Startwert
- increment (optional, Standard = 1) – Schrittweite
- end – Ende (wird nicht überschritten)
- Beispiele:
for (a = [3:5]) echo(a); // 3 4 5
for (a = [3:0]) echo(a); // ungültig (start > end), ab 2015.3 veraltet
for (a = [3:0.5:5]) echo(a); // 3 3.5 4 4.5 5
for (a = [0:2:5]) echo(a); // 0 2 4 (5 wird nicht erreicht!)
for (a = [3:-2:-1]) echo(a); // 3 1 -1 (negative Schritte erst ab 2015.3)
Für jedes Element eines Vektors
[Bearbeiten]Die Aktion wird für jedes Element des Vektors ausgeführt.
for (a = [3,4,1,5]) echo(a); // 3 4 1 5
for (a = [0.3,PI,1,99]) echo(a); // 0.3 3.14159 1 99
x1=2; x2=8; x3=5.5;
for (a = [x1,x2,x3]) echo(a); // 2 8 5.5
for (a = [[1,2],6,"s",[[3,4],[5,6]]]) echo(a); // [1,2] 6 "s" [[3,4],[5,6]]
Der Vektor kann auch extern definiert werden – wie eine „for each“-Schleife in anderen Sprachen:
animals = ["elephants", "snakes", "tigers", "giraffes"];
for(animal = animals)
echo(str("I've been to the zoo and saw ", animal));
// → Ein Satz pro Tier
Für jedes Element eines Objekts
[Bearbeiten]Die Aktion wird für jeden Schlüsselnamen des Objekts ausgeführt (Reihenfolge nicht garantiert):
tm = textmetrics("Hello, World!");
for (name = tm) echo(name, tm[name]);
Wichtige Hinweise
[Bearbeiten]"for()" ist ein Operator – bei mehreren Aktionen brauchst du "{}". Aktionen enden mit ";", Operatoren nicht.
Obwohl OpenSCAD keine echte Schleifensprache ist, bekommt jede Iteration ihren eigenen Gültigkeitsbereich – so kannst du innerhalb der Schleife Variablen frei nutzen. Aber: Du kannst nicht "a = a + 1" schreiben – das geht nicht!
Intern baut "for()" einen Baum von Objekten, nicht eine Schleife im klassischen Sinn:
for (i=[0:3])
translate([i*10,0,0])
cube(i+1);
Erzeugt vier unabhängige Zweige im CSG-Baum – nicht nacheinander ausgeführten Code!
Verschachtelte for()-Schleifen
[Bearbeiten]Du kannst mehrere "for()"-Schleifen verschachteln:
for(z=[-180:45:+180])
for(x=[10:5:50])
rotate([0,0,z]) translate([x,0,0]) cube(1);
Oder noch kürzer: Alle Bereiche in einer "for()"-Anweisung:
// Langversion:
color_vec = ["black","red","blue","green","pink","purple"];
for (x = [-20:10:20] )
for (y = [0:4] ) color(color_vec[y])
for (z = [0,4,10] )
{translate([x,y*5-10,z]) cube();}
// Kurzversion:
color_vec = ["black","red","blue","green","pink","purple"];
for (x = [-20:10:20],
y = [0:4],
z = [0,4,10] )
translate([x,y*5-10,z]) { color(color_vec[y]) cube(); }

- Beispiele mit Vektor von Vektoren

// Beispiel 1 – Rotation
for(i = [ [ 0, 0, 0],
[ 10, 20, 300],
[200, 40, 57],
[ 20, 88, 57] ])
{
rotate(i)
cube([100, 20, 20], center = true);
}

// Beispiel 2 – Translation
for(i = [ [ 0, 0, 0],
[10, 12, 10],
[20, 24, 20],
[30, 36, 30],
[20, 48, 40],
[10, 60, 50] ])
{
translate(i)
cube([50, 15, 10], center = true);
}

// Beispiel 3
for(i = [ [[ 0, 0, 0], 20],
[[10, 12, 10], 50],
[[20, 24, 20], 70],
[[30, 36, 30], 10],
[[20, 48, 40], 30],
[[10, 60, 50], 40] ])
{
translate([i[0][0], 2*i[0][1], 0])
cube([10, 15, i[1]]);
}
Intersection For Loop
[Bearbeiten]Iteriert über einen Bereich oder Vektor und erzeugt den Durchschnitt (Schnittmenge) aller Objekte, die in den einzelnen Durchläufen entstehen.
Während die normale "for()"-Schleife intern eine implizite Vereinigung ("union") aller Instanzen erzeugt, ersetzt "intersection_for()" diese durch eine Schnittmenge ("intersection"). Das ist nötig, weil "intersection() for() ..." nicht das gewünschte Ergebnis liefert.
"intersection_for()" verwendet dieselben Parameter wie "for()" – nur das Ergebnis ist anders.
| Beispiel 1 – Bereich: | ||
intersection_for(n = [1 : 6])
{
rotate([0, 0, n * 60])
{
translate([5,0,0])
sphere(r=12);
}
}
|
If-Anweisung
[Bearbeiten]Prüft eine Bedingung und führt Aktionen nur aus, wenn sie wahr ist.
WICHTIG: Du kannst keine bestehenden Variablen ändern! Eine Zuweisung innerhalb von "{}" erzeugt eine neue lokale Variable, die nach dem Block wieder verschwindet.
if (test) scope1
if (test){scope1}
if (test) scope1 else scope2
if (test){scope1} else {scope2}
- Parameter
- test: Meist ein boolescher Ausdruck (aber jeder Wert ist erlaubt).
- Wann ist ein Wert „wahr“?
- Vergleichsoperatoren
- Verwechsle Zuweisung "=" nicht mit Gleichheit "=="!
- scope1: Aktion(en), wenn "test" wahr ist.
- scope2: Aktion(en), wenn "test" falsch ist.
- test: Meist ein boolescher Ausdruck (aber jeder Wert ist erlaubt).
Beispiele:
if (b==a) cube(4);
if (b<a) {cube(4); cylinder(6);}
if (b&&a) {cube(4); cylinder(6);}
if (b!=a) cube(4); else cylinder(3);
if (b) {cube(4); cylinder(6);} else {cylinder(10,5,5);}
if (!true){cube(4); cylinder(6);} else cylinder(10,5,5);
if (x>y) cube(1, center=false); else {cube(size = 2, center = true);}
if (a==4) {} else echo("a is not 4");
if ((b<5)&&(a>8)) {cube(4);} else {cylinder(3);}
if (b<5&&a>8) cube(4); else cylinder(3);
Ab Version 2015.03 darfst du Variablen in jedem Block zuweisen – aber sie bleiben lokal (siehe Gültigkeitsbereich).
- Verschachteltes if
Du kannst "if"-Anweisungen beliebig tief verschachteln:
if (test1)
{
scope1
if (test2) {scope2.1}
else {scope2.2}
}
else
{
scope2
if (test3) {scope3.1}
else {scope3.2}
}
Wenn ein Block nur aus einem "if" besteht, kannst du die äußeren Klammern weglassen:
if (test1)
if (test2) {scope2.1}
else {scope2.2}
else
if (test3) {scope3.1}
else {scope3.2}
else if
[Bearbeiten]So kannst du mehrere Bedingungen prüfen – die erste wahre wird ausgeführt, alle anderen übersprungen:
if(test1) {scope1}
else if(test2) {scope2}
else if(test3) {scope3}
else if(test4) {scope4}
else {scope5}
Beachte: "else" und "if" sind zwei separate Wörter.
- Beispiel
if((k<8)&&(m>1)) cube(10);
else if(y==6) {sphere(6);cube(10);}
else if(y==7) color("blue") sphere(5);
else if(k+m!=8) {cylinder(15,5,0);sphere(8);}
else color("green") {cylinder(12,5,0);sphere(8);}
Bedingungsoperator ? :
[Bearbeiten]Ein ternärer Operator, der basierend auf einer Bedingung einen von zwei Werten zurückgibt.
a = test ? TrueValue : FalseValue;
echo(test ? TrueValue : FalseValue);
- Parameter
- test: Beliebiger Ausdruck („falsy“ oder „truthy“).
- TrueValue: Wert, wenn "test" wahr ist.
- FalseValue: Wert, wenn "test" falsch ist.
Das funktioniert wie der "?:"-Operator in C, Java etc.
- Beispiele
a=1; b=2; c= a==b ? 4 : 5; // c = 5
a=1; b=2; c= a==b ? "a==b" : "a!=b"; // c = "a!=b"
TrueValue = true; FalseValue = false;
a=5; test = a==1;
echo(test ? TrueValue : FalseValue); // false
L = 75; R = 2; test = (L/R)>25;
TrueValue = [test,L,R,L/R,cos(30)];
FalseValue = [test,L,R,sin(15)];
a1 = test ? TrueValue : FalseValue; // [true, 75, 2, 37.5, 0.866025]
Rekursive Funktionsaufrufe
[Bearbeiten]Rekursion wird unterstützt – aber es gibt ein internes Limit, um Abstürze zu vermeiden. Wird es erreicht, liefert die Funktion "undef".
Beispiel: Summe eines Vektors berechnen:
function sumv(v, i, s = 0) = (i == s ? v[i] : v[i] + sumv(v, i-1, s));
vec=[10,20,30,40];
echo("sum vec=", sumv(vec, 2, 1)); // → 20+30 = 50
Komplexe Ausdrücke übersichtlich formatieren
[Bearbeiten]Verschachtelte Bedingungen lassen sich wie "if/else"-Blöcke einrücken:
// Maximum eines Vektors finden
function maxv(v, m=-999999999999, i=0) =
(i == len(v))
? m
: (m > v[i])
? maxv(v, m, i+1)
: maxv(v, v[i], i+1);
v=[7,3,9,3,5,6];
echo("max",maxv(v)); // ECHO: "max", 9
Assign-Anweisung
[Bearbeiten]Vorlage:OpenSCAD User Manual/Deprecated
Weist Variablen für einen Unterbaum neue Werte zu.
- Beispiel:
// Alte Schreibweise (veraltet):
for (i = [10:50])
{
assign (angle = i*360/20, distance = i*10, r = i*2)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}
// Moderne Schreibweise (ohne assign):
for (i = [10:50])
{
angle = i*360/20;
distance = i*10;
r = i*2;
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
Let-Anweisung
[Bearbeiten]Weist Variablen für einen Unterbaum neue Werte zu – nacheinander, sodass spätere Zuweisungen auf frühere zurückgreifen können (im Gegensatz zu "assign").
- Beispiel:
for (i = [10:50])
{
let (angle = i*360/20, r = i*2, distance = r*5)
{
rotate(angle, [1, 0, 0])
translate([0, distance, 0])
sphere(r = r);
}
}



