12. Abfrage - if() {...} else {...}

Worum geht es: Wenn das Wetter schön ist, sitze ich an der Sonne, wenn nicht, dann sitze ich im Haus.In den Worten von OpenSCAD würde das so aussehen:

  if (wetter == schön) {
    sitze an der Sonne
  } else {
    sitze im Haus
  }

Klar, sitze an der Sonne und sitze im Haus wären dann unser OpenSCAD-Code. Der Aufbau mit if (), den geschweiften Klammern und else entspricht genau unserem wenn-dann-sonst. Genau darum geht es hier … aber erst im zweiten Teil des Kapitels.

12.1 Schachbrett

12.1.1 Erste Überlegung

Nehmen wir uns als Nächstes ein Schachbrett vor. Dazu brauchen wir zwei Konstanten: feld für die Feldgrösse und dick für die Brettdicke. Ein Schachbrett hat 8×8 Felder, die abwechselnd schwarz und weiss sind.

feld=20;
dick=2;

color("black")
  translate([0,0,0])
    cube([feld,feld,dick]);
color("white")
  translate([feld,0,0])
    cube([feld,feld,dick]);

Hier sind erst mal die ersten zwei Felder.druckansicht

Nun folgen die nächsten zwei Felder. Dabei wird die x-Verschiebung beim black-Feld mit feld+feld berechnet. Beim vierten Feld wäre das dann feld+feld+feld oder 3*feld.

color("black")
  translate([feld+feld,0,0])
    cube([feld,feld,dick]);
color("white")
  translate([3*feld,0,0])
    cube([feld,feld,dick]);

Das Resultat sieht wie gewünscht aus, aber wenn wir so weitermachen, wären das 64 translate()- und cube()-Aufrufe.

druckansicht

12.1.2 Wiederholung for()

Wiederholungen mit for() haben wir im letzten Kapitel kennengelernt. Hier geht es um eine Wiederholung mit schrittweiser Erhöhung der x-Verschiebung. Für eine Linie des Schachbretts ergeben sich jeweils 4 × ein schwarzes und ein weisses Feld. Die Konstanten feld=20; und dick=2; behalten wir vom letzten Beispiel.

Unser Zähler ist i, der bei 0 beginnt und bis 3 hochgezählt wird. Zuerst wird das Feld black, dann das Feld white erstellt. Anschliessend wieder black und wieder white

Die Formel für die Verschiebung des Feldpaares ist nicht ganz so einfach.

druckansicht

Ein i*feld wird uns kein richtiges Resultat liefern. Es muss immer in Zweierschritten weitergerechnet werden, wobei das zweite Feld um ein Feld verschoben gezeichnet wird. Das erste Feldpaar müsste bei 0 starten, das zweite bei 40, das dritte bei 80, das vierte bei 120.

Machen wir es zuerst auf die falsche Art.

for (i = [0:1:3]) {
  echo("runde");
  echo(i*feld);
  echo(i+1*feld);
}

Schauen wir uns die Resultate von echo(...) genau an.

druckansicht

Beim zweiten Feld stimmt einiges nicht. Punkt vor Strich … somit müsste i+1 in Klammern stehen, da sonst zuerst 1*feld und dann +i gerechnet wird. Richtig wäre i*feld+feld, denn das zweite Feld ist immer um ein Feld weiter als das erste.

for (i = [0:1:3]) {
  echo("runde");
  echo(i*feld);
  echo(i*feld+feld);
}

druckansicht

Schon etwas besser:

erstes Feldpaar = 0 und 20 (richtig)

Jedes Feldpaar müsste um 2*feld verschoben sein, also i*2*feld.

for (i = [0:1:3]) {
  echo("runde");
  echo(i*2*feld);
  echo(i*2*feld+feld);
}

Klammern sind nicht nötig, da Punkt vor Strich korrekt gerechnet wird. Natürlich kann auch ((i*2)*feld)+feld geschrieben werden. So wird zuerst i*2, dann Resultat*feld und schliesslich +feld gerechnet … genau gleich wie ohne Klammern.

druckansicht

Somit sieht unser Code so aus:

for (i = [0:1:3]) {
  color("black")
    translate([i*2*feld,0,0])
      cube([feld,feld,dick]);
  color("white")
    translate([i*2*feld+feld,0,0])
      cube([feld,feld,dick]);
}

Die erste Reihe ist gemacht.

druckansicht

12.1.3 zweite Reihe

Die zweite Schachbrettreihe wäre dann mit umgekehrten Farbfeldern, aber in y um feld = 20 verschoben …

for (i = [0:1:3]) {
  color("white")
    translate([i*2*feld,feld,0])
      cube([feld,feld,dick]);
  color("black")
    translate([i*2*feld+feld,feld,0])
      cube([feld,feld,dick]);
}

Ja, genau so soll es sein …

druckansicht

Die dritte Reihe ist wieder um feld=20 weiter in y-Richtung verschoben, und dann nochmals und nochmals, bis alle 8 Reihen gebaut sind. Das müsste doch mit einer zweiten for()-Schleife machbar sein.

Wir könnten nun die beiden Reihen in eine Schleife nehmen und wie bei den x-Feldern den y-Wert um iy*2*feld und iy*2*feld+feld erhöhen. Aber wir könnten auch eine weitere Steuerungsmöglichkeit anschauen.

12.1.4 Ablauf Steuern mit "if () {...} else {...}"

Wie wäre es, wenn wir abfragen könnten, ob es eine gerade oder ungerade Reihe des Schachbretts ist? Die erste Reihe ist Reihe 0 und somit eine gerade Reihe. Reihe 1 ist eine ungerade Reihe, Reihe 2 wieder gerade, Reihe 3 ungerade …

Wir müssten bei jeder Wiederholung nur wissen, ob iy gerade oder ungerade ist, und dann zwei verschiedene Wege für das Erstellen der cube() wählen.

Dazu gibt es in OpenSCAD die Rechenoperation %, auch Modulo genannt. Modulo berechnet den Rest einer Division.

Bevor wir % oder Modulo in den Code einbauen, machen wir einen Test.

for (iy = [0:1:7]) {
  echo(iy%2);
}

Im Konsolenfenster wird die Zahlenreihe 0,1,0,1,0,1,0,1 erscheinen.

Wenn wir nun das Resultat aus iy%2 mit if (iy%2 == 0) {...} abfragen, können wir den Ablauf in zwei Programmblöcke umschalten. Das == bedeutet gleich. In der Algebra steht da jeweils nur ein =, aber in vielen Programmiersprachen wird == geschrieben.

Wenn iy%2 gleich 0 ist, wird der erste Block ausgeführt, ansonsten der zweite.

if (iy%2 == 0) {
  //erste Klammer
  ...
} else {
  // zweite Klammer
  ...
}

Das Ganze sieht dann so aus (feld=20 und dick=2 bleiben am Anfang stehen):

for (iy = [0:1:7]) {
  for (i = [0:1:3]) {
    if (iy%2 == 0) {
      color("black")
        translate([i*2*feld,iy*feld,0])
          cube([feld,feld,dick]);
      color("white")
        translate([i*2*feld+feld,iy*feld,0])
          cube([feld,feld,dick]);
    } else {
      color("white")
        translate([i*2*feld,iy*feld,0])
          cube([feld,feld,dick]);
      color("black")
        translate([i*2*feld+feld,iy*feld,0])
          cube([feld,feld,dick]);
    }
  }
}

Unser Schachbrett ist fertig!

druckansicht

Das Code-Beispiel kann auch ganz anders aufgebaut werden. Es zeigt aber, wie mit einer if()-Abfrage der Ablauf gesteuert werden kann.