diff --git a/readme.md b/readme.md
index fb90dbe..2b8c6e8 100644
--- a/readme.md
+++ b/readme.md
@@ -24,18 +24,18 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
Belts | LED_meters | Rod | Carriers | Fillet | Polyholes |
Blowers | LEDs | SCS_bearing_blocks | Corner_block | Gears | Rounded_rectangle |
Bulldogs | Leadnuts | SK_brackets | Door_hinge | Hanging_hole | Sphere |
- Buttons | Light_strips | SMDs | Door_latch | Layout | Teardrops |
- Cable_strips | Linear_bearings | SSRs | Fan_guard | Maths | |
- Cameras | Mains_sockets | Screws | Fixing_block | Offset | |
- Circlips | Microswitches | Sealing_strip | Flat_hinge | Quadrant | |
- Components | Microview | Sheets | Foot | Round | |
- DIP | Modules | Spades | Handle | Rounded_cylinder | |
- D_connectors | Nuts | Spools | PCB_mount | Rounded_polygon | |
- Displays | O_ring | Springs | PSU_shroud | Sector | |
- Extrusion_brackets | Opengrab | Stepper_motors | Printed_box | Sweep | |
- Extrusions | PCB | Swiss_clips | Ribbon_clamp | Thread | |
- Fans | PCBs | Toggles | SSR_shroud | Tube | |
- Fuseholder | PSUs | Transformers | Screw_knob | | |
+ Buttons | Light_strips | SMDs | Door_latch | Horiholes | Teardrops |
+ Cable_strips | Linear_bearings | SSRs | Fan_guard | Layout | |
+ Cameras | Mains_sockets | Screws | Fixing_block | Maths | |
+ Circlips | Microswitches | Sealing_strip | Flat_hinge | Offset | |
+ Components | Microview | Sheets | Foot | Quadrant | |
+ DIP | Modules | Spades | Handle | Round | |
+ D_connectors | Nuts | Spools | PCB_mount | Rounded_cylinder | |
+ Displays | O_ring | Springs | PSU_shroud | Rounded_polygon | |
+ Extrusion_brackets | Opengrab | Stepper_motors | Printed_box | Sector | |
+ Extrusions | PCB | Swiss_clips | Ribbon_clamp | Sweep | |
+ Fans | PCBs | Toggles | SSR_shroud | Thread | |
+ Fuseholder | PSUs | Transformers | Screw_knob | Tube | |
Geared_steppers | Panel_meters | Tubings | Socket_box | | |
Green_terminals | Pillars | Variacs | Strap_handle | | |
Hot_ends | Pin_headers | Veroboard | | | |
@@ -5287,6 +5287,32 @@ Method to print holes in mid air. See Top
+
+---
+
+## Horiholes
+Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops).
+
+
+[utils/horiholes.scad](utils/horiholes.scad) Implementation.
+
+[tests/horiholes.scad](tests/horiholes.scad) Code for this example.
+
+### Functions
+| Function | Description |
+|:--- |:--- |
+| ```teardrop_plus_x(r, y, h)``` | Calculate the ordinate of a compensated teardrop given y. |
+| ```teardrop_x(r, y)``` | Calculate the ordinate of a teardrop given y. Sweeping y from -r to + r yields the positive X half of the shape. |
+
+### Modules
+| Module | Description |
+|:--- |:--- |
+| ```horihole(r, z, h = 0, center = true)``` | For making horizontal holes that don't need support material and are correct dimensions |
+
+
+
+
Top
---
@@ -5859,6 +5885,9 @@ This ensures `hull` and `minkowski` results have the correct dimensions when sph
For making horizontal holes that don't need support material.
Small holes can get away without it, but they print better with truncated teardrops.
+Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
+do not intrude into the circle.
+
[utils/core/teardrops.scad](utils/core/teardrops.scad) Implementation.
@@ -5867,12 +5896,12 @@ Small holes can get away without it, but they print better with truncated teardr
### Modules
| Module | Description |
|:--- |:--- |
-| ```semi_teardrop(h, r, d = undef, center = true, chamfer = 0)``` | A semi teardrop in the positive Y domain |
-| ```teardrop(h, r, center = true, truncate = true, chamfer = 0)``` | For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging |
+| ```semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)``` | A semi teardrop in the positive Y domain |
+| ```teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)``` | For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging |
| ```teardrop_chamfer(h, center, chamfer)``` | Helper module for adding chamfer to a teardrop |
-| ```teardrop_plus(h, r, center = true, truncate = true, chamfer = 0)``` | Slightly bigger teardrop to allow for the 3D printing staircase effect |
-| ```tearslot(h, r, w, center = true, chamfer = 0)``` | A horizontal slot that doesn't need support material |
-| ```vertical_tearslot(h, r, l, center = true, chamfer = 0)``` | A vertical slot that doesn't need support material |
+| ```teardrop_plus(h, r, center = true, truncate = true, chamfer = 0)``` | Slightly elongated teardrop to allow for the 3D printing staircase effect |
+| ```tearslot(h, r, w, center = true, chamfer = 0, plus = false)``` | A horizontal slot that doesn't need support material |
+| ```vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false)``` | A vertical slot that doesn't need support material |

