OpenSCAD für Anfänger · Teil 7TutorialEinsteiger

OpenSCAD

OpenSCAD für Anfänger – Teil 7: Löcher und Ausschnitte mit difference()

Erzeuge Bohrungen, Taschen und Durchbrüche mit difference() und ergänze einen parametrischen Winkelhalter um Befestigungsbohrungen.

Veröffentlicht am · Aktualisiert am

5 Minuten Lesezeit · 1 PDF-Download

Mit difference() erzeugst du in OpenSCAD Löcher und Ausschnitte, indem du Schneidkörper von einem Grundkörper abziehst. In diesem Tutorial baust du Schritt für Schritt Bohrungen und einen Winkelhalter mit Befestigungslöchern.

Voraussetzungen

Du brauchst OpenSCAD und die Grundlagen aus Teil 6 des Kurses.

Kapitel 2 – Richtig konstruieren

Im vorherigen Teil haben wir mit union() mehrere Grundkörper zu einer gemeinsamen Konstruktion zusammengefasst.

Jetzt lernen wir die zweite wichtige boolesche Operation kennen:

difference();

Mit difference() wird Geometrie von einem anderen Körper abgezogen.

Damit lassen sich beispielsweise erzeugen:

  • Bohrungen

  • Ausschnitte

  • Durchbrüche

  • Taschen

  • Hohlräume

  • Kabelöffnungen

  • Steckerausschnitte

Gerade für technische 3D-Druckteile gehört difference() deshalb zu den wichtigsten OpenSCAD-Befehlen überhaupt.

Lernziel:
Nach dieser Lektion kannst du Körper voneinander abziehen und damit parametrische Bohrungen und Ausschnitte erzeugen. Außerdem kannst du union() und difference() miteinander kombinieren.


OpenSCAD difference(): So funktioniert die Subtraktion

Ein einfaches Beispiel:

difference() {

    cube([40, 30, 10]);

    cylinder(
        h=10,
        d=10,
        $fn=64
    );
}

Der erste Körper innerhalb von difference() ist der Grundkörper.

Alle folgenden Körper werden davon abgezogen.

Das Prinzip lautet also:

Grundkörper
-
Schneidkörper
=
Ergebnis
OpenSCAD-Code mit difference-Block und Quader mit kreisförmigem Ausschnitt an einer Ecke.
Im ersten difference()-Beispiel liegt der Zylinder im Ursprung und schneidet deshalb eine Ecke des Quaders aus.

Die Reihenfolge ist wichtig

Bei union() spielt die Reihenfolge der enthaltenen Körper meist keine große Rolle.

Bei difference() dagegen schon.

Beispiel:

difference() {

    grundkoerper();

    schneidkoerper1();

    schneidkoerper2();
}

Dabei gilt:

  1. Das erste Objekt bleibt bestehen.

  2. Das zweite wird abgezogen.

  3. Das dritte wird ebenfalls abgezogen.

Weitere Objekte würden ebenfalls vom ersten Körper entfernt.


Eine Bohrung erzeugen

Nehmen wir einen einfachen Quader:

cube([40, 30, 10]);

Um eine mittige Bohrung zu erzeugen, verwenden wir einen Zylinder:

difference() {

    cube([40, 30, 10]);

    translate([
        20,
        15,
        0
    ])
        cylinder(
            h=10,
            d=8,
            $fn=64
        );
}

Der Zylinder besitzt 8 mm Durchmesser und wird in der Mitte des Quaders positioniert.

Quader mit mittiger Bohrung und sichtbaren Darstellungsartefakten auf der oberen Fläche in der OpenSCAD-Vorschau.
Der Schneidzylinder endet hier bündig mit der Oberseite. In der Vorschau sind an der Bohrung Darstellungsartefakte sichtbar.

Schneidkörper etwas größer machen

Bei booleschen Operationen ist es meist sinnvoll, einen Schneidkörper nicht exakt an den Außenflächen enden zu lassen.

Statt:

cylinder(
    h=10,
    d=8
);

verwenden wir beispielsweise:

translate([0, 0, -1])
    cylinder(
        h=12,
        d=8,
        $fn=64
    );

Der Zylinder ragt damit sowohl unten als auch oben etwas aus dem Quader heraus.

OpenSCAD-Code mit überstehendem Schneidzylinder und Quader mit sauber dargestellter mittiger Bohrung.
Mit Start bei Z = −1 und Höhe 12 reicht der Schneidzylinder über beide Seiten des 10 mm hohen Quaders hinaus.

Warum ist der Überstand sinnvoll?

Wenn zwei Flächen exakt aufeinanderliegen, können bei geometrischen Berechnungen ungünstige Grenzfälle entstehen.

Deshalb ist es eine gute Angewohnheit, Schneidkörper etwas größer als nötig zu machen.

Ein kleiner Überstand von beispielsweise:

1

Millimeter ist bei vielen einfachen Konstruktionen ausreichend.


Überstand parametrisch definieren

ueberstand = 1;

