Zum Inhalt springen

OpenSCAD Benutzerhandbuch/Transformationen

Aus Wikibooks

Grundkonzept

[Bearbeiten]

Transformationen wirken auf ihre Kind-Objekte und verändern sie – wie der Name schon sagt – auf verschiedene Weise: z. B. durch Verschieben, Drehen oder Skalieren.

Transformationen werden vor dem Objekt geschrieben, das sie beeinflussen sollen, z. B.:

translate([10,20,30])
    cube(10);

Beachte: Hinter einem Transformationsbefehl steht kein Semikolon!

Möchtest du mehrere Objekte gemeinsam transformieren, schließt du sie mit "{" und "}" in einen Block ein:

translate([0,0,-5])
{
    cube(10);
    cylinder(r=5,h=10);
}

Du kannst Transformationen auch verschachteln, um mehrere Effekte hintereinander anzuwenden:

rotate([45,45,45])
    translate([10,20,30])
        cube(10);
Bei kombinierten Transformationen ist die Reihenfolge entscheidend!

Die Kombination von Transformationen erfolgt sequenziell von rechts nach links. Schau dir diese beiden Beispiele an:

color("red")   translate([0,10,0])  rotate([45,0,0])     cube(5);
color("green") rotate([45,0,0])     translate([0,10,0])  cube(5);

Obwohl beide dieselben Befehle enthalten, passiert etwas völlig anderes:

  • Beim roten Würfel wird zuerst um den Ursprung gedreht – danach wird er um "[0,10,0]" verschoben.
  • Beim grünen Würfel wird zuerst verschoben – erst danach wird um den Ursprung gedreht. Dadurch bewegt sich der Würfel auf einem Kreisbogen mit Radius 10 um den Ursprung.

Die Reihenfolge macht also einen riesigen Unterschied!

Fortgeschrittenes Konzept

[Bearbeiten]

OpenSCAD nutzt unterschiedliche Bibliotheken für verschiedene Funktionen – das kann zu kleinen Inkonsistenzen im Vorschaumodus (F5) führen.

„Klassische“ Transformationen wie "translate", "rotate", "scale", "mirror" und "multmatrix" werden in der Vorschau über OpenGL gerendert. Komplexere Befehle wie "resize" hingegen nutzen CGAL – sie verändern also das eigentliche Geometrieobjekt, statt es nur optisch zu transformieren.

Das wirkt sich besonders bei Modifikator-Zeichen wie "#" (Highlight) oder "%" (Transparent) aus: Manchmal wird das ursprüngliche, manchmal das berechnete Objekt hervorgehoben – je nachdem, ob es sich um eine „echte“ CSG-Operation handelt oder nicht.

scale

[Bearbeiten]

Skaliert alle Kind-Objekte mit dem angegebenen Vektor. Im Gegensatz zu "resize()" wird hier multipliziert: Die aktuelle Größe wird mit dem Faktor im Vektor multipliziert. Der Parametername ist optional.

Beispiel:

cube(10);
translate([15,0,0]) scale([0.5,1,2]) cube(10);

Ergebnis der scale()-Transformation in OpenSCAD

resize

[Bearbeiten]

Passt die Größe des Kind-Objekts exakt an die angegebenen x-, y- und z-Werte an.

"resize()" ist eine CGAL-Operation – sie arbeitet also mit der vollen Geometrie und braucht daher auch in der Vorschau (F5) etwas Zeit.


Beispiel:

// Vergrößere die Kugel auf 30 in X, 60 in Y und 10 in Z
resize(newsize=[30,60,10]) sphere(r=10);

OpenSCAD – resize()-Beispiel (Ellipse)

Ist einer der Werte (x, y oder z) 0, bleibt diese Dimension unverändert:

// Vergrößere den 1×1×1-Würfel auf 2×2×1
resize([2,2,0]) cube();

Mit dem Parameter "auto = true" werden alle 0-Dimensionen automatisch skaliert, um das Seitenverhältnis zu erhalten:

