uilleann

3d printable Uilleann bagpipes
git clone https://git.woozle.org/neale/uilleann.git

commit
c38bb58
parent
cb65741
author
Neale Pickett
date
2025-11-28 09:55:45 -0700 MST
maybe fix tenon, clean up everything
16 files changed,  +145, -333
M daye/Makefile
+10, -2
 1@@ -1,9 +1,17 @@
 2-default: chanter.stl
 3+default: chanter
 4 
 5+.PHONY: chanter
 6+chanter: chanter/top.3mf
 7+chanter: chanter/bottom.3mf
 8+
 9+.PHONY: clean
10 clean:
11-	rm -f *.stl
12+	rm -f */*.stl */*.3mf
13 
14 %.stl: %.scad
15 	openscad -o $@ $<
16 
17+%.3mf: %.scad
18+	openscad -o $@ $<
19+
20 chanter/chanter-%.stl: chanter/chanter-%.scad chanter/chanter.scad
M daye/chanter/bottom.scad
+1, -1
1@@ -1,5 +1,5 @@
2 include <../common.scad>
3-use <./chanter.scad>
4+use <./complete.scad>
5 
6 tenon(top=false) {
7   chanter();
D daye/chanter/chanter.scad
+0, -114
  1@@ -1,114 +0,0 @@
  2-include <../common.scad>
  3-
  4-height = 360.0;
  5-od = 16.0;
  6-od_derlin = od + 0.5;
  7-id_bot = 13.2;
  8-id_top = 5.51;
  9-cut_height = 155; // Where to cut it in half
 10-
 11-module tonehole(h=10, d=10, undercut=0) {
 12-  rotate([0, 0, -90])
 13-  translate([od/2, 0, h]) {
 14-    rotate([0, -90+undercut, 0]) {
 15-      // Scoot it down a hair so it will penetrate the entire tube when rotated
 16-      translate([0, 0, -od/2]) {
 17-        cylinder(h=od, d=d);
 18-      }
 19-    }
 20-  }
 21-}
 22-
 23-
 24-// Something like David Daye's Penny Chanter,
 25-// based on my measurements and undercut hints on David's web site.
 26-// This is symmetrical, so both pieces can be printed at the same time,
 27-// with color changes
 28-module chanter() {
 29-  difference () {
 30-    union() {
 31-      // The core part of the instrument is this brass tube
 32-      difference() {
 33-        brass() cylinder(h=height, d=od);
 34-
 35-        // Seam guides
 36-        translate([0, od/2, 0]) cylinder(d=1, h=400);
 37-      }
 38-
 39-      // David adds this outer Derlin tube as an upgrade option
 40-      difference() {
 41-        derlin() translate([0, 0, 40.0]) cylinder(h=290, d=od_derlin);
 42-
 43-        // The slits up the sides serve three purposes:
 44-        // 1. directs the slicer to place seams in it (and not on the face)
 45-        // 2. provides alignment guides for attaching the two pieces
 46-        // 3. looks like an intentional stylistic thing
 47-        rotate([0, 0, 85]) translate([0, od_derlin/2, 0]) cylinder(d=1, h=cut_height+20); // overlap
 48-        rotate([0, 0, -85]) translate([0, od_derlin/2, cut_height-20]) cylinder(d=1, h=400);
 49-      }
 50-
 51-      // These little doodads are probably just to hide the Derlin seam
 52-      ivory() translate([0, 0, 30.0]) cylinder(h=12, d=22.0);
 53-      ivory() translate([0, 0, height - 30.0 - 12]) cylinder(h=12, d=22.0);
 54-    }
 55-
 56-    // Seam guides
 57-    translate([0, 11, 0]) cylinder(d=1, h=400);
 58-
 59-    // Inner bore, which runs up to the place where the reed drops in
 60-    translate([0, 0,   0]) cylinder(h=337.01, d1=id_bot, d2=id_top);
 61-    translate([0, 0, 337]) cylinder(h=23.1, d1=id_top, d2=7.1);
 62-
 63-    // I totally dig David's minimalist aesthetic
 64-    translate([0, 0, 3]) rings(d=16.0);
 65-
 66-    // Stamp my name on it
 67-    difference() {
 68-      translate([0, 0, 307]) {
 69-        rotate([90, 0, 180]) {
 70-          linear_extrude(50) {
 71-            translate([0, 5]) text("neale", font="Fontdiner Swanky", valign="bottom", size=3, halign="center");
 72-            translate([0, 0]) text("2024-2", font="Fontdiner Swanky", valign="bottom", size=3, halign="center");
 73-          }
 74-        }
 75-      }
 76-      cylinder(h=360, d=od-0.5);
 77-    }
 78-
 79-
 80-    // Tone Holes!
 81-    // XXX: Undercut angle should be taken into account here
 82-    tonehole(h=57.1, d=6.68); // E-
 83-    tonehole(h=87.0, d=4.25); // E
 84-    tonehole(h=118.0, d=8.33); // F#
 85-    tonehole(h=149.0, d=5.51, undercut=-15); // G
 86-    tonehole(h=184.5, d=7.75, undercut=15); // A
 87-    tonehole(h=184.5, d=7.75, undercut=-15); // A (wide undercut)
 88-    tonehole(h=219.0, d=6.72, undercut=15); // B
 89-    tonehole(h=250.0, d=5.50, undercut=30); // C
 90-    rotate([0, 0, 180]) tonehole(h=270.0, d=7.11, undercut=30); // D
 91-  }
 92-}
 93-
 94-module tenon(top=false, h=cut_height, od=od, depth=20, thickness=2) {
 95-  module cut() {
 96-        cylinder(h=cut_height+depth, d=od-thickness-clearance);
 97-        cylinder(h=cut_height, d=50);
 98-  }
 99-
100-  if (top) {
101-    difference() {
102-      children();
103-      cut();
104-    }
105-  } else {
106-    intersection() {
107-      children();
108-      cut();
109-    }
110-  }
111-}
112-
113-chanter();
114-//translate([0, 50, 360]) rotate([180, 0, 0]) chanter();
115-
M daye/chanter/reed.scad
+16, -15
 1@@ -1,5 +1,7 @@
 2 include <../common.scad>
 3 
 4+$fn = 180;
 5+
 6 // Evertjan 't Hart's guide was super helpful:
 7 // https://www.hartdd.com/reedmaking/reed1.html
 8 //
 9@@ -7,13 +9,12 @@ include <../common.scad>
10 // the width comes out to 13.2mm,
11 // which is what the page says it should be.
12 
13+printing = true; // If false, sand the inside to be circular. FDM 3d printers can't do this, so you have to sand it afterwards.
14 length = 50;
15 thickness = 0.55;
16 cane_d = 24;
17 base_thickness = 2;
18 
19-scrape_angle = atan((base_thickness-thickness)/length)*2.6;
20-
21 difference() {
22   translate([0, 0, -cane_d/2+base_thickness]) {
23     difference() {
24@@ -27,23 +28,23 @@ difference() {
25 
26   // Cut the tails
27   // I totally guessed at all of these
28-  #translate([0, 10, 0]) rotate([0, 0, -30]) cube(20);
29+  for (m=[0:1]) {
30+    mirror([m, 0, 0]) {
31+      a=60; // I just eyeballed this
32+      translate([a+1, 0, -1]) cylinder(r=a, h=10);
33+    }
34+  }
35   
36 
37   // Sand inside to 1.5mm thickness
38-  sander_d = 82;
39-  translate([0, 0, base_thickness - 1.5 - sander_d/2]) rotate([-90, 0, 0]) cylinder(d=sander_d, h=length);
40+  if (!printing) {
41+    sander_d = 82;
42+    translate([0, -0.5, base_thickness - 1.5 - sander_d/2]) rotate([-90, 0, 0]) cylinder(d=sander_d, h=length+1);
43+  }
44 
45   // Scrape reed
46-  translate([0, length, d/2-base_thickness+thickness]) rotate([-scrape_angle, 0, 0]) translate([-d/2, -length, 0]) cube([d, length, d]);
47-
48-  // Reed chopper
49-  translate([0, length, 0]) {
50-    translate([0, -d/2, 0]) {
51-      difference() {
52-        translate([-d/2, 0, 0]) cube([d, d/2, d]);
53-        cylinder(d=d, h=d);
54-      }
55-    }
56+  scrape_angle = 3.5;
57+  for (m=[-5,0,5]) {
58+    rotate([0, m, 0]) translate([-cane_d/2, 30, base_thickness]) rotate([-scrape_angle, 0, 0]) cube([cane_d, length, cane_d]);
59   }
60 }
M daye/chanter/top.scad
+1, -1
1@@ -1,4 +1,4 @@
2-use <./chanter.scad>
3+use <./complete.scad>
4 
5 tenon(top=true) {
6   chanter();
M daye/common.scad
+2, -2
 1@@ -1,8 +1,8 @@
 2 // Make circles circular in final renders.
 3-$fn = $preview ? 0 : 60;
 4+$fn = $preview ? 0 : 180;
 5 
 6 // clearance in a permanent tenon/mortise joint
 7-clearance = 0.03;
 8+clearance = 0.04;
 9 
10 module brass() {
11   color("gold") children();
M daye/drones/baritone/reed-body.scad
+4, -12
 1@@ -1,6 +1,6 @@
 2 include<../../common.scad>
 3 
 4-id = 7.12;
 5+id = 6;
 6 od = 8;
 7 pluglen = 5;  // Length of the plug at the end
 8 opening = [2, 10, 6]; // Opening size
 9@@ -9,23 +9,15 @@ cutaway = [10, 0.74, 28]; // Tongue cutaway
10 module reed_body() {
11   difference() {
12     // The main piece
13-    cylinder(h=100, d=od);
14+    cylinder(h=100, d=od, $fn=6);
15 
16     // Inner bore
17     translate([0, 0, pluglen]) {
18-      difference() {
19-        cylinder(h=100, d=id);
20-
21-        // Leave material for a platform on the tongue cutaway
22-        translate([-5, id/2 - cutaway[1], 0]) cube(cutaway);
23-      }
24+      cylinder(h=100, d=id, $fn=6);
25     }
26 
27-    // Tongue cutaway
28-    translate([-5, od/2 - cutaway[1], 0]) cube(cutaway);
29-
30     // Opening
31-    translate([-opening[0]/2+.6, 0, pluglen]) cube(opening);
32+    translate([-opening[0]/2, 0, pluglen]) cube(opening);
33   }
34 }
35 
D daye/drones/baritone/reed.scad
+0, -36
 1@@ -1,36 +0,0 @@
 2-include <../../common.scad>
 3-
 4-// 9mm od
 5-// 7.5mm from plane on reed holder to back
 6-// 9 - 7.5 = 2.5 thickness; 4.5-2.5=2 cutaway from center
 7-
 8-length = 45;
 9-thickness = 0.55;
10-d = 9;
11-base_thickness = 1.5;
12-
13-scrape_angle = atan((base_thickness-thickness)/length)*2.6;
14-
15-translate([0, 0, -d/2+base_thickness])
16-difference() {
17-  rotate([-88, 0, 0]) cylinder(d=d, h=length);
18-
19-  // Chop off excess cylinder at the base
20-  translate([-d/2, -d, 0]) cube(d);
21-
22-  // Shave off reed
23-  translate([-d/2, -length, -d/2-base_thickness]) cube([d, length*3, d]);
24-
25-  // Scrape reed
26-  translate([0, length, d/2-base_thickness+thickness]) rotate([-scrape_angle, 0, 0]) translate([-d/2, -length, 0]) cube([d, length, d]);
27-
28-  // Reed chopper
29-  translate([0, length, 0]) {
30-    translate([0, -d/2, 0]) {
31-      difference() {
32-        translate([-d/2, 0, 0]) cube([d, d/2, d]);
33-        cylinder(d=d, h=d);
34-      }
35-    }
36-  }
37-}
M pickett-d-quiet/chanter.scad
+5, -3
 1@@ -77,10 +77,12 @@ module chanter() {
 2 }
 3 
 4 joint = 160; // Where to split it in half for printing
 5-module tenon(top=false, h=joint, od=od-5, depth=20, thickness=2, clearance=0.12) {
 6+module tenon(top=false, h=joint, od=od-5, depth=20, thickness=2, clearance=0.2) {
 7   module cut() {
 8-        cylinder(h=h+depth, d=od-thickness+clearance);
 9-        cylinder(h=h, d=50);
10+    d = od-thickness+clearance;
11+    cylinder(h=h+depth, d=d);
12+    cylinder(h=h, d=d+20);
13+    translate([0, 0, h+depth]) cylinder(h=d/2, d1=d, d2=0);
14   }
15 
16   if (top) {
M pickett-d-quiet/sigil.scad
+4, -3
 1@@ -1,13 +1,14 @@
 2 use <MCAD/regular_shapes.scad>
 3 
 4-module sigil(d, stamp) {
 5+module sigil(d, stamp, rot=0) {
 6   // Sigil
 7   translate([0, 0, 4]) intersection() {
 8     cylinder_tube(50, d/2+0.5, 1);
 9     union() {
10-      rotate([90, 90, -90]) {
11+      rotate([90, 0, -90]) {
12         linear_extrude(height=d, convexity=4) {
13-          translate([-8, -5]) import("ruby.svg");
14+          translate([-4, 0]) import("ruby.svg");
15+          // XXX: when this is in openscad prod, add center to import and remove translate
16         }
17       }
18       rotate([90, 90, -160]) {
M pickett-d/Makefile
+1, -1
1@@ -1,6 +1,6 @@
2 rev=$(shell git log -1 --pretty='format:%cd' --date='format:%Y-%m-%d')
3 
4-all: top.3mf bottom.3mf
5+all: chanter.3mf split.3mf
6 clean:
7 	rm -f *.3mf
8 
D pickett-d/bottom.scad
+0, -5
1@@ -1,5 +0,0 @@
2-use <./chanter.scad>
3-
4-split(top=false) {
5-  chanter();
6-}
M pickett-d/chanter.scad
+97, -108
  1@@ -1,88 +1,66 @@
  2 // Based on O'Flynn Rowsome Chanter Measurements
  3 // http://pipers.ie/source/media/?mediaId=31307&galleryId=1353
  4 
  5-use <./tenon.scad>
  6+use <./sigil.scad>
  7 
  8-$fn =60;
  9+rev = "preview";
 10+stamp = str(rev);
 11+
 12+$fn =120;
 13 
 14 // Diameter of screw hole
 15 Screwhole = 4; // [1:10]
 16 
 17 module metal() {
 18-    color("silver") children();
 19+  color("silver") children();
 20 }
 21 
 22 module leather() {
 23-    color("sienna") children();
 24+  color("sienna") children();
 25 }
 26 
 27 module ivory() {
 28-    color("wheat") children();
 29+  color("wheat") children();
 30 }
 31 
 32 module wood() {
 33-    color("saddlebrown") children();
 34+  color("saddlebrown") children();
 35 }
 36 
 37-// A shape like a hamburger patty
 38-module patty(h, d) {
 39-    intersection() {
 40-        cylinder(h=h, d=d);
 41-        translate([0, 0, h/2]) {
 42-            resize([d, d, h*3]) {
 43-                sphere(d=d);
 44-            }
 45-        }
 46-    }
 47-}    
 48-
 49-// A cylinder with something like a compression fitting around it
 50+// A compression fitting, basically.
 51 module ringyding(h, d) {
 52-  ivory() resize([d, d, h]) sphere(d=d);
 53+  color("goldenrod") resize([d, d, h]) sphere(d=d);
 54 }
 55 
 56 // A fillet is a sort of trumpet bell shape
 57 module fillet(h, d1, d2) {
 58-  r = abs(d1-d2)/2;
 59-  render(convexity=4) {
 60-    resize([d1, d1, h]) {
 61-      rotate_extrude() {
 62-        translate([d2/2, 0, 0]) {
 63-          difference() {
 64-            square([r, r]);
 65-            translate([r, r]) circle(r=r);
 66-          }
 67-        }
 68-      }
 69+  rmin = min(d1, d2)/2;
 70+  rmax = max(d1, d2)/2;
 71+  r = rmax-rmin;
 72+  rotate_extrude(convexity=4) {
 73+    difference() {
 74+      square([rmax, h]);
 75+      translate([rmax, d1>d2?h:0]) resize([r*2, h*2]) circle();
 76     }
 77   }
 78 }
 79 
 80-// An upside-down fillet
 81-module tellif(h, d2, d1) {
 82-    translate([0, 0, h]) mirror([0, 0, 1]) fillet(h, d1, d2);
 83-}
 84-
 85-// Absolutely nothing: helps make the code look better
 86-module nothing(h) {
 87-}
 88-
 89 // Just a rotated cylinder
 90 // h: height of the *top* of the protrusion
 91 // d: height of the protrusion (diameter?)
 92 // protrusion: amount of protrusion
 93 module bumpout(h, d, protrusion) {
 94-    intersection() {
 95-        translate([0, -protrusion, h-d]) {
 96-            cylinder(h=d, d=20.4);
 97-        }
 98-        translate([0, -protrusion, h-d/2]) {
 99-            sphere(d=protrusion*4);
100-        }
101-        translate([0, 0, h-d]) {
102-            cylinder(h=d, d1=19, d2=50);
103-        }
104+  intersection() {
105+    translate([0, -protrusion, h-d]) {
106+      cylinder(h=d, d=20.4);
107     }
108+    translate([0, -protrusion, h-d/2]) {
109+      sphere(d=protrusion*4);
110+    }
111+    translate([0, 0, h-d]) {
112+      cylinder(h=d, d1=19, d2=50);
113+    }
114+  }
115 }
116 
117 
118@@ -103,73 +81,84 @@ module tonehole(h, td, ld, ch, undercut=1) {
119 }
120 
121 module chanter() {
122-    difference() {
123-        union() {
124-            translate([0, 0,  0]) metal() cylinder(h=22.0, d=17.1);
125-            translate([0, 0, 22]) wood() cylinder(h=23.5, d=17.1);  // Rings go around this
126+  // We start by building everything up in a union(),
127+  // then we ream it with difference().
128+  difference() {
129+    union() {
130+      // Inner metal tube
131+      metal() cylinder(h=331.2, d=17);
132             
133-            // Decorative stuff on the bottom
134-            translate([0, 0, 32]) {          
135-                translate([0, 0, 1.7]) ringyding(h=8, d=28);
136-                translate([0, 0, 8.2]) ringyding(h=5, d=22);
137-            }
138-
139-            // A taper on that bottom ring so it will print nicely
140-            translate([0, 0, 12]) wood() tellif(h=20, d1=25.5, d2=100);
141+      // Wood body
142+      translate([0, 0, 32.5]) wood() cylinder(h=258, d1=20.4, d2=18);
143             
144-            // Main body
145-            translate([0, 0, 32.5]) wood() cylinder(h=258, d1=20.4, d2=18);
146+      // Bottom wood transition
147+      translate([0, 0, 33.7]) ringyding(h=8, d=23);
148+      translate([0, 0, 25.6]) ivory() fillet(h=7, d1=18, d2=22); // eliminate overhang
149+      translate([0, 0, 25.6]) ringyding(h=4.3, d=19);
150             
151-            // Top decoration
152-          translate([0, 0, 290.4]) {
153-                color("silver") cylinder(h=40.8, d=17);
154-                
155-                translate([0, 0,  0.0]) ringyding(h=5.5, d=20);
156-                translate([0, 0,  5.5]) nothing(h=9.7); // metal
157-                translate([0, 0, 15.2]) ringyding(h=4.3, d=19);
158-                translate([0, 0, 19.5]) nothing(h=6.7); // metal
159-                translate([0, 0, 27.2]) ringyding(h=5.5, d=20.2);
160-                translate([0, 0, 28.2]) leather() {
161-                  // XXX: kludge
162-                  tellif(h=8, d2=19, d1=23);
163-                  cylinder(h=8, d=19);
164-                }
165-                translate([0, 0, 37.9]) ringyding(h=8, d=25.4);
166-            }
167+      // Top wood transition
168+      translate([0, 0, 290.4]) ringyding(h=5.5, d=20);
169+      translate([0, 0, 305.6]) ringyding(h=4.3, d=19);
170+      translate([0, 0, 317.6]) ringyding(h=5.5, d=20.2);
171+      translate([0, 0, 318.6]) ivory() fillet(h=8.4, d1=17, d2=24); // eliminate overhang
172+      translate([0, 0, 328.3]) ringyding(h=8, d=25.4);
173             
174-            // This protects the reed and provides a place for tubing to connect
175-            translate([0, 0, 324.5]) metal() cylinder(h=32.7, d=14.8);
176+      // This protects the reed and provides a place for tubing to connect
177+      translate([0, 0, 324.5]) metal() cylinder(h=32.7, d=14.8);
178             
179-            // Bumpouts
180-            // These angles are my best guess based on photos
181-            rotate(220) wood() bumpout(161.2, 14.8, 6); // protrusion guessed
182-        }
183-
184-        // Inner bore
185-        union() {
186-            translate([0, 0, -0.01]) { // Go just a bit past the ends
187-                translate([0, 0,   0]) cylinder(h=337.01, d1=13.2, d2=5.51);
188-                translate([0, 0, 337]) cylinder(h=21, d1=5.51, d2=7.1);
189-            }
190-        }
191-
192-        // Tone Holes!
193-        translate([0, 0, 5]) { // This offset is specified nowhere. I'm guessing to make it fit the bumpouts.
194-          rotate(180) tonehole(263, 6.04, 7.95, 10.1, 1.2); // back D
195-          rotate(0) tonehole(246.4, 6.42, 6.57, 11.3); // C♯
196-          rotate(0) tonehole(216.2, 6.89, 6.96, 11.3); // B
197-          rotate(0) tonehole(182, 8.85, 9.06, 11.4); // A
198-          rotate(0) tonehole(147.4, 6.98, 7.44, 12.2); //  G
199-          rotate(0) tonehole(116.2, 8.39, 8.88, 12.7); // F♯
200-          rotate(0) tonehole(84.7, 5.25, 5.49, 14); // E
201-          rotate(0) tonehole(53.3, 6.94, 7.16, 14.1); // E♭
202-        }
203+      // Bumpouts
204+      // These angles are my best guess based on photos
205+      rotate(220) wood() bumpout(161.2, 14.8, 6); // protrusion guessed
206+    }
207+
208+    // Inner bore
209+    union() {
210+      translate([0, 0, -0.01]) { // Go just a bit past the ends
211+        translate([0, 0,   0]) cylinder(h=337.01, d1=13.2, d2=5.51);
212+        translate([0, 0, 337]) cylinder(h=21, d1=5.51, d2=7.1);
213+      }
214     }
215+
216+    // Tone Holes!
217+    translate([0, 0, 5]) { // Magic offset from published measurements
218+      rotate(180) tonehole(263, 6.04, 7.95, 10.1, 1.2); // back D
219+      rotate(0) tonehole(246.4, 6.42, 6.57, 11.3); // C♯
220+      rotate(0) tonehole(216.2, 6.89, 6.96, 11.3); // B
221+      rotate(0) tonehole(182, 8.85, 9.06, 11.4); // A
222+      rotate(0) tonehole(147.4, 6.98, 7.44, 12.2); //  G
223+      rotate(0) tonehole(116.2, 8.39, 8.88, 12.7); // F♯
224+      rotate(0) tonehole(84.7, 5.25, 5.49, 14); // E
225+      rotate(0) tonehole(53.3, 6.94, 7.16, 14.1); // E♭
226+    }
227+
228+    sigil(17.1, stamp);
229+  }
230 }
231 
232 module split(top=false) {
233-  tenon(top=top, h=162, d=15, depth=15) {
234-    children();
235+  h=162; // Where to make the cut
236+  d=14; // Diameter of the tenon
237+  depth=15; // Insertion depth of the tenon
238+  clearance=0.12; // Gap between tenon and mortise
239+  
240+  module cut(id) {
241+    translate([0, 0, h+depth]) cylinder(h=id/2, d1=id, d2=0);
242+    cylinder(h=h+depth, d=id);
243+    cylinder(h=h, d=id+40);
244+  }
245+
246+  if (top) {
247+    translate([0, 0, -h]) {
248+      difference() {
249+        chanter();
250+        cut(d+clearance);
251+      }
252+    }
253+  } else {
254+    intersection() {
255+      chanter();
256+      cut(d);
257+    }
258   }
259 }
260 
A pickett-d/split.scad
+4, -0
1@@ -0,0 +1,4 @@
2+use <./chanter.scad>
3+
4+translate([-20, 0, 0]) split(true);
5+translate([20, 0, 0]) split(false);
D pickett-d/tenon.scad
+0, -24
 1@@ -1,24 +0,0 @@
 2-use <BOSL/math.scad>
 3-
 4-module tenon(top=false, h=100, d=5, depth=20, thickness=2, clearance=0.2) {
 5-  module cut() {
 6-    id = d-thickness+clearance;
 7-    translate([0, 0, h+depth]) cylinder(h=id/2, d1=id, d2=0);
 8-    cylinder(h=h+depth, d=id);
 9-    cylinder(h=h, d=id+40);
10-  }
11-
12-  if (top) {
13-    difference() {
14-      children();
15-      cut();
16-    }
17-  } else {
18-    intersection() {
19-      children();
20-      cut();
21-    }
22-  }
23-}
24-
25-chanter();
D pickett-d/top.scad
+0, -6
1@@ -1,6 +0,0 @@
2-use <./chanter.scad>
3-use <./tenon.scad>
4-
5-split(top=true) {
6-  chanter();
7-}