Dann kann die Bohrung beispielsweise so aufgebaut werden:

translate([
    breite / 2,
    tiefe / 2,
    -ueberstand
])
    cylinder(
        h=hoehe + 2 * ueberstand,
        d=bohrung_d,
        $fn=64
    );

Der Schneidkörper reicht damit auf beiden Seiten über das Bauteil hinaus.


Parametrische Bohrung

Das vollständige Beispiel:

breite = 40;
tiefe = 30;
hoehe = 10;

bohrung_d = 8;
ueberstand = 1;

difference() {

    cube([
        breite,
        tiefe,
        hoehe
    ]);

    translate([
        breite / 2,
        tiefe / 2,
        -ueberstand
    ])
        cylinder(
            h=hoehe + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );
}

Ändern wir beispielsweise:

breite = 60;

bleibt die Bohrung automatisch mittig.


Mehrere Bohrungen

Innerhalb von difference() können beliebig viele Schneidkörper verwendet werden.

Beispiel:

difference() {

    cube([60, 30, 10]);

    translate([15, 15, -1])
        cylinder(
            h=12,
            d=8,
            $fn=64
        );

    translate([45, 15, -1])
        cylinder(
            h=12,
            d=8,
            $fn=64
        );
}
OpenSCAD-Code mit zwei Schneidzylindern und Vorschau einer Platte mit zwei durchgehenden Löchern.
Zwei Schneidzylinder erzeugen zwei Bohrungen innerhalb desselben difference()-Blocks.

Rechteckige Ausschnitte

Auch Quader können als Schneidkörper verwendet werden.

Beispiel:

difference() {

    cube([60, 40, 10]);

    translate([
        15,
        10,
        -1
    ])
        cube([
            30,
            20,
            12
        ]);
}

Damit entsteht ein rechteckiger Durchbruch.

Solche Ausschnitte eignen sich beispielsweise für:

  • Displays

  • Steckverbinder

  • Kabel

  • Lüftungsöffnungen

  • Führungen

  • Taschen


union() und difference() kombinieren

Jetzt verwenden wir wieder unseren Winkelhalter aus Teil 6.

Er besteht aus:

union() {

    // Grundplatte

    // Rückwand
}

Diesen kompletten Grundkörper können wir innerhalb einer difference() verwenden:

difference() {

    union() {

        // Grundkörper

    }

    // Schneidkörper
}

Die Struktur kann man sich so vorstellen:

difference
├── union
│   ├── Grundplatte
│   └── Rückwand
├── Bohrung 1
└── Bohrung 2

Praxisprojekt: Winkelhalter mit Befestigungsbohrungen

Wir bauen den Winkelhalter aus Teil 6 weiter aus.

Parameter des Halters

breite = 80;
tiefe = 40;
hoehe = 50;
wand = 6;

Parameter der Bohrungen

bohrung_d = 5;
rand = 10;
ueberstand = 1;

Grundkörper

union() {

    // Grundplatte
    cube([
        breite,
        tiefe,
        wand
    ]);

    // Rückwand
    translate([
        0,
        0,
        wand
    ])
        cube([
            breite,
            wand,
            hoehe - wand
        ]);
}

Linke Bohrung

translate([
    rand,
    tiefe / 2,
    -ueberstand
])
    cylinder(
        h=wand + 2 * ueberstand,
        d=bohrung_d,
        $fn=64
    );

Die Bohrung befindet sich:

  • rand Millimeter von der linken Außenkante entfernt

  • mittig in Y-Richtung

  • vollständig durch die Grundplatte


Rechte Bohrung

Die zweite Bohrung können wir aus der Gesamtbreite berechnen:

translate([
    breite - rand,
    tiefe / 2,
    -ueberstand
])
    cylinder(
        h=wand + 2 * ueberstand,
        d=bohrung_d,
        $fn=64
    );

Damit bleibt der Abstand zur rechten Außenkante automatisch gleich.


Vollständiger Winkelhalter

// -------------------------
// Parameter
// -------------------------

breite = 80;
tiefe = 40;
hoehe = 50;
wand = 6;

bohrung_d = 5;
rand = 10;

ueberstand = 1;

// -------------------------
// Modell
// -------------------------

difference() {

    // ---------------------
    // Grundkörper
    // ---------------------

    union() {

        // Grundplatte
        cube([
            breite,
            tiefe,
            wand
        ]);

        // Rückwand
        translate([
            0,
            0,
            wand
        ])
            cube([
                breite,
                wand,
                hoehe - wand
            ]);
    }

    // ---------------------
    // Bohrungen
    // ---------------------

    // linke Bohrung
    translate([
        rand,
        tiefe / 2,
        -ueberstand
    ])
        cylinder(
            h=wand + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );

    // rechte Bohrung
    translate([
        breite - rand,
        tiefe / 2,
        -ueberstand
    ])
        cylinder(
            h=wand + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );
}

Parametrische Vorteile

Ändern wir:

bohrung_d = 6;