// Vergrößere den 1×2×0.5-Würfel auf 7×14×3.5
resize([7,0,0], auto=true) cube([1,2,0.5]);

Du kannst auch gezielt einzelne Dimensionen automatisch skalieren lassen:

// Vergrößere auf 10×8×1 – Z bleibt unverändert
resize([10,0,0], auto=[true,true,false]) cube([5,4,1]);

rotate

[Bearbeiten]

Dreht das Kind-Objekt um einen bestimmten Winkel – entweder um die Standardachsen oder um eine beliebige Achse.

Die Parameternamen sind optional, wenn die Argumente in der richtigen Reihenfolge stehen.

// Nutzung:
rotate(a = winkel, v = [x, y, z]) { ... }  
// oder
rotate(winkel, [x, y, z]) { ... }
rotate(a = [wx, wy, wz]) { ... }
rotate([wx, wy, wz]) { ... }

Wenn "a" ein Array ist (z. B. "[ax,ay,az]"), wird der "v"-Parameter ignoriert. Die Drehung erfolgt dann nacheinander: erst um X, dann um Y, dann um Z. Das heißt:

rotate(a=[ax,ay,az]) {...}

ist das Gleiche wie:

rotate(a=[0,0,az]) rotate(a=[0,ay,0]) rotate(a=[ax,0,0]) {...}

Um ein Objekt z. B. auf den Kopf zu stellen, drehst du es um 180° um die Y-Achse:

rotate([0,180,0]) { ... }

Der optionale Parameter "v" definiert eine beliebige Rotationsachse als Normalenvektor. Beispiel: Drehung um 45° um die Achse "[1,1,0]":

rotate(a=45, v=[1,1,0]) { ... }

Ergebnis der rotate()-Transformation

Ein einzelner Zahlenwert dreht immer um die Z-Achse – besonders praktisch in 2D:

rotate(45) square(10);

Ergebnis von rotate(45) in 2D

Hilfestellung zur Drehregel
[Bearbeiten]
Rechte-Hand-Regel

Für "rotate([a, b, c])" gilt:

  • a: Drehung um die X-Achse – von +Y Richtung +Z
  • b: Drehung um die Y-Achse – von +Z Richtung +X
  • c: Drehung um die Z-Achse – von +X Richtung +Y

Das folgt der Rechte-Hand-Regel: Zeig mit dem rechten Daumen in Richtung der positiven Achse – deine Finger zeigen die Drehrichtung.

Wenn du "a = 0" setzt und nur "b" und "c" veränderst, erhältst du ein Kugelkoordinatensystem. So baust du z. B. einen Zylinder vom Ursprung zu einem Punkt "(x,y,z)":

x= 10; y = 10; z = 10; // Zielpunkt

length = norm([x,y,z]);  // Abstand zum Ursprung
b = acos(z/length);      // Neigungswinkel (Inklination)
c = atan2(y,x);          // Azimutwinkel

rotate([0, b, c]) 
    cylinder(h=length, r=0.5);
%cube([x,y,z]); // Ecke des Würfels sollte mit Zylinderspitze übereinstimmen

Beispiel: rotate() als Kugelkoordinatensystem

translate

[Bearbeiten]

Verschiebt alle Kind-Objekte entlang des angegebenen Vektors. Der Parametername ist optional.

Beispiel:

cube(2,center = true); 
translate([5,0,0]) 
   sphere(1,center = true);

Ergebnis der translate()-Transformation

mirror

[Bearbeiten]

Erzeugt ein Spiegelbild des Kind-Objekts an einer Ebene durch den Ursprung. Der übergebene Vektor ist der Normalenvektor dieser Spiegelebene.

Beispiel: "mirror([1,0,0])" spiegelt an der YZ-Ebene – alle x-Koordinaten wechseln ihr Vorzeichen.

Funktions-Signatur:

[Bearbeiten]
mirror(v = [x, y, z]) { ... }

Beispiele

[Bearbeiten]