diff --git a/tests/horiholes.scad b/tests/horiholes.scad
new file mode 100644
index 0000000..a53bac5
--- /dev/null
+++ b/tests/horiholes.scad
@@ -0,0 +1,86 @@
+//
+// NopSCADlib Copyright Chris Palmer 2020
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+$layer_height = 0.25;
+include <../utils/core/core.scad>
+use <../utils/horiholes.scad>
+
+show_disc = true;
+thickness = 3;
+length = 50;
+height = 20;
+overlap_x = 15;
+overlap_y = 5;
+
+module hole_positions() {
+ for($i = [0 : 4], $z = 5 + $i * layer_height / 5, $r = 3)
+ translate([5 + $i * 10, $z])
+ children();
+
+ for($i = [0 : 4], $z = 15 + $i * layer_height / 5, $r = 0.5 + $i / 2)
+ translate([5 + $i * 10, $z])
+ children();
+}
+
+module horiholes_stl(t = thickness) {
+ rotate([90, 0, 0])
+ difference() {
+ linear_extrude(t, center = true) {
+ difference() {
+ square([length, height]);
+
+ hole_positions()
+ horihole($r, $z);
+ }
+ }
+ }
+ if(t == thickness)
+ translate([length / 2, 0])
+ rounded_rectangle([length + 2 * overlap_x, thickness + 2 * overlap_y, 2], 5);
+}
+
+module horiholes() {
+ stl_colour(pp1_colour)
+ rotate([-90, 0, 0])
+ horiholes_stl(eps);
+
+ if(show_disc)
+ hole_positions()
+ color(silver)
+ cylinder(r = $r, h = eps, center = true, $fn = 360);
+
+ hole_positions()
+ color("red")
+ linear_extrude(2 * eps, center = true)
+ //offset(0.01, $fn = 360)
+ intersection() {
+ difference() {
+ square(8, center = true);
+
+ horihole($r, $z);
+ }
+
+ circle($r, $fn = 360);
+ }
+}
+
+if($preview)
+ rotate(is_undef($bom) ? 0 : [70, 0, 315])
+ horiholes();
+else
+ horiholes_stl();
diff --git a/tests/png/flat_hinge.png b/tests/png/flat_hinge.png
index b228a2d..e91bf77 100644
Binary files a/tests/png/flat_hinge.png and b/tests/png/flat_hinge.png differ
diff --git a/tests/png/horiholes.png b/tests/png/horiholes.png
new file mode 100644
index 0000000..573240c
Binary files /dev/null and b/tests/png/horiholes.png differ
diff --git a/tests/png/teardrops.png b/tests/png/teardrops.png
index 6c28aa4..b04ef9d 100644
Binary files a/tests/png/teardrops.png and b/tests/png/teardrops.png differ
diff --git a/utils/core/teardrops.scad b/utils/core/teardrops.scad
index 79f27e5..24e84a5 100644
--- a/utils/core/teardrops.scad
+++ b/utils/core/teardrops.scad
@@ -20,18 +20,24 @@
//
//! For making horizontal holes that don't need support material.
//! Small holes can get away without it, but they print better with truncated teardrops.
+//!
+//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
+//! do not intrude into the circle.
//
-module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
- module teardrop_2d(r, truncate) {
- hull() {
- circle4n(r);
- if(truncate)
- translate([0, r / 2])
- square([2 * r * (sqrt(2) - 1), r], center = true);
- else
- polygon([[0, 0], [eps, 0], [0, r * sqrt(2)]]);
- }
- }
+module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
+ module teardrop_2d(r, truncate)
+ hull()
+ for(y = plus ? [-1 : 1] : 0)
+ translate([0, y * (layer_height / 2 - eps)]) {
+
+ circle4n(r);
+
+ if(truncate)
+ translate([0, r / 2])
+ square([2 * r * (sqrt(2) - 1), r], center = true);
+ else
+ polygon([[0, 0], [eps, 0], [0, r * sqrt(2)]]);
+ }
render(convexity = 5)
extrude_if(h, center)
@@ -40,23 +46,23 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0) { //! For mak
teardrop_chamfer(h, center, chamfer) {
linear_extrude(eps, center = true)
teardrop_2d(r + chamfer / 2, truncate);
+
translate_z(-chamfer / 2)
linear_extrude(eps, center = true)
teardrop_2d(r, truncate);
}
}
-module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi teardrop in the positive Y domain
- module semi_teardrop_2d(r, d) {
+module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false) { //! A semi teardrop in the positive Y domain
+ module semi_teardrop_2d(r, d)
intersection() {
R = is_undef(d) ? r : d / 2;
- teardrop(r = R, h = 0);
+ teardrop(r = R, h = 0, plus = plus);
sq = R + 1;
translate([-sq, 0])
square([2 * sq, sq]);
}
- }
render(convexity = 5)
extrude_if(h, center)
@@ -65,22 +71,21 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0) { //! A semi t
teardrop_chamfer(h, center, chamfer) {
linear_extrude(eps, center = true)
semi_teardrop_2d(r + chamfer / 2, d);
+
translate_z(-chamfer / 2)
linear_extrude(eps, center = true)
semi_teardrop_2d(r, d);
}
}
-module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly bigger teardrop to allow for the 3D printing staircase effect
- teardrop(h, r + layer_height / 4, center, truncate, chamfer);
+module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
+ teardrop(h, r, center, truncate, chamfer, plus = true);
-module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot that doesn't need support material
- module tearslot_2d(r, w) {
- hull() {
- translate([-w / 2, 0]) teardrop(r = r, h = 0);
- translate([w / 2, 0]) teardrop(r = r, h = 0);
- }
- }
+module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horizontal slot that doesn't need support material
+ module tearslot_2d(r, w)
+ hull()
+ for(x = [-1, 1])
+ translate([x * w / 2, 0]) teardrop(r = r, h = 0, plus = plus);
extrude_if(h, center)
tearslot_2d(r, w);
@@ -88,19 +93,19 @@ module tearslot(h, r, w, center = true, chamfer = 0) { //! A horizontal slot tha
teardrop_chamfer(h, center, chamfer) {
linear_extrude(eps, center = true)
tearslot_2d(r + chamfer / 2, w);
+
translate_z(-chamfer / 2)
linear_extrude(eps, center = true)
tearslot_2d(r, w);
}
}
-module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical slot that doesn't need support material
- module vertical_tearslot_2d(r, l) {
- hull() {
- translate([0, l / 2]) teardrop(0, r, true);
- translate([0, -l / 2]) circle4n(r);
- }
- }
+module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //! A vertical slot that doesn't need support material
+ module vertical_tearslot_2d(r, l)
+ hull()
+ for(y = [-1, 1])
+ translate([0, y * l / 2])
+ teardrop(0, r, true, plus = plus);
extrude_if(h, center)
vertical_tearslot_2d(r, l);
@@ -108,6 +113,7 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0) { //! A vertical s
teardrop_chamfer(h, center, chamfer) {
linear_extrude(eps, center = true)
vertical_tearslot_2d(r + chamfer / 2, l);
+
translate_z(-chamfer / 2)
linear_extrude(eps, center = true)
vertical_tearslot_2d(r, l);
@@ -123,4 +129,3 @@ module teardrop_chamfer(h, center, chamfer) { //! Helper module for adding chamf
hull()
children();
}
-
diff --git a/utils/horiholes.scad b/utils/horiholes.scad
new file mode 100644
index 0000000..4328e80
--- /dev/null
+++ b/utils/horiholes.scad
@@ -0,0 +1,49 @@
+//
+// NopSCADlib Copyright Chris Palmer 2020
+// nop.head@gmail.com
+// hydraraptor.blogspot.com
+//
+// This file is part of NopSCADlib.
+//
+// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with NopSCADlib.
+// If not, see .
+//
+
+//
+//! Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops).
+//
+include <../utils/core/core.scad>
+
+function teardrop_x(r, y) = //! Calculate the ordinate of a teardrop given y. Sweeping y from -r to + r yields the positive X half of the shape.
+ let(x2 = sqr(r) - sqr(y))
+ y > r / sqrt(2) ? y >= r ? 0
+ : r * sqrt(2) - y
+ : x2 > 0 ? sqrt(x2)
+ : 0;
+
+function teardrop_plus_x(r, y, h) = //! Calculate the ordinate of a compensated teardrop given y.
+ y < -h ? teardrop_x(r, y + h)
+ : y > h ? teardrop_x(r, y - h)
+ : r;
+
+module horihole(r, z, h = 0, center = true) { //! For making horizontal holes that don't need support material and are correct dimensions
+ bot_layer = floor((z - r) / layer_height);
+ top_layer = ceil((z + r) / layer_height);
+ render(convexity = 5)
+ extrude_if(h, center)
+ for(i = [bot_layer : top_layer]) {
+ Z = i * layer_height;
+ x = teardrop_plus_x(r, Z - z + layer_height / 2, layer_height / 2);
+ if(x > 0)
+ translate([-x, Z - z])
+ square([2 * x, layer_height]);
+ }
+}