werden automatisch beide Bohrungen größer.

Ändern wir:

rand = 15;

verschieben sich beide Bohrungen entsprechend nach innen.

Ändern wir:

breite = 100;

bleibt die rechte Bohrung automatisch im gleichen Abstand zur rechten Außenkante.

Genau solche Abhängigkeiten machen parametrische Konstruktionen besonders flexibel.


Eine Bohrung durch die Rückwand

Auch die senkrechte Rückwand kann durchbohrt werden.

Dazu müssen wir den Schneidzylinder drehen.

Beispiel:

translate([
    breite / 2,
    -ueberstand,
    hoehe / 2
])
    rotate([-90, 0, 0])
        cylinder(
            h=wand + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );

Dabei wird:

  1. der Zylinder erzeugt

  2. um 90 Grad gedreht

  3. an die gewünschte Position verschoben

  4. vom Grundkörper abgezogen


Verschachtelte Operationen lesen

Mit zunehmender Komplexität wird der Code stärker verschachtelt.

Zum Beispiel:

difference() {

    union() {

        cube(...);

        translate(...)
            cube(...);
    }

    translate(...)
        cylinder(...);
}

Man kann sich die Struktur als Baum vorstellen:

difference
├── union
│   ├── cube
│   └── translate
│       └── cube
└── translate
    └── cylinder

Diese Denkweise hilft später enorm beim Verständnis größerer OpenSCAD-Modelle.


Mitmach-Aufgabe

Erstelle einen parametrischen Winkelhalter mit folgenden Abmessungen:

Halter

Parameter Wert
Breite 100 mm
Tiefe 50 mm
Höhe 60 mm
Wandstärke 6 mm

Bohrungen

Parameter Wert
Durchmesser 6 mm
Randabstand 15 mm

Die Grundplatte soll zwei Befestigungsbohrungen besitzen.

Die linke Bohrung befindet sich 15 mm von der linken Außenkante entfernt.

Die rechte Bohrung soll automatisch 15 mm von der rechten Außenkante entfernt liegen.

Verwende:

union()
difference()
translate()
cylinder()

Musterlösung

// -------------------------
// Parameter
// -------------------------

breite = 100;
tiefe = 50;
hoehe = 60;
wand = 6;

bohrung_d = 6;
rand = 15;

ueberstand = 1;

// -------------------------
// Modell
// -------------------------

difference() {

    // Grundkörper
    union() {

        // Grundplatte
        cube([
            breite,
            tiefe,
            wand
        ]);

        // Rückwand
        translate([
            0,
            0,
            wand
        ])
            cube([
                breite,
                wand,
                hoehe - wand
            ]);
    }

    // linke Bohrung
    translate([
        rand,
        tiefe / 2,
        -ueberstand
    ])
        cylinder(
            h=wand + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );

    // rechte Bohrung
    translate([
        breite - rand,
        tiefe / 2,
        -ueberstand
    ])
        cylinder(
            h=wand + 2 * ueberstand,
            d=bohrung_d,
            $fn=64
        );
}

Was haben wir gelernt?

Nach dieser Lektion kennst du die zweite wichtige boolesche Operation:

difference();

Du weißt:

  • der erste Körper bleibt erhalten

  • alle folgenden Körper werden abgezogen

  • Zylinder eignen sich hervorragend für Bohrungen

  • Quader können als rechteckige Schneidkörper verwendet werden

  • Schneidkörper sollten möglichst etwas überstehen

  • beliebig viele Geometrien können gleichzeitig entfernt werden

  • union() und difference() lassen sich verschachteln

  • Bohrungspositionen können vollständig parametrisch berechnet werden

Damit können wir bereits viele typische technische Bauteile für den 3D-Druck konstruieren.


Im nächsten Teil

Im nächsten Teil lernen wir die dritte grundlegende boolesche Operation kennen:

intersection();

Während union() Körper vereinigt und difference() Geometrie entfernt, behält intersection() nur den Bereich, in dem sich mehrere Körper überschneiden.

Damit lassen sich unter anderem interessante Formkörper und gezielt begrenzte Geometrien erzeugen.


Häufige Fragen

Wie entsteht mit difference() eine Bohrung?

Ein Zylinder wird vom Grundkörper abgezogen. Er muss an der gewünschten Bohrungsposition liegen und für ein durchgehendes Loch die gesamte Materialstärke durchdringen. Ein kleiner Überstand auf beiden Seiten erleichtert eine saubere Subtraktion.

Warum verschwindet bei difference() der falsche Körper?

Nur das erste Kind im Block bleibt als Grundkörper erhalten; alle folgenden Kinder werden davon abgezogen. Soll der Grundkörper aus mehreren Teilen bestehen, fasse diese zuerst mit union() zusammen.

Passendes Cheatsheet

Im Cheatsheet „Boolesche Operationen“ findest du ergänzende Grundlagen zum Nachschlagen. Du kannst das Cheatsheet auch direkt als PDF herunterladen.

Weiterlernen