Das Original ist rechts. Beachte: "mirror()" erzeugt keine Kopie – es verändert das Objekt direkt (genau wie "rotate" oder "scale").

 // Original
 rotate([0,0,-30]){
   cube([23,12,10]);
   translate([0.5, 4.4, 9.9]){
     color("red", 1.0){
       linear_extrude(height=2){
         text("OpenSCAD", size= 3);
       }
     }
   }
 }
 // Gespiegelt
 mirror([1,0,0]){
   rotate([0,0,-30]){
     cube([23,12,10]);
     translate([0.5, 4.4, 9.9]){
       color("red", 1.0){
         linear_extrude(height=2){
           text("OpenSCAD", size= 3);
         }
       }
     }
   }
 }

multmatrix

[Bearbeiten]

Wendet eine affine Transformationsmatrix auf alle Kind-Objekte an. Die Matrix ist 4×3 (drei Zeilen mit je vier Werten) oder 4×4 (vierte Zeile muss "[0,0,0,1]" sein).

Nutzung: "multmatrix(m = [...]) { ... }"

Was du mit den einzelnen Elementen erreichen kannst (erste drei Zeilen):

Skalierung XScherung X nach YScherung X nach ZVerschiebung X
Scherung Y nach XSkalierung YScherung Y nach ZVerschiebung Y
Scherung Z nach XScherung Z nach YSkalierung ZVerschiebung Z

Jeder Punkt wird als 4D-Vektor "[x, y, z, 1]" behandelt. Die vierte Zeile "[0,0,0,1]" sorgt dafür, dass die Verschiebung korrekt funktioniert.

Dieses Beispiel dreht um 45° in der XY-Ebene und verschiebt um "[10,20,30]" – äquivalent zu "translate([10,20,30]) rotate([0,0,45])":

angle=45;
multmatrix(m = [ [cos(angle), -sin(angle), 0, 10],
                 [sin(angle),  cos(angle), 0, 20],
                 [         0,           0, 1, 30],
                 [         0,           0, 0,  1]
              ]) union() {
   cylinder(r=10.0,h=10,center=false);
   cube(size=[10,10,10],center=false);
}

Mit "multmatrix" kannst du auch Scherungen erzeugen – das geht mit anderen Transformationen nicht:

M = [ [ 1  , 0  , 0  , 0   ],
      [ 0  , 1  , 0.7, 0   ],  // 0.7 = Scherfaktor: Y wird bei steigendem Z verschoben
      [ 0  , 0  , 1  , 0   ],
      [ 0  , 0  , 0  , 1   ] ] ;
multmatrix(M) {  union() {
    cylinder(r=10.0,h=10,center=false);
    cube(size=[10,10,10],center=false); 
} }

color

[Bearbeiten]

Färbt die Kind-Objekte mit der angegebenen Farbe (RGBA). Achtung: Farben wirken nur in der Vorschau (F5) – beim Rendern (F6) und im STL-Export werden sie ignoriert.

Funktions-Signatur:

[Bearbeiten]
color(c = [r, g, b, a]) { ... }
color(c = [r, g, b], alpha = 1.0) { ... }
color("#hexwert") { ... }
color("farbname", 1.0) { ... }

Alle RGBA-Werte müssen als Fließkommazahlen zwischen 0.0 und 1.0 angegeben werden. Möchtest du Werte aus dem Bereich [0–255] verwenden, teile einfach durch 255:

color([0,125,255]/255) { ... }

Vorlage:OpenSCAD User Manual/Tip

Benannte Farben

[Bearbeiten]

Vorlage:Requires Farben lassen sich auch per Namen angeben (Groß-/Kleinschreibung egal):

color("red") sphere(5);
color("Blue",0.5) cube(5);
color("green",alpha=0.5) cube(5);

Die Namen stammen aus der SVG-Farbliste des W3C. OpenSCAD kennt zusätzlich ""transparent"" → "[0,0,0,0]".

CSS-Farbnamen-Tabelle
(Beachte: sowohl „grey“ als auch „gray“ sind gültig!)

