# Practical Solid Modeling for 3D Printing with OpenSCAD

I’m teaching an introduction to OpenSCAD for Squidwrench this evening in Highland NY…

To quote from the course description:

This intensive course will bootstrap you into designing solid models of useful objects suitable for production on a 3D printer.

We won’t build anything like this, but it makes a nice showpiece:

The presentation in PDF form: Practical Solid Modeling for 3D Printing with OpenSCAD – 2013-09-25

I plan on a bunch of learning-by-doing, but, in the event the typing becomes burdensome, here are the OpenSCAD files:

A simplified version of the Dishwasher Rack Protector, minus the support structure:

```// Dishwasher rack protector
// Simplified version for OpenSCAD course
// Ed Nisley KE4ZNU - July 2013

Protrusion = 0.1;							// make holes end cleanly

//-------
// Dimensions

PinDia = 4.0 + 0.5;                 // upright pin diameter + clearance

PinOC = 3.4;                        // bar center to pin center

PinTubeLength = 15.0;               // length of upright tube along pin

BarDia = 4.7 + 0.2;                 // horizontal bar diameter + clearance

BarTubeLength = 30.0;               // length of horizontal half tube along bar

TubeWall = 4*ThreadWidth;           // wall thickness -- allow for fill motion

TubeSides = 4 * 4;                  // default side count for tubes (in quadrants)
\$fn = TubeSides;

SupportClear = 0.85;                // support structure clearance fraction

//-------

module ShowPegGrid(Space = 10.0,Size = 1.0) {

Range = floor(50 / Space);
for (x=[-Range:Range])
for (y=[-Range:Range])
translate([x*Space,y*Space,Size/2])
%cube(Size,center=true);
}

//-------
// Put it together

module Protector() {

difference() {
union() {
translate([0,PinOC,0])
rotate(180/TubeSides)
cylinder(r=(PinDia + 2*TubeWall)/2,h=PinTubeLength);
translate([-BarTubeLength/2,0,0])
rotate([0,90,0])
rotate(180/TubeSides)
cylinder(r=(BarDia + 2*TubeWall)/2,h=BarTubeLength);
}

translate([0,PinOC,-Protrusion])
rotate(180/TubeSides)

translate([-BarTubeLength/2,0,0])
rotate([0,90,0])
rotate(180/TubeSides)
translate([0,0,-Protrusion])

cube([(BarTubeLength + 2*Protrusion),
BarTubeLength,
}

}

//-------
// Build it!

ShowPegGrid();

Protector();
```

And a bare-bones version:

```// Dishwasher rack protector
// Trivial version for OpenSCAD course
// Ed Nisley KE4ZNU - July 2013

difference() {
union() {
translate([0,3.4,0])
color("lightgreen")
cylinder(r=5,h=15);
translate([-15.0,0,0])
rotate([0,90,0])
color("lightyellow")
cylinder(r=6.0,h=30.0);
}

translate([0,3.4,-15.0])
cylinder(r=3.0,h=3*15.0);

translate([-30.0,0,0])
rotate([0,90,0])
cylinder(r=3.0,h=2*30.0);

translate([0,0,-5.0])
cube([50,50,10.0],center=true);
}
```

A simplified version of the Sink Drain Strainer I wrote up for Digital Machinist:

```// Strainer Plate
// Simplified version for OpenSCAD course
// Ed Nisley KE4ZNU - July 2013

Layout = "Build";				// Handle Plate Show Build

Protrusion = 0.1;							// make holes end cleanly

PlateOD = 150.0;							// strainer plate diameter
PlateThick = 5.0;							//  .. thickness

HoleOD = 6.0;								// hole diameter

NumRings = 4;								// number of hole rings
RingMinDia = 20.0;							// innermost ring diameter
RingStep = 30.0;							// ring diameter increment

HandleOD = 8.0;								// handle diameter
HandleLength = 15.0;						//  .. length
HandlePegOD = HandleOD/2;					//  .. mounting peg
HandlePegLength = 1.5;

//-- Create single handle

module Handle() {

cylinder(r=HandleOD/2,h=HandleLength);
cylinder(r=HandlePegOD/2,h=(HandleLength + HandlePegLength));

}//-- Create single ring of holes

module RingHoles(RingDia,HoleDia,Thickness) {

Num = floor(90/asin(HoleDia/RingDia));	// how many holes fit in ring?
echo(str("Dia: ",RingDia," Holes: ",Num));

for(n=[0:(Num-1)]) {
rotate([0,0,n*360/Num])
translate([RingDia/2,0,-Protrusion])
cylinder(r=HoleDia/2,
h=(Thickness + 2*Protrusion));
}

}

//-- Create strainer plate with holes

module StrainerPlate() {

difference() {
cylinder(r=PlateOD/2,h=PlateThick);
for (RingID = [0:NumRings-1]) {
RingHoles((RingMinDia + RingID*RingStep),
HoleOD,PlateThick);
}
cylinder(r=HandlePegOD/2,h=3*PlateThick,center=true);
}
}

//-- Build it!

if (Layout == "Plate")
StrainerPlate();

if (Layout == "Handle")
Handle();

if (Layout == "Build") {
StrainerPlate();
translate([PlateOD/2,PlateOD/2,0])
Handle();
translate([(PlateOD/2 - 2*HandleOD),
PlateOD/2,0])
Handle();
}

if (Layout == "Show") {
color("LightYellow")
StrainerPlate();
color("LightGreen") {
translate([0,0,-HandleLength])
Handle();
translate([0,0,(PlateThick + HandleLength)])
rotate([180,0,0])
Handle();
}

}
```

And a bare-bones version, minus the handles:

```Protrusion = 0.1;

PlateOD = 150.0;
PlateThick = 5.0;
HoleOD = 6.0;

NumRings = 4;
RingMinDia = 20.0;
RingStep = 30.0;

module RingHoles(RingDia,HoleDia,Thickness) {

Num = floor(90/asin(HoleDia/RingDia));
echo("Dia: ",RingDia," holes: ",Num);

for(n=[0:(Num-1)]) {
rotate([0,0,n*360/Num])
translate([RingDia/2,0,-Protrusion])
cylinder(r=HoleDia/2,
h=(Thickness + 2*Protrusion));
}
}

difference() {
cylinder(r=PlateOD/2,h=PlateThick);
for (RingID = [0:NumRings-1]) {
RingHoles((RingMinDia + RingID*RingStep),
HoleOD,PlateThick);
}
}
```

[Update: The talk went well and took a bit under three hours, although by mutual agreement we didn’t fire up the M2 at the end. I’ll work on a short talk about Design for Printability and we’ll run that with a separate printing session. A good time was had by all!]

## 14 thoughts on “Practical Solid Modeling for 3D Printing with OpenSCAD”

1. holy smoke! best concise tutorial i have ever seen for openscad! i thought i was pretty good, but you managed to teach me even more! i feel like i just took your course. where do i send the check?

1. Ed says:

Imagine what it’ll be like with a few hours of standup comedy!

where do i send the check?

Dang, I knew I forgot a slide… Paypal should work fine, though. [grin]

2. What are the chances that the audio will be recorded? It would be hyper-groovy to be able to listen to the presentation while flipping through the pages.

1. Ed says:

Over the years various camera fanatics have tried that, but I’m apparently non-recordable; either I speak badly or Something Just Doesn’t Work.

On the other hand, if all those glitzy singers can lip-sync while gyrating vigorously, I ought to be able stand-and-deliver into a mic, right? Youtube, here I come … [wince]

3. smellsofbikes says:

I may be reading too quickly but on page 48 a definition of ‘manifold’ may be useful if the pdf is used as a stand-alone rather than accompanying a verbal discussion.

1. Ed says:

on page 48 a definition of ‘manifold’

That’s where I say “Aaaaand what’s this ‘manifold’ thing? Hold that thought; you’ll see some examples in a bit.” Another couple dozen clicks, we get to “Geometric Requirements” on page 84, and then the examples appear.

If I can remember to say it, of course. I’m hoping for a straight man to ask questions to keep me on track…

4. This is a very useful PDF that covers a lot of the details not generally covered elsewhere. Thanks.

You draw your own supports? Have you found the slic3r automated supports not suitable for your needs?

Also, I had a question about drawing thin walled objects. I’m trying to get a thin wall that is, say, 5 extrusion widths across exactly to convince slic3r not to insert a zig-zag infill, which slows down the print considerably. I’ve tried playing with various dimensions, but it continues to insist on adding that infill. Do you have any idea if it is possible? The thin walls are only part of a larger object, so I can’t do something global like turning off infill.

1. Ed says:

automated supports not suitable

Mostly, the things I build require so little support that it’s easier to just add a few lines that build exactly what’s needed. That wouldn’t work with the much larger support structures other folks need for their objects, though, so it’s more happenstance than anything significant.

not to insert a zig-zag infill

I think you can get complete parallel “infill” only when the total number of perimeters on both sides adds up to the exact width of the wall, so there’s no actual infill required. Thinner walls produce gaps where the perimeters can’t fit and thicker walls require infill between the perimeters, so it’s a delicate balance.

In fact, if the walls aren’t exactly straight, then the parallel perimeter threads might not fit at the bends, so you get weird little holes and gaps.

I spend a lot of time having gcode.ws tell me that what I’m trying to do doesn’t work…

5. Thanks. You were right, I had to lower the perimeter settings to get it to work. gcode.ws is super handy.

1. Ed says:

Good!

The trouble with gcode.ws is that you (well, I) can spend way too much time futzing with the details. [sigh]