The teardrop is around in the 3D printing scene virtually forever. It’s even part of RepRap’s icon.
This geometric shape is used whenever an object with horizontal holes is printed. This avoids overhangs greater than 45° at the top of the hole, which are not (or at least not easily and clean) printable on FDM printers without support material.
Some people use teardrops only for larger holes (>4 or 5 mm diameter), since the overhangs are not such a big problem on smaller holes. While this is generally true, I tend to use teardrops even for smaller holes (3mm or even 1mm), since it turns out, that even these tiny holes look cleaner when printed in teardrop shape.
It always was kind of tricky to design objects containing teardrop shapes in classic CAD apps, since the teardrop shape isn’t a standard primitive in those applications (at least not in those I used).
This luckily changed with the release of OpenSCAD and it’s ability to use user written libraries.
At the latest with the release of Randy Young’s great Libs.scad library, using teardrops instead of cylinders for punching holes into objects is easy as pie.
Here’s the code of teardrop module from the Libs.scad library. I changed the Libs.scad code on my computer to use the polygon code instead of whosawwhatsis’ projection code, since the projection code takes forever to render in CGAL mode.
module teardrop(radius=5, length=10, angle=90) { $fn=resolution(radius); rotate([0, angle, 0]) union() { linear_extrude(height = length, center = true, convexity = radius, twist = 0) circle(r = radius, center = true); linear_extrude(height = length, center = true, convexity = radius, twist = 0) polygon(points = [ [radius * -cos(-45), radius * sin(-45)], [radius * -cos(-45), radius * -sin(-45)], [(sin(-135) + cos(-135)) * radius, 0]], paths = [[0, 1, 2]]); } // This code take forever to render: // teardrop module by whosawhatsis <www.thingiverse.com/thing:3457> // Creative Commons LGPL, 2010. I added default values and resolution code /* rotate([0, angle, 0]) union() { linear_extrude(height = length, center = true, convexity = radius, twist = 0) circle(r = radius, center = true); linear_extrude(height = length, center = true, convexity = radius, twist = 0) projection(cut = false) rotate([0, -angle, 0]) translate([0, 0, radius * sin(45) * 1.5]) cylinder(h = radius * sin(45), r1 = radius * sin(45), r2 = 0, center = true); }*/ }
The problem with teardrop holes is, that they need considerably more space. This can be a real problem, when the main object is limited in size for one reason or another.
For example, this is a ball bearing retainer:
When simply using teardrops instead of cylinders for the holes, the result would be this:
As you can see, the larger footprint of the teardrop shape becomes a real problem with the larger holes in front and back of the retainer. In this case, the structural stability might still be good enough, since the smaller center bore is still closed at the top. But often teardrop holes just aren’t an option unless you significantly re-design the main object (and usually make it larger).
Well, it turns out there is another option after all:
Introducing the Flat Teardrop
The solution is simple. Although overhangs > 45° are a problem in 3D printing, reasonably short bridges aren’t!
So why not just cut off the dead space in the tip of a teardrop?
I wrote a new module in OpenSCAD, called flatteardrop. This module is derived from the original teardrop module in Libs.scad:
module flatteardrop(radius=5, length=10, angle=90, luck=0) { $fn=resolution(radius); sx1 = radius * sin(-45); sx2 = radius * -sin(-45); sy = radius * -cos(-45); ex = 0; ey = (sin(-135) + cos(-135)) * radius; dx= ex-sx1; dy = ey-sy; eys = -radius-luck; dys = eys-sy; ex1 = sy+dys*dx/dy; ex2 = -ex1; rotate([0, angle, 0]) union() { linear_extrude(height = length, center = true, convexity = radius, twist = 0) circle(r = radius, center = true); linear_extrude(height = length, center = true, convexity = radius, twist = 0) polygon(points = [ [sy, sx1], [sy, sx2], [eys, ex2], [eys, ex1]], paths = [[0, 1, 2, 3]]); } }
Since the top is cut at radius height of the theoretical cylinder inside the teardrop, it might be a problem when the bridged part at top of the flat teardrop sags a bit during printing. This might happen when the bridge gets longer, i.e. on larger teardrops.
As a countermeasure it’s possible to add a little bit height to the cut “for luck”. To do so, set the value of the luck parameter to the additional height. However, the default value of this parameter is 0 and simply can be omitted in most cases.
The module makes use of the resolution function of the Libs.scad library. If you add the flatteardrop module to this library (as I did on my computer), it just works. If you plan to use the flatteardrop module separately, you might want to comment out the line
$fn=resolution(radius);
or set $fn to a fixed value (e.g. 36).
For the record, the projection script was trying to solve a problem that i’m not sure really existed, to minimize the teardrop shape to exactly what was required to avoid overhangs > 45 degrees. There was originally a bug in the projection code that made rendering take a long time, I fixed that bug, but in hindsight, my second solution using polygons was probably better.
The best way to turn my teardrop shapes into truncated ones is to intersect them with a square, but I’ve moved on from teardrops to hexagons and octagons because they have a more predictable relationship between the inner and outer diameters, with fewer variables to worry about.
I use these, which seem simpler to me:
// truncated teardrop
module teardrop (r=8, h=20) {
render()
rotate([-270, 0, 90]) {
cylinder(r=r, h=h, $fn=64);
translate([-(r * sqrt(2)) / 2, 0, 0]) cube([r * sqrt(2), r * sqrt(2) / 2, h]);
difference() {
rotate([0, 0, 45]) cube([r, r, h]);
translate([-r, r, -1]) cube([2 * r, r, h + 2]);
}
}
}
// tapered truncated teardrop
module teardrop2(r1 = 10, r2 = 5, h=5) {
difference() {
cube([r1, r1, h]);
translate([r1 * sqrt(2), 0, 0]) rotate([0, 0, 45]) rotate([0, -atan((r1 – r2) / h), 0]) translate([0, 0, -r1]) cube([r1 * 2, r1 * 2, h * (r1)]);
translate([r1, r1, 0]) rotate([0, 0, 90]) rotate([0, -atan((r1 – r2) / h), 0]) translate([0, 0, -r1]) cube([r1 * 2, r1 * 2, h * (r1)]);
translate([r1, -r1, 0]) rotate([0, 0, 0]) rotate([0, -atan((r1 – r2) / h), 0]) translate([0, 0, -r1]) cube([r1 * 2, r1 * 2, h * (r1)]);
}
cylinder(r1 = r1, r2 = r2, h=h);
}