Purples
Lavender
Thistle
Plum
Violet
Orchid
Fuchsia
Magenta
MediumOrchid
MediumPurple
BlueViolet
DarkViolet
DarkOrchid
DarkMagenta
Purple
Indigo
DarkSlateBlue
SlateBlue
MediumSlateBlue
Reds
IndianRed
LightCoral
Salmon
DarkSalmon
LightSalmon
Red
Crimson
FireBrick
DarkRed
Blues
Aqua
Cyan
LightCyan
PaleTurquoise
Aquamarine
Turquoise
MediumTurquoise
DarkTurquoise
CadetBlue
SteelBlue
LightSteelBlue
PowderBlue
LightBlue
SkyBlue
LightSkyBlue
DeepSkyBlue
DodgerBlue
CornflowerBlue
RoyalBlue
Blue
MediumBlue
DarkBlue
Navy
MidnightBlue
Pinks
Pink
LightPink
HotPink
DeepPink
MediumVioletRed
PaleVioletRed
Greens
GreenYellow
Chartreuse
LawnGreen
Lime
LimeGreen
PaleGreen
LightGreen
MediumSpringGreen
SpringGreen
MediumSeaGreen
SeaGreen
ForestGreen
Green
DarkGreen
YellowGreen
OliveDrab
Olive
DarkOliveGreen
MediumAquamarine
DarkSeaGreen
LightSeaGreen
DarkCyan
Teal
Oranges
LightSalmon
Coral
Tomato
OrangeRed
DarkOrange
Orange
Yellows
Gold
Yellow
LightYellow
LemonChiffon
LightGoldenrodYellow
PapayaWhip
Moccasin
PeachPuff
PaleGoldenrod
Khaki
DarkKhaki
Browns
Cornsilk
BlanchedAlmond
Bisque
NavajoWhite
Wheat
BurlyWood
Tan
RosyBrown
SandyBrown
Goldenrod
DarkGoldenrod
Peru
Chocolate
SaddleBrown
Sienna
Brown
Maroon
Whites
White
Snow
Honeydew
MintCream
Azure
AliceBlue
GhostWhite
WhiteSmoke
Seashell
Beige
OldLace
FloralWhite
Ivory
AntiqueWhite
Linen
LavenderBlush
MistyRose
Grays
Gainsboro
LightGrey
Silver
DarkGray
Gray
DimGray
LightSlateGray
SlateGray
DarkSlateGray
Black

Tabelle basierend auf „Web Colors“ von Wikipedia

Hex-Farbwerte

[Bearbeiten]

Vorlage:Requires Du kannst Farben auch als Hex-String angeben – in RGB oder RGBA, mit 3/4 oder 6/8 Zeichen:

  • "#rgb"
  • "#rgba"
  • "#rrggbb"
  • "#rrggbbaa"

Wird Alpha sowohl im Hex-Wert als auch separat angegeben, hat der separate Parameter Vorrang.

Beispiel

[Bearbeiten]
Eine farbige 3D-Sinuswelle
for(i=[0:36]) {
  for(j=[0:36]) {
    color([0.5+sin(10*i)/2, 0.5+sin(10*j)/2, 0.5+sin(10*(i+j))/2])
    translate([i, j, 0])
    cube(size = [1, 1, 11+10*cos(10*i)*sin(10*j)]);
  }
}

Da "-1 ≤ sin(x) ≤ 1", liegt jeder Farbwert sicher zwischen 0 und 1.

Beispiel 2

[Bearbeiten]

So kannst du Farben optional ein- oder ausschalten:

module myModule(withColors=false) {
   c = withColors ? "red" : undef;
   color(c) circle(r=10);
}

"undef" als Farbe behält die Standardfarbe bei.

offset

[Bearbeiten]

Vorlage:Requires Standardwert (ohne Angabe): "r = 1", "chamfer = false"

"offset()" erzeugt eine neue 2D-Innen- oder Außenkontur aus einer bestehenden.

Es gibt zwei Modi:

  • Radial ("r"): Ein Kreis mit Radius "r" „rollt“ um die Kontur herum → abgerundete Ecken.
  • Delta ("delta"): Die neue Kontur hat überall denselben Abstand zur alten → eckige Ecken.

"offset" ist super, um dünne Wände zu erzeugen – z. B. durch Subtraktion einer negativen von einer positiven Offset-Kontur.

Damit kannst du auch Abrundungen simulieren:

  • Innenrundung (Fillet): "offset(r=-3) offset(delta=+3)"
  • Außenrundung (Round): "offset(r=+3) offset(delta=-3)"

Parameter

[Bearbeiten]

Der erste Parameter kann ohne Namen übergeben werden → wird als "r" interpretiert.

r oder delta

Zahl. Betrag der Verschiebung. Negativ = nach innen.
  • "r" (Standard): Radius des „Rollkreises“ → abgerundete Ecken.
  • "delta": fester Abstand → eckige Ecken.
chamfer
Boolesch. Bei "delta" bestimmt dies, ob Ecken abgeschrägt ("true") oder verlängert ("false") werden. Hat keine Wirkung bei "r".

$fa, $fs, $fn

Steuern die Glätte bei radialen Offsets (keine Wirkung bei "delta").

Vorlage:Multiple image

Beispiele

[Bearbeiten]
Beispiel 1: Ergebnis.
// Beispiel 1
linear_extrude(height = 60, twist = 90, slices = 60) {
   difference() {
     offset(r = 10) square(20, center = true);
     offset(r = 8) square(20, center = true);
   }
}
// Beispiel 2: Fillet-Modul
module fillet(r) {
   offset(r = -r) offset(delta = r) children();
}


Vorlage:Requires

"fill()" entfernt Löcher aus Polygonen, ohne die Außenkontur zu verändern. Bei konvexen Formen ist das Ergebnis identisch mit "hull()".

Beispiel

Beispiel 1: Ergebnis.
t = "OpenSCAD";

linear_extrude(15) {
	text(t, 50);
}
color("darkslategray") {
	linear_extrude(2) {
		offset(4) {
			fill() {
				text(t, 50);
			}
		}
	}
}

minkowski

[Bearbeiten]
Ein Quader und ein Zylinder
Minkowski-Summe davon

Zeigt die Minkowski-Summe der Kind-Objekte an.

Beispiel: Du willst einen flachen Quader mit abgerundeten Kanten? Nimm den Quader und einen Zylinder:

$fn=50;
cube([10,10,1]);
cylinder(r=2,h=1);

Und bilde die Minkowski-Summe:

$fn=50;
minkowski() {
  cube([10,10,1]);
  cylinder(r=2,h=1);
}

Achtung: Der Ursprung des zweiten Objekts bestimmt die Addition! Diese beiden Varianten liefern unterschiedliche Ergebnisse:

minkowski() {
	cube([10, 10, 1]);
	cylinder(1, center=true); // symmetrisch um Ursprung
}
minkowski() {
	cube([10, 10, 1]);
	cylinder(1); // liegt bei z ≥ 0
}

Warnung: Bei hohen "$fn"-Werten wird’s schnell sehr rechenintensiv – denn jeder Punkt des ersten Objekts wird mit jedem Punkt des zweiten kombiniert!

Warnung: Wenn eine Eingabe aus mehreren Teilen besteht (z. B. "sphere(); cylinder();"), behandelt "minkowski" sie als getrennte Objekte – das führt oft zu unerwünschten „Brücken“. Um das zu vermeiden, packe alles in ein "union()".

Zwei Zylinder
Konvexe Hülle davon

Zeigt die konvexe Hülle der Kind-Objekte an.

Beispiel:

hull() {
    translate([15,10,0]) circle(10);
    circle(10);
}

"hull()" arbeitet bei 2D-Objekten nur in der XY-Ebene – die Z-Höhe wird ignoriert.

Tipp: Es ist viel schneller, "hull()" auf 2D-Kreisen anzuwenden und das Ergebnis dann mit "linear_extrude()" in 3D zu heben, als direkt "hull()" auf 3D-Zylindern zu verwenden – auch wenn das Ergebnis gleich aussieht!