Compare commits
18 Commits
9e771b3125
...
d1055841fa
| Author | SHA1 | Date | |
|---|---|---|---|
| d1055841fa | |||
| 950cf6a2fd | |||
| 4e3dba66ec | |||
| 70ef92b45c | |||
| 510ccffa0d | |||
| 537e61d97b | |||
| 00b3272abe | |||
| 22a2b276f5 | |||
| 330998483a | |||
| be16bda8ee | |||
| 77daf344b7 | |||
| 0a44ab7907 | |||
| 58f789e1b9 | |||
| 09c532b234 | |||
| b71f1d2295 | |||
| 78bd6b9738 | |||
| 49ac2aa5f1 | |||
| aa7725adef |
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "lib/threads"]
|
||||||
|
path = lib/threads
|
||||||
|
url = git@github.com:rcolyer/threads-scad.git
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,637 @@
|
|||||||
|
include <../lib/chamfered-cube.scad>
|
||||||
|
include <../lib/rounded-cube.scad>
|
||||||
|
|
||||||
|
// All units in mm
|
||||||
|
$fn=128;
|
||||||
|
outerWall=4;
|
||||||
|
innerWall=2;
|
||||||
|
layerClearance = 0.5;
|
||||||
|
verStr="v12";
|
||||||
|
font="Montserrat";
|
||||||
|
ep = 0.01; // smallest unit to ensure overlap between shapes
|
||||||
|
|
||||||
|
// as a convention, outer dimensions refer to measurements from outside wall to
|
||||||
|
// outside wall, as if you put a caliper around the whole thing. Inner
|
||||||
|
// dimesions refers to inside or void dimensions: the space available to be
|
||||||
|
// filled.
|
||||||
|
layer1H = 44;
|
||||||
|
layer2H = 40;
|
||||||
|
|
||||||
|
outerBoxLength = 300;
|
||||||
|
outerBoxWidth = 154;
|
||||||
|
outerBoxHeight = layer1H + layer2H + 2*outerWall;
|
||||||
|
|
||||||
|
innerBoxLength = outerBoxLength - 2*outerWall;
|
||||||
|
innerBoxWidth = outerBoxWidth - 2*outerWall;
|
||||||
|
|
||||||
|
audioTraySide = 64;
|
||||||
|
audioTrayHeight = 15;
|
||||||
|
audioTrayIS = audioTraySide - 2*innerWall;
|
||||||
|
audioTrayIH = audioTrayHeight - innerWall;
|
||||||
|
|
||||||
|
|
||||||
|
module shellBottom(dims) {
|
||||||
|
lipClearance = innerWall + 0.2;
|
||||||
|
bottomShellH = dims[2]*0.75;
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
// main body
|
||||||
|
chamferedCube(dims,
|
||||||
|
chamfer=4);
|
||||||
|
|
||||||
|
// top-cut (75% up)
|
||||||
|
translate([-outerWall, -outerWall, bottomShellH])
|
||||||
|
cube([dims[0] + 2*outerWall, dims[1] + 2*outerWall, dims[2]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add lip to mate with top
|
||||||
|
translate([lipClearance, lipClearance, bottomShellH - 2])
|
||||||
|
chamferedCube(
|
||||||
|
[dims[0] - 2*lipClearance, dims[1] - 2*lipClearance, 6 - 1],
|
||||||
|
chamfer=1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// carve out the interior
|
||||||
|
translate([outerWall, outerWall, outerWall])
|
||||||
|
cube([dims[0] - 2*outerWall, dims[1] - 2*outerWall, dims[2]]);
|
||||||
|
|
||||||
|
// carve out a 0.6mm sliver for the fabric to sit in
|
||||||
|
/*
|
||||||
|
fabricClearance = 0.6;
|
||||||
|
translate([
|
||||||
|
lipClearance - fabricClearance,
|
||||||
|
lipClearance - fabricClearance,
|
||||||
|
bottomShellH - 4])
|
||||||
|
difference() {
|
||||||
|
roundedCube(
|
||||||
|
[ dims[0] - 2*lipClearance + 2*fabricClearance,
|
||||||
|
dims[1] - 2*lipClearance + 2*fabricClearance,
|
||||||
|
7],
|
||||||
|
[2, 2, 0]);
|
||||||
|
|
||||||
|
translate([fabricClearance, fabricClearance, -ep])
|
||||||
|
roundedCube(
|
||||||
|
[dims[0] - 2*lipClearance, dims[1] - 2*lipClearance, 8],
|
||||||
|
[2, 2, 0]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ropeway
|
||||||
|
for (i = [1, 3]) {
|
||||||
|
for (j = [-1, 1]) {
|
||||||
|
/* Older, diagonal cut
|
||||||
|
translate([dims[0]/2 - j*dims[0]/2 + j*1.5, i*dims[1]/4, -1])
|
||||||
|
rotate([0, 0, 45 + 90*j])
|
||||||
|
cube([4, 4, bottomShellH + 8]);
|
||||||
|
*/
|
||||||
|
translate([dims[0]/2 - j*dims[0]/2 - 1.5, i*dims[1]/4 - 2.5, -1])
|
||||||
|
chamferedCube([3, 5, bottomShellH + 8], chamfer=1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Older, diagonal cut
|
||||||
|
translate([-1, i*dims[1]/4, 1.5])
|
||||||
|
rotate([-135, 0, 0])
|
||||||
|
cube([dims[0] + 8, 4, 4]);
|
||||||
|
*/
|
||||||
|
translate([-1, i*dims[1]/4 - 2.5, -1.5])
|
||||||
|
chamferedCube([dims[0] + 8, 5, 3], chamfer=1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// version marker
|
||||||
|
color("black")
|
||||||
|
translate([0.6, 26, 8]) rotate([90, 0,-90])
|
||||||
|
linear_extrude(0.61) text(text = verStr, font = font, size = 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module shellTop(dims) {
|
||||||
|
topShellH = dims[2]*0.25;
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
// main body
|
||||||
|
chamferedCube(dims,
|
||||||
|
chamfer=4);
|
||||||
|
|
||||||
|
// top-cut (75% up)
|
||||||
|
translate([-outerWall, -outerWall, topShellH + 4])
|
||||||
|
cube([dims[0] + 2*outerWall, dims[1] + 2*outerWall, dims[2]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// carve out the interior
|
||||||
|
translate([outerWall, outerWall, outerWall])
|
||||||
|
cube([dims[0] - 2*outerWall, dims[1] - 2*outerWall, dims[2]]);
|
||||||
|
|
||||||
|
// carve out the interior of the lip
|
||||||
|
translate([innerWall - 0.2, innerWall - 0.2, topShellH])
|
||||||
|
chamferedCube(
|
||||||
|
[dims[0] - 2*innerWall + 0.4, dims[1] - 2*innerWall + 0.4, dims[2]],
|
||||||
|
chamfer = 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// carve out a 0.6mm sliver for the fabric to sit in
|
||||||
|
fabricClearance = 0.6;
|
||||||
|
translate([
|
||||||
|
layerClearance,
|
||||||
|
layerClearance,
|
||||||
|
topShellH - 4])
|
||||||
|
difference() {
|
||||||
|
roundedCube(
|
||||||
|
[ dims[0] - 2*layerClearance,
|
||||||
|
dims[1] - 2*layerClearance,
|
||||||
|
7],
|
||||||
|
[2, 2, 0]);
|
||||||
|
|
||||||
|
translate([fabricClearance, fabricClearance, -ep])
|
||||||
|
roundedCube(
|
||||||
|
[ dims[0] - 2*layerClearance - 2*fabricClearance,
|
||||||
|
dims[1] - 2*layerClearance - 2*fabricClearance,
|
||||||
|
8],
|
||||||
|
[2, 2, 0]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ropeway
|
||||||
|
for (i = [1, 3]) {
|
||||||
|
for (j = [-1, 1]) {
|
||||||
|
/* Older, diagonal cut
|
||||||
|
translate([dims[0]/2 - j*dims[0]/2 + j*1.5, i*dims[1]/4, -1])
|
||||||
|
rotate([0, 0, 45 + 90*j])
|
||||||
|
cube([4, 4, topShellH + 8]);
|
||||||
|
*/
|
||||||
|
translate([dims[0]/2 - j*dims[0]/2 - 1.5, i*dims[1]/4 - 2.5, -1])
|
||||||
|
chamferedCube([3, 5, topShellH + 8], chamfer=1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Older, diagonal cut
|
||||||
|
translate([-1, i*dims[1]/4, 1.5])
|
||||||
|
rotate([-135, 0, 0])
|
||||||
|
cube([dims[0] + 8, 4, 4]);
|
||||||
|
*/
|
||||||
|
translate([-1, i*dims[1]/4 - 2.5, -1.5])
|
||||||
|
chamferedCube([dims[0] + 8, 5, 3], chamfer=1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// version marker
|
||||||
|
color("black")
|
||||||
|
translate([0.6, 26, 8]) rotate([90, 0,-90])
|
||||||
|
linear_extrude(0.61) text(text = verStr, font = font, size = 8);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -45 = x + -y
|
||||||
|
* x = y - 45
|
||||||
|
*
|
||||||
|
* 135 = x + y
|
||||||
|
* y = 135 - x
|
||||||
|
* y = 135 - (y - 45)
|
||||||
|
* y = 180 - y
|
||||||
|
* y = 90
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// tray indent location
|
||||||
|
// X: innerWall + iW/2 - audioTraySide/2
|
||||||
|
// 2 + (innerBoxWidth - 2*layerClearance - 2*innerWall)/2 - 64/2
|
||||||
|
// 2 + ((outerBoxWidth - 2*outerWall) - 2*0.5 - 2*2)/2 - 32
|
||||||
|
// 2 + (154 - 8 - 1 - 4)/2 - 32
|
||||||
|
// 40.5
|
||||||
|
//
|
||||||
|
// Y: innerWall + iL - audioTraySide/2 - cableDia/2 - innerWall
|
||||||
|
// 2 + (innerBoxLength - 2*layerClearance - 2*innerWall) - 64/2 - 130/2 - 2
|
||||||
|
// 2 + (outerBoxLength - 2*outerWall) - 2*0.5 - 2*2 - 32 - 65 - 2
|
||||||
|
// 300 - 8 - 1 - 4 - 32 - 65
|
||||||
|
// 190
|
||||||
|
//
|
||||||
|
translate([
|
||||||
|
40.5 + outerWall + layerClearance,
|
||||||
|
190 + outerWall + layerClearance,
|
||||||
|
1])
|
||||||
|
//(dims[0] - audioTraySide)/2,
|
||||||
|
//dims[1] - outerWall - innerWall - audioTraySide/2 - 130/2,
|
||||||
|
//1])
|
||||||
|
roundedCube(
|
||||||
|
[ audioTraySide - 2*(innerWall + layerClearance),
|
||||||
|
audioTraySide - 2*(innerWall + layerClearance),
|
||||||
|
4],
|
||||||
|
[1, 1, 1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module layer1() {
|
||||||
|
oH = layer1H;
|
||||||
|
oL = innerBoxLength - 2*layerClearance; // outer length
|
||||||
|
oW = innerBoxWidth - 2*layerClearance; // outer width
|
||||||
|
iL = oL - 2*innerWall; // inner length
|
||||||
|
iW = oW - 2*innerWall; // inner width
|
||||||
|
iH = oH - innerWall; // inner height
|
||||||
|
|
||||||
|
handleDia = 42;
|
||||||
|
cableDia = 130;
|
||||||
|
translate([innerWall, innerWall, innerWall])
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
// main shell
|
||||||
|
translate([-innerWall, -innerWall, -innerWall])
|
||||||
|
roundedCube([oW, oL, oH], [1, 1, 1]);
|
||||||
|
|
||||||
|
translate([0, 169, 0])
|
||||||
|
mirror([0, 1, 0])
|
||||||
|
union() {
|
||||||
|
// screwdriver handle
|
||||||
|
translate([handleDia / 2, handleDia / 2, handleDia / 2])
|
||||||
|
sphere(d=handleDia);
|
||||||
|
|
||||||
|
translate([handleDia / 2, handleDia / 2, handleDia / 2])
|
||||||
|
cylinder(d=handleDia, h = handleDia / 2 + innerWall);
|
||||||
|
|
||||||
|
translate([handleDia / 2, handleDia / 2 + 3, handleDia / 2])
|
||||||
|
sphere(d=handleDia);
|
||||||
|
|
||||||
|
translate([handleDia / 2, handleDia / 2 + 3, handleDia / 2])
|
||||||
|
cylinder(d=handleDia, h = handleDia / 2 + innerWall);
|
||||||
|
|
||||||
|
translate([(handleDia - 32) / 2, handleDia / 2, 7]) cube([32, 103 - handleDia/2, oH]);
|
||||||
|
|
||||||
|
// screw bits
|
||||||
|
bitL = 112;
|
||||||
|
bitW = 22;
|
||||||
|
// plain cube version (we're going to oversize and chamfer to get
|
||||||
|
// diagonal edges)
|
||||||
|
// translate([(handleDia - bitW) / 2, handleDia / 2, 0]) cube([bitW, bitL + handleDia/2, oH]);
|
||||||
|
translate([(handleDia - bitW) / 2 - 5, handleDia / 2 - 5, -ep])
|
||||||
|
chamferedCube([bitW + 10, bitL + handleDia/2 + 10, 16], chamfer=5);
|
||||||
|
|
||||||
|
// power block cutout
|
||||||
|
translate([(handleDia - 32) / 2 - 4, handleDia / 2 + 80, 7]) cube([40, 68, oH]);
|
||||||
|
|
||||||
|
// fingerway cut-outs
|
||||||
|
translate([handleDia*0.6, 55, 0]) cube([24, 36, oH]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower-right cubby
|
||||||
|
translate([handleDia + 2*innerWall, 0, 0])
|
||||||
|
cube([iW - handleDia - 3*innerWall, 150, oH]);
|
||||||
|
|
||||||
|
// cable cut-out
|
||||||
|
translate([iW/2, iL - cableDia/2 - innerWall, 0])
|
||||||
|
cylinder(d=cableDia, h=oH);
|
||||||
|
|
||||||
|
// upper-left bits
|
||||||
|
union() {
|
||||||
|
// PortaPow
|
||||||
|
translate([6.5, 249.5, 22])
|
||||||
|
rotate([0, 0, 45])
|
||||||
|
cube([44.5, 10.5, oH]);
|
||||||
|
|
||||||
|
// USB thumbdrive
|
||||||
|
translate([5, 272, 1])
|
||||||
|
rotate([0, 0, 45])
|
||||||
|
cube([13, 5, oH]);
|
||||||
|
|
||||||
|
// fingerway
|
||||||
|
translate([16, 271, iH + 15])
|
||||||
|
sphere(d=46);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SD-card adapter + SIM removal tool
|
||||||
|
union() {
|
||||||
|
translate([iW - 27, 278, 9.5])
|
||||||
|
rotate([0, 0, -45])
|
||||||
|
cube([25, 2.5, 33]);
|
||||||
|
|
||||||
|
translate([iW - 8, 280, 4.5])
|
||||||
|
rotate([0, 0, -135])
|
||||||
|
cube([8.75, 1.5, 38]);
|
||||||
|
|
||||||
|
// fingerway
|
||||||
|
translate([iW - 16, 271, iH + 15])
|
||||||
|
sphere(d=46);
|
||||||
|
}
|
||||||
|
|
||||||
|
// version marker
|
||||||
|
color("black")
|
||||||
|
translate([-innerWall + 0.6, 26, 4]) rotate([90, 0,-90])
|
||||||
|
linear_extrude(0.61) text(text = verStr, font = font, size = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([handleDia*0.988, 77.5, -0.1])
|
||||||
|
cylinder(d=9, oH - innerWall + 0.1);
|
||||||
|
|
||||||
|
translate([handleDia*0.988, 114.5, -0.1])
|
||||||
|
cylinder(d=9, oH - innerWall + 0.1);
|
||||||
|
|
||||||
|
translate([iW/2 - audioTraySide/2, iL - audioTraySide/2 - cableDia/2 - innerWall, 0])
|
||||||
|
difference() {
|
||||||
|
translate([0, 0, -0.1])
|
||||||
|
roundedCube([audioTraySide, audioTraySide, 1.1], [0.4, 0.4, 0.4]);
|
||||||
|
translate([innerWall, innerWall, 0])
|
||||||
|
cube([audioTraySide - 2*innerWall, audioTraySide - 2*innerWall, 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module layer2() {
|
||||||
|
oH = layer2H;
|
||||||
|
oL = innerBoxLength - 2*layerClearance; // outer length
|
||||||
|
oW = innerBoxWidth - 2*layerClearance; // outer width
|
||||||
|
iL = oL - 2*innerWall; // inner length
|
||||||
|
iW = oW - 2*innerWall; // inner width
|
||||||
|
iH = oH - innerWall; // inner height
|
||||||
|
|
||||||
|
union() {
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
roundedCube([oW, oL, oH], [1, 1, 1]);
|
||||||
|
|
||||||
|
translate([innerWall, innerWall, innerWall])
|
||||||
|
union() {
|
||||||
|
// HDD
|
||||||
|
translate([(iW - 131)/2, 0, 0])
|
||||||
|
cube([131, 83, oH]);
|
||||||
|
|
||||||
|
// Tekton tool kit
|
||||||
|
translate([2, 103 + innerWall, 0])
|
||||||
|
cube([105.5, 61, oH]);
|
||||||
|
|
||||||
|
// Slice knife
|
||||||
|
translate([114, 103 + innerWall, 0])
|
||||||
|
cube([22.5, 156, oH]);
|
||||||
|
|
||||||
|
// cables
|
||||||
|
translate([56, 226, 0])
|
||||||
|
cylinder(d=110, h=oH);
|
||||||
|
|
||||||
|
// fingerways
|
||||||
|
translate([30, 80, 0])
|
||||||
|
cube([36, 30, oH]);
|
||||||
|
|
||||||
|
translate([105, 130, 0])
|
||||||
|
cube([12, 36, oH]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// version marker
|
||||||
|
color("black")
|
||||||
|
translate([0.6, 26 + innerWall, 4]) rotate([90, 0,-90])
|
||||||
|
linear_extrude(0.61) text(text = verStr, font = font, size = 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([32, 96, 0]) scale([6, 22, 1]) cylinder(d=1, h=oH);
|
||||||
|
translate([68, 96, 0]) scale([6, 22, 1]) cylinder(d=1, h=oH);
|
||||||
|
translate([112.75, 132, 0]) scale([6.5, 6, 1]) cylinder(d=1, h=oH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module audioTrayBlank(s, h) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
translate([0, 0, 1])
|
||||||
|
roundedCube(
|
||||||
|
[s, s, h - 1],
|
||||||
|
[1, 1, 1]);
|
||||||
|
|
||||||
|
translate([innerWall + layerClearance, innerWall + layerClearance, 0])
|
||||||
|
roundedCube(
|
||||||
|
[ s - 2*(innerWall + layerClearance),
|
||||||
|
s - 2*(innerWall + layerClearance),
|
||||||
|
h - 1],
|
||||||
|
[1, 1, 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom edge chamfers
|
||||||
|
translate([-1, (innerWall + layerClearance), 1])
|
||||||
|
rotate([-30, 0, 0])
|
||||||
|
translate([0, -2*(innerWall + layerClearance), -4])
|
||||||
|
cube([audioTraySide+2, 2*(innerWall + layerClearance), 4]);
|
||||||
|
|
||||||
|
translate([-1, audioTraySide - (innerWall + layerClearance), 1])
|
||||||
|
rotate([30, 0, 0])
|
||||||
|
translate([0, 0, -4])
|
||||||
|
cube([audioTraySide+2, 2*(innerWall + layerClearance), 4]);
|
||||||
|
|
||||||
|
translate([(innerWall + layerClearance), -1, 1])
|
||||||
|
rotate([0, 30, 0])
|
||||||
|
translate([-2*(innerWall + layerClearance), 0, -4])
|
||||||
|
cube([2*(innerWall + layerClearance), audioTraySide+2, 4]);
|
||||||
|
|
||||||
|
translate([audioTraySide - (innerWall + layerClearance), -1, 1])
|
||||||
|
rotate([0, -30, 0])
|
||||||
|
translate([0, 0, -4])
|
||||||
|
cube([2*(innerWall + layerClearance), audioTraySide+2, 4]);
|
||||||
|
|
||||||
|
// top lip cutaway
|
||||||
|
translate([innerWall, innerWall, h - 1])
|
||||||
|
cube([audioTrayIS,audioTrayIS, 4]);
|
||||||
|
|
||||||
|
// version marker
|
||||||
|
translate([0.6, 30, 4]) rotate([90, 0,-90])
|
||||||
|
linear_extrude(0.61) text(text = verStr, font = font, size = 8);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module audioJackTray() {
|
||||||
|
difference() {
|
||||||
|
audioTrayBlank(s = audioTraySide, h = audioTrayHeight);
|
||||||
|
|
||||||
|
translate([2.5, innerWall, innerWall])
|
||||||
|
union() {
|
||||||
|
|
||||||
|
for (i = [0, 1]) {
|
||||||
|
translate([i*(11), i*60, 0])
|
||||||
|
mirror([0, i, 0])
|
||||||
|
union() {
|
||||||
|
translate([6.5, 0, 6])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=13, h=28);
|
||||||
|
translate([0, 0, 6]) cube([13, 28, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6.5, 27.5, 6])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=7, h=32.5);
|
||||||
|
translate([3, 27.5, 6]) cube([7, 32.5, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6.5, 48, 3.5])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=7, h=12);
|
||||||
|
translate([3, 48, 3.5]) cube([7, 12, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6.5, 53, 11])
|
||||||
|
sphere(d=14);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([22 + i*(10), i*60, 0])
|
||||||
|
mirror([0, i, 0])
|
||||||
|
translate([0, 6, 0])
|
||||||
|
union() {
|
||||||
|
translate([6, 0, 7])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=12, h=16);
|
||||||
|
translate([0, 0, 7]) cube([12, 16, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6, 15.5, 7])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=7, h=32.5);
|
||||||
|
translate([2.5, 15.5, 7]) cube([7, 32.5, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6, 36, 4])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=7, h=12);
|
||||||
|
translate([2.5, 36, 4]) cube([7, 12, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6, 43, 11])
|
||||||
|
sphere(d=13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([audioTrayIS - 14, 8, 0])
|
||||||
|
union() {
|
||||||
|
translate([6, 0, 6.5]) rotate([-90, 0, 0]) cylinder(d=12, h=40);
|
||||||
|
translate([0, 0, 6.5]) cube([12, 40, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6, 26, 5]) rotate([-90, 0, 0]) cylinder(d=12, h=14);
|
||||||
|
translate([0, 26, 5]) cube([12, 14, audioTrayIH]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show Cross-section
|
||||||
|
// translate([-2, -1, -1]) cube([audioTraySide + 4, 20, audioTrayHeight + 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module drumKeyTray() {
|
||||||
|
difference() {
|
||||||
|
audioTrayBlank(s = audioTraySide, h = audioTrayHeight);
|
||||||
|
|
||||||
|
translate([innerWall, innerWall, innerWall])
|
||||||
|
union() {
|
||||||
|
|
||||||
|
// drum-key
|
||||||
|
translate([audioTrayIS/2, 2*innerWall, 0])
|
||||||
|
union() {
|
||||||
|
translate([0, 0, 7.5])
|
||||||
|
rotate([-90, 0, 0]) cylinder(d=11, h=36);
|
||||||
|
translate([-5.5, 0, 7.5]) cube([11, 36, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([-51/2, 0, 7.5 - 3]) cube([51, 9, audioTrayIH]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
translate([audioTrayIS/2 - 6 + i*20, 16, 0])
|
||||||
|
union() {
|
||||||
|
translate([6, 0, 7]) rotate([-90, 0, 0]) cylinder(d=12, h=40);
|
||||||
|
translate([0, 0, 7]) cube([12, 40, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([6, 26, 5]) rotate([-90, 0, 0]) cylinder(d=12, h=14);
|
||||||
|
translate([0, 26, 5]) cube([12, 14, audioTrayIH]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show Cross-section
|
||||||
|
// translate([-2, -1, -1]) cube([audioTraySide + 4, 10, audioTrayHeight + 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module headphoneAmpTray() {
|
||||||
|
difference() {
|
||||||
|
audioTrayBlank(s = audioTraySide, h = audioTrayHeight - 1);
|
||||||
|
|
||||||
|
translate([2*innerWall, (audioTrayIS - 43)/2, innerWall])
|
||||||
|
cube([43, 43, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([3*innerWall + 43, (audioTrayIS - 43)/2, innerWall])
|
||||||
|
cube([12.4, 46, audioTrayIH]);
|
||||||
|
|
||||||
|
translate([50, 8 + innerWall*2, innerWall])
|
||||||
|
cylinder(d=16, h=audioTrayIH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module usbBitsTray() {
|
||||||
|
difference() {
|
||||||
|
audioTrayBlank(s = audioTraySide, h = audioTrayHeight);
|
||||||
|
|
||||||
|
translate([innerWall, innerWall, innerWall])
|
||||||
|
union() {
|
||||||
|
|
||||||
|
// right-angle connectors (1st variation)
|
||||||
|
translate([innerWall, innerWall, -1])
|
||||||
|
for (i = [0, 1]) {
|
||||||
|
translate([34*i, 16*i, 0])
|
||||||
|
rotate([0, 0, 180*i])
|
||||||
|
union() {
|
||||||
|
// main body
|
||||||
|
cube([22.5, 7, 14]);
|
||||||
|
|
||||||
|
// usb connector
|
||||||
|
// 1.64 to edge, 4.64 thick
|
||||||
|
translate([1.4, 0, 0]) cube([6, 16, 14]);
|
||||||
|
|
||||||
|
// release wedge
|
||||||
|
translate([22.5, 0, 0])
|
||||||
|
rotate([0, 15, 0])
|
||||||
|
translate([-22, 0, 0])
|
||||||
|
cube([22, 7, 14]);
|
||||||
|
|
||||||
|
// fingerway
|
||||||
|
translate([-1, -1, 11])
|
||||||
|
cube([36, 18, 3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// right-angle connectors (2nd variation)
|
||||||
|
translate([innerWall, innerWall + 18, 5 + 0.1])
|
||||||
|
for (i = [0, 1]) {
|
||||||
|
translate([30*i, 36*i, 0])
|
||||||
|
rotate([0, 0, 180*i])
|
||||||
|
union() {
|
||||||
|
// main body
|
||||||
|
cube([25, 13, 7]);
|
||||||
|
|
||||||
|
// usb connector
|
||||||
|
// 10.32 wide, 0.73 to edge
|
||||||
|
cube([12, 22, 7]);
|
||||||
|
|
||||||
|
// release wedge
|
||||||
|
translate([17, 0, 0])
|
||||||
|
rotate([0, 30, 0])
|
||||||
|
cube([8, 13, 7]);
|
||||||
|
|
||||||
|
// finergway
|
||||||
|
translate([25, 6.5, 8]) sphere(d=13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// usb A-C converers
|
||||||
|
// 29 x 18 x 9
|
||||||
|
translate([innerWall + 38, innerWall - 0.5, 3])
|
||||||
|
for(i = [0,1]) {
|
||||||
|
translate([0, 28.5*2*i, 0])
|
||||||
|
mirror([0, i, 0])
|
||||||
|
union() {
|
||||||
|
// main body
|
||||||
|
cube([18, 29, 10]);
|
||||||
|
|
||||||
|
// release wedge
|
||||||
|
translate([0, 28.5, -4])
|
||||||
|
rotate([-20, 0, 0])
|
||||||
|
translate([0, -29, 0])
|
||||||
|
cube([18, 29, 14]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
standoffX = outerBoxWidth + 10;
|
||||||
|
standoffY = outerBoxLength + 10;
|
||||||
|
|
||||||
|
// test-print the lip
|
||||||
|
// shellBottom([20, 30, 30]);
|
||||||
|
// translate([24, 0, 0]) shellTop([20, 30, 30]);
|
||||||
|
shellBottom([outerBoxWidth, outerBoxLength, outerBoxHeight]);
|
||||||
|
translate([0, standoffY, 0]) shellTop([outerBoxWidth, outerBoxLength, outerBoxHeight]);
|
||||||
|
translate([standoffX, 0, 0]) layer1();
|
||||||
|
translate([standoffX, standoffY, 0]) layer2();
|
||||||
|
translate([2*standoffX, 0, 0]) audioJackTray();
|
||||||
|
translate([2*standoffX, 80, 0]) usbBitsTray();
|
||||||
|
translate([2*standoffX, 160, 0]) headphoneAmpTray();
|
||||||
|
translate([2*standoffX, 240, 0]) drumKeyTray();
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
$fn=256;
|
||||||
|
|
||||||
|
// all measurements in mm
|
||||||
|
height = 100; // total
|
||||||
|
hoseClampWidth = 12; // accomodate 5/16" (8mm) hose clamp width
|
||||||
|
sectionHeight = 22; // (height - 2 * hoseClampWidth) / 3;
|
||||||
|
centerHeight = height - 2 * (hoseClampWidth + sectionHeight);
|
||||||
|
|
||||||
|
/*
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// main sections
|
||||||
|
for (i = [-1,1]) {
|
||||||
|
translate([0, 0, i * (hoseClampWidth + sectionHeight)])
|
||||||
|
cylinder(d = 48, h = sectionHeight, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hose pipe fitting sections
|
||||||
|
for (i = [-1,1]) {
|
||||||
|
translate([0, 0, i * (0.1 + hoseClampWidth + sectionHeight) * 0.5])
|
||||||
|
cylinder(d = 44, h = hoseClampWidth + 0.2, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, i * ((sectionHeight + hoseClampWidth) * 0.5) + (hoseClampWidth * 0.5) - 1])
|
||||||
|
cylinder(d1 = 44, d2 = 48, h = 2, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, i * ((sectionHeight + hoseClampWidth) * 0.5) + (hoseClampWidth * 0.5) + 1 - hoseClampWidth])
|
||||||
|
cylinder(d1 = 48, d2 = 44, h = 2, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// center section
|
||||||
|
cylinder(d = 48, h = sectionHeight, center = true);
|
||||||
|
|
||||||
|
// center ring
|
||||||
|
translate([0, 0, -1.5]) cylinder(d1 = 48, d2 = 52, h = 3, center = true);
|
||||||
|
translate([0, 0, 1.5]) cylinder(d1 = 52, d2 = 48, h = 3, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hollow out
|
||||||
|
cylinder(d = 36, h = 100.2, center = true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// main sections
|
||||||
|
for (i = [-1,1]) {
|
||||||
|
translate([0, 0, i * ((centerHeight + sectionHeight) * 0.5 + hoseClampWidth)])
|
||||||
|
cylinder(d = 48, h = sectionHeight, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hose pipe fitting sections
|
||||||
|
for (i = [-1,1]) {
|
||||||
|
translate([0, 0, i * (0.1 + hoseClampWidth + centerHeight) * 0.5])
|
||||||
|
cylinder(d = 44, h = hoseClampWidth + 0.2, center = true);
|
||||||
|
|
||||||
|
color("SlateGray")
|
||||||
|
translate([0, 0, (hoseClampWidth / 2 - 1) + i * ((centerHeight + hoseClampWidth)* 0.5)])
|
||||||
|
cylinder(d1 = 44, d2 = 48, h = 2, center = true);
|
||||||
|
|
||||||
|
color("SeaGreen")
|
||||||
|
translate([0, 0, -(hoseClampWidth / 2 - 1) + i * ((centerHeight + hoseClampWidth)* 0.5)])
|
||||||
|
cylinder(d1 = 48, d2 = 44, h = 2, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// center section
|
||||||
|
cylinder(d = 48, h = centerHeight, center = true);
|
||||||
|
|
||||||
|
// center ring
|
||||||
|
translate([0, 0, -1.5]) cylinder(d1 = 48, d2 = 52, h = 3, center = true);
|
||||||
|
translate([0, 0, 1.5]) cylinder(d1 = 52, d2 = 48, h = 3, center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hollow out
|
||||||
|
cylinder(d = 36, h = 100.2, center = true);
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,289 @@
|
|||||||
|
include <../lib/joints.scad>
|
||||||
|
include <../lib/solids.scad>
|
||||||
|
|
||||||
|
// All linear dimensions are in millimeters, all angles in degrees
|
||||||
|
boardThickness = 4;
|
||||||
|
supportAngle = 30;
|
||||||
|
width = 240;
|
||||||
|
depth = 180;
|
||||||
|
toeChop = 36;
|
||||||
|
tenonDims = [boardThickness, boardThickness, 10];
|
||||||
|
morticeDims = [boardThickness, boardThickness + 0.2, 10];
|
||||||
|
|
||||||
|
$fn = 128;
|
||||||
|
|
||||||
|
module triangleCutouts(h, rep = 2, wMul = 1) {
|
||||||
|
tH = h - 2*boardThickness;
|
||||||
|
tW = wMul * tH;
|
||||||
|
tAng = atan(tH / tW);
|
||||||
|
diagonalThickness = boardThickness / sin(tAng);
|
||||||
|
|
||||||
|
// triangle cutouts, 1st half
|
||||||
|
cutoutOffset = tW + boardThickness;
|
||||||
|
translate([cutoutOffset, -0.1, boardThickness]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tW, tH);
|
||||||
|
|
||||||
|
translate([diagonalThickness, 0, 0]) for (i = [0:rep-1]) {
|
||||||
|
setOffset = i * (2 * tW + 2 * diagonalThickness);
|
||||||
|
translate([cutoutOffset + setOffset, -0.1, boardThickness]) mirror([1, 0, 0]) rotate([0, 90, 0]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tH, tW);
|
||||||
|
translate([cutoutOffset + setOffset - 0.1, -0.1, boardThickness]) rotate([0, 90, 0]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tH, tW);
|
||||||
|
translate([cutoutOffset + setOffset + diagonalThickness, -0.1, boardThickness]) mirror([1, 0, 0]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tW, tH);
|
||||||
|
translate([cutoutOffset + setOffset + 2*tW + diagonalThickness - 0.1, -0.1, boardThickness]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tW, tH);
|
||||||
|
|
||||||
|
if (i == rep - 1) {
|
||||||
|
translate([cutoutOffset + setOffset + 2*tW + 2*diagonalThickness, -0.1, boardThickness]) mirror([1, 0, 0]) rotate([0, 90, 0]) rotate([0, 0, 90]) prism(boardThickness + 0.2, tH, tW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module sidePanel(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
translate([0, -toeChop, 0]) difference() {
|
||||||
|
cube([boardThickness, depth, 100]);
|
||||||
|
translate([-0.1, 0, 0]) union() {
|
||||||
|
rotate([supportAngle, 0, 0]) cube([boardThickness + 0.2, 240, 100]);
|
||||||
|
rotate([supportAngle, 0, 0]) translate([0, 192, -80]) cube([boardThickness + 0.2, 40, 100]);
|
||||||
|
translate([0, -0.1, -0.1]) cube([boardThickness + 0.2, toeChop + 0.1, 101]);
|
||||||
|
translate([boardThickness/2 + 0.1, 90, 75]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 50, center = true);
|
||||||
|
|
||||||
|
// Speed holes
|
||||||
|
if (cutWeight) {
|
||||||
|
translate([boardThickness/2 + 0.1, 60, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 10, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 84, 12]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 8, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 104, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 9, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 130, 20]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 14, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 158, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 10, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 156, 42]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 14, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 158, 70]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 9, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dovetail sockets
|
||||||
|
|
||||||
|
// back panel dovetail socket
|
||||||
|
translate([boardThickness, -0.01, 10 + 4])
|
||||||
|
rotate([-90, 90, 0])
|
||||||
|
color("blue") dovetail(tailHeight = boardThickness + 0.01, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness + 0.01);
|
||||||
|
|
||||||
|
// front panel dovetail sockets
|
||||||
|
translate([boardThickness, 144 - boardThickness, 10 + 12])
|
||||||
|
rotate([-90, 90, 0])
|
||||||
|
color("blue") dovetail(tailHeight = boardThickness + 0.01, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness + 0.01);
|
||||||
|
|
||||||
|
translate([boardThickness, 144 - boardThickness, 10 + 48])
|
||||||
|
rotate([-90, 90, 0])
|
||||||
|
color("blue") dovetail(tailHeight = boardThickness + 0.01, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness + 0.01);
|
||||||
|
|
||||||
|
// top panel dovetail sockets
|
||||||
|
color("blue")
|
||||||
|
translate([0, -toeChop, 0])
|
||||||
|
rotate([supportAngle, 0, 0])
|
||||||
|
union() {
|
||||||
|
translate([boardThickness, toeChop + 16, -boardThickness])
|
||||||
|
rotate([0, 0, 90])
|
||||||
|
dovetail(tailHeight = boardThickness + 0.01, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness + 0.01);
|
||||||
|
|
||||||
|
translate([boardThickness, toeChop + 138, -boardThickness])
|
||||||
|
rotate([0, 0, 90])
|
||||||
|
dovetail(tailHeight = boardThickness + 0.01, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness + 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module midPanel(cutWeight = true) {
|
||||||
|
// main panel
|
||||||
|
translate([0, -toeChop, 0])
|
||||||
|
difference() {
|
||||||
|
|
||||||
|
cube([boardThickness, depth - boardThickness, 100]);
|
||||||
|
|
||||||
|
translate([-0.1, 0, 0])
|
||||||
|
union() {
|
||||||
|
// main cut establishing the angled plane
|
||||||
|
rotate([supportAngle, 0, 0])
|
||||||
|
translate([0, 0, -boardThickness])
|
||||||
|
cube([boardThickness + 0.2, 240, 100]);
|
||||||
|
|
||||||
|
// cut off the top corner
|
||||||
|
rotate([supportAngle, 0, 0])
|
||||||
|
translate([0, 192, -80])
|
||||||
|
cube([boardThickness + 0.2, 40, 100]);
|
||||||
|
|
||||||
|
// cut off the toe
|
||||||
|
translate([0, -0.1, -0.1])
|
||||||
|
cube([boardThickness + 0.2, toeChop + boardThickness + 0.1, 101]);
|
||||||
|
|
||||||
|
// cut out the main scoop
|
||||||
|
translate([boardThickness/2 + 0.1, 90, 75])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
cylinder(h = boardThickness + 0.2, r = 50, center = true);
|
||||||
|
|
||||||
|
// cut speed holes
|
||||||
|
if (cutWeight) {
|
||||||
|
translate([boardThickness/2 + 0.1, 60, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 10, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 84, 12]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 8, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 104, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 9, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 130, 20]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 14, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 158, 14]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 10, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 156, 42]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 14, center = true);
|
||||||
|
translate([boardThickness/2 + 0.1, 158, 70]) rotate([0, 90, 0]) cylinder(h = boardThickness + 0.2, r = 9, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// top panel tenons
|
||||||
|
translate([0, -toeChop, 0]) // adjust for the toe chop
|
||||||
|
rotate([supportAngle, 0, 0]) // rotate the tenon plane to match the panel angle
|
||||||
|
union() {
|
||||||
|
// lower tenon
|
||||||
|
// orient the tenon along the plane of the edge
|
||||||
|
// 10 = bring tenon to origin
|
||||||
|
// 43.9 = distance on the plane of the top to lip of the piece
|
||||||
|
// 8 = offset to center the tenon on the piece
|
||||||
|
translate([0, 10 + 43.9 + 8, -boardThickness])
|
||||||
|
rotate([90, 0, 0]) // orient the tenon upright (facing positive Z)
|
||||||
|
tenon(tenonDims);
|
||||||
|
|
||||||
|
// upper tenon
|
||||||
|
// orient the tenon along the plane of the edge
|
||||||
|
// 10 = bring tenon to origin
|
||||||
|
// 159.3 = distance on the plane of the top to lip of the piece
|
||||||
|
// 14.7 = offset to place the tenon on the piece
|
||||||
|
translate([0, 10 + 159.3 + 14.7, -boardThickness]) // orient the tenon along the plane of the edge
|
||||||
|
rotate([90, 0, 0]) // orient the tenon upright
|
||||||
|
tenon(tenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
// front panel tenon
|
||||||
|
translate([0, boardThickness, 4])
|
||||||
|
mirror([0, 1, 0])
|
||||||
|
tenon(tenonDims);
|
||||||
|
|
||||||
|
// back panel tenons
|
||||||
|
translate([0, 144 - boardThickness, 8]) tenon(tenonDims);
|
||||||
|
translate([0, 144 - boardThickness, 48]) tenon(tenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
module backPanel(cutWeight = true) {
|
||||||
|
panelHeight = 18.4;
|
||||||
|
translate([boardThickness, 0, 0])
|
||||||
|
difference() {
|
||||||
|
cube([width - boardThickness * 2, boardThickness, panelHeight]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
triangleCutouts(h = panelHeight, rep = 3, wMul = 0.95);
|
||||||
|
translate([width - boardThickness * 2, 0, 0]) mirror([1, 0, 0]) triangleCutouts(h = panelHeight, rep = 3, wMul = 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([(width - 3*boardThickness) / 2, 0, 4]) morticeBlank(morticeDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dovetails to connect to the side panels
|
||||||
|
translate([boardThickness, boardThickness, 4])
|
||||||
|
rotate([0, -90, 90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
translate([width - boardThickness, 0, 4])
|
||||||
|
rotate([0, -90, -90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module frontPanel(cutWeight = true) {
|
||||||
|
panelHeight = 72.2;
|
||||||
|
translate([boardThickness, 0, 0])
|
||||||
|
difference() {
|
||||||
|
cube([width - boardThickness * 2, boardThickness, panelHeight]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
triangleCutouts(h = panelHeight, rep = 1, wMul = 0.48);
|
||||||
|
translate([width - boardThickness * 2, 0, 0]) mirror([1, 0, 0]) triangleCutouts(h = panelHeight, rep = 1, wMul = 0.48);;
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([(width - 3*boardThickness) / 2, 0, 8]) morticeBlank(morticeDims);
|
||||||
|
translate([(width - 3*boardThickness) / 2, 0, 48]) morticeBlank(morticeDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dovetails to connect to the side panels
|
||||||
|
translate([boardThickness, boardThickness, 12])
|
||||||
|
rotate([0, -90, 90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
translate([width - boardThickness, 0, 12])
|
||||||
|
rotate([0, -90, -90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
translate([boardThickness, boardThickness, 48])
|
||||||
|
rotate([0, -90, 90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
translate([width - boardThickness, 0, 48])
|
||||||
|
rotate([0, -90, -90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module topPanel(cutWeight = true) {
|
||||||
|
panelHeight = 26;
|
||||||
|
|
||||||
|
translate([boardThickness, 0, 0])
|
||||||
|
difference() {
|
||||||
|
cube([width - boardThickness * 2, boardThickness, panelHeight]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
triangleCutouts(h = panelHeight, wMul = 0.9);
|
||||||
|
translate([width - boardThickness * 2, 0, 0]) mirror([1, 0, 0]) triangleCutouts(h = panelHeight, wMul = 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mortice to connect to the mid piece
|
||||||
|
translate([(width - 3*boardThickness)/2, -0.1, 8]) morticeBlank(morticeDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dovetails to connect to the side panels
|
||||||
|
translate([boardThickness, boardThickness, 8])
|
||||||
|
rotate([0, -90, 90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
|
||||||
|
translate([width - boardThickness, 0, 8])
|
||||||
|
rotate([0, -90, -90])
|
||||||
|
dovetail(tailHeight = boardThickness, tailWidthMin = 6, tailWidthMax = 10, depth = boardThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
module assembled(cutWeight = true) {
|
||||||
|
spaceBetween = (width - 3*boardThickness) / 2;
|
||||||
|
|
||||||
|
color("Tan") sidePanel(cutWeight);
|
||||||
|
color("RosyBrown") translate([1*(boardThickness + spaceBetween), 0, 0]) midPanel(cutWeight);
|
||||||
|
color("Tan") translate([2*(boardThickness + spaceBetween) + boardThickness, 0, 0]) mirror([1, 0, 0]) sidePanel(cutWeight);
|
||||||
|
|
||||||
|
color("DarkSeaGreen") backPanel(cutWeight);
|
||||||
|
color("LightSeaGreen") translate([0, depth - toeChop - boardThickness, 0]) frontPanel(cutWeight);
|
||||||
|
|
||||||
|
color("SkyBlue") translate([0, -toeChop, 0]) rotate([1*(-90 + supportAngle), 0, 0]) translate([0, 0, 43.9]) topPanel(cutWeight);
|
||||||
|
color("LightSteelBlue") translate([0, -toeChop, 0]) rotate([1*(-90 + supportAngle), 0, 0]) translate([0, 0, 166]) topPanel(cutWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module flatPack(cutWeight = true) {
|
||||||
|
color("Tan") translate([0, 60, boardThickness]) rotate([0, 90, 0]) sidePanel(cutWeight);
|
||||||
|
color("Tan") translate([98, 144, 0]) mirror([0, 0, 1]) rotate([0, 90, 180]) sidePanel(cutWeight);
|
||||||
|
color("RosyBrown") translate([180, 300, boardThickness]) mirror([0, 1, 0]) rotate([0, 90, 90]) midPanel(cutWeight);
|
||||||
|
|
||||||
|
color("DarkSeaGreen") translate([100, 0, 0]) rotate([90, 0, 90]) backPanel(cutWeight);
|
||||||
|
|
||||||
|
color("LightSeaGreen") translate([120, 0, 0]) rotate([90, 0, 90]) frontPanel(cutWeight);
|
||||||
|
|
||||||
|
color("SkyBlue") translate([194, 0, 0]) rotate([90, 0, 90]) topPanel(cutWeight);
|
||||||
|
color("LightSteelBlue") translate([222, 0, 0]) rotate([90, 0, 90]) topPanel(cutWeight);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// backPanel();
|
||||||
|
// midPanel();
|
||||||
|
// topPanel();
|
||||||
|
// sidePanel();
|
||||||
|
|
||||||
|
// assembled();
|
||||||
|
flatPack();
|
||||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
|||||||
|
include <../../lib/metric-machine-screws.scad>;
|
||||||
|
|
||||||
|
$fn=128;
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cylinder(d=20, h=6);
|
||||||
|
translate([0, -10, 0]) cube([160, 20, 6]);
|
||||||
|
translate([160, 0, 0]) cylinder(d=20, h=6);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = [7.5, 68.7, 152.5]) {
|
||||||
|
translate([x, 0, -0.01]) union() {
|
||||||
|
translate([0, 0, 2.02]) m4Nut(h = 4);
|
||||||
|
cylinder(d=4, h=8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//color("blue") translate([80, 0, 0]) rotate([0, 90, 0]) import("Coat_Rack.stl");
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
|||||||
|
$fn=128;
|
||||||
|
length=95;
|
||||||
|
|
||||||
|
rotate([90, 0, 0]) translate([0, length / 2, 0]) difference() {
|
||||||
|
union() {
|
||||||
|
rotate([90, 0, 0]) cylinder(d=30, h=length, center=true);
|
||||||
|
translate([10, 0, 0]) cube([20, length, 30], center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
translate([0, -0.01, 0]) rotate([90, 0, 0]) cylinder(d=20, h=length + 0.2, center=true);
|
||||||
|
translate([20, -0.01, 0]) cube([40, length + 0.2, 20], center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//translate([-4, -4, 0]) cylinder(d=14, h=5.2);
|
||||||
|
|
||||||
|
//translate([-1, -1]) cylinder(d=4, h=15);
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
include <../lib/metric-machine-screws.scad>
|
||||||
|
|
||||||
|
$fn=128;
|
||||||
|
|
||||||
|
h_handle = 200; // Length of the handle
|
||||||
|
h_tilted = h_handle / sqrt(2);
|
||||||
|
|
||||||
|
d_handle = 20; // Diameter of the handle
|
||||||
|
screw_distance_on_center = 88.5;
|
||||||
|
|
||||||
|
//translate([0, 0, h_tilted / 2])
|
||||||
|
//rotate([45, 0, 0])
|
||||||
|
//translate([0, d_handle / 2, 0])
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cylinder(d=d_handle, h=h_handle, center=true); // Main handle body
|
||||||
|
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
translate([0, 17, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d=10, h=18, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
translate([0, 5, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
m3Nut(h=d_handle + 10, center=true, clearance=0.2);
|
||||||
|
|
||||||
|
translate([0, 7, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d=3.2, h=40, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
translate([0, -0.2, h_tilted / 2])
|
||||||
|
difference() {
|
||||||
|
cube([1, h_tilted, h_tilted], center=true);
|
||||||
|
|
||||||
|
color("blue")
|
||||||
|
translate([0, h_tilted / 2, h_tilted / 2])
|
||||||
|
rotate([45, 0, 0])
|
||||||
|
cube([2, h_handle, h_handle], center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0, -h_tilted / 2, 40])
|
||||||
|
cube([40, 1, 80], center=true);
|
||||||
|
*/
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
difference() {
|
||||||
|
cube([]);
|
||||||
|
|
||||||
|
union() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This thing was created by Thingiverse user GhostsonAcid, and is licensed under GNU - GPL
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
Stronger wall-hook by GhostsonAcid on Thingiverse: https://www.thingiverse.com/thing:5587903
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
Here's a 2-part hook for safely hanging kitchen pans, or other 'heavy' things.-Use a single M4 screw. Also, I included a small hole at the bottom of the hook for an optional "finishing nail" (-diameter ≤1.5mm) to help prevent rotation.-Please note that the bottoms of each piece are designed to interlock with each-other, and thus will hold firmly in place, once installed. (-Refer to the picture above.)--> I would like to do more with this design, but right now I feel I just don't have so much time to devote to such a small project.For this, I simply wanted a stronger hook than most. The better (i.e. stronger) way to print a hook is with it lying on its side. -But then what about a back-plate that keeps it from twisting?..... So, this is what I arrived at.-Will update/change later, maybe.....
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,68 @@
|
|||||||
|
include <../lib/rounded-cube.scad>
|
||||||
|
|
||||||
|
$fn=256;
|
||||||
|
|
||||||
|
d=40;
|
||||||
|
l=140;
|
||||||
|
|
||||||
|
module version1() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
rotate([0, 10, 0]) cube([d, l, 50]);
|
||||||
|
translate([1.5*d, 0, 0]) mirror([1, 0, 0]) rotate([0, 10, 0]) cube([d, l, 50]);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0.75*d, l+1, 0.5*d+12]) rotate([90, 0, 0]) cylinder(d=d, h=l+2);
|
||||||
|
translate([-d, -1, 20]) cube([3*d, l + 2, 40]);
|
||||||
|
translate([-d, -1, -10]) cube([3*d, l + 2, 10]);
|
||||||
|
color("red") translate([-1, l*0.5+4, -124]) rotate([0, 90, 0]) cylinder(d=270, h=1.5*d+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0, 0, 0.01])
|
||||||
|
difference() {
|
||||||
|
rotate([-20, 0, 0])
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
rotate([0, 10, 0]) translate([0, 0, -15-0.01]) cube([1.4*d, 12, 30]);
|
||||||
|
translate([1.5*d, 0, 0]) mirror([1, 0, 0]) rotate([0, 10, 0]) translate([0, 0, -15-0.01]) cube([1.4*d, 12, 30]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translate([-10, -10, -45]) cube([1.5*d + 20, 30, 35]);
|
||||||
|
translate([-d, -10, 0]) cube([3.5*d, 40, 20]);
|
||||||
|
translate([-10, -10, -20]) cube([1.5*d + 20, 10, 40]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module version2() {
|
||||||
|
difference() {
|
||||||
|
translate([0, 0, -10]) cube([1.5*d, l, 50]);
|
||||||
|
|
||||||
|
// mic handle cut-out
|
||||||
|
translate([0.75*d, l+1, 0.5*d+12]) rotate([90, 0, 0]) cylinder(d=d, h=l+2);
|
||||||
|
|
||||||
|
// top cut
|
||||||
|
translate([-10, -1, 0.5*d]) cube([1.5*d + 20, l+2, 50]);
|
||||||
|
|
||||||
|
// bottom notch cut
|
||||||
|
translate([0, 12, 0]) rotate([-20, 0, 0]) translate([-1, 0, -20]) cube([1.5*d+2, 20, 20]);
|
||||||
|
|
||||||
|
// button flush cut
|
||||||
|
translate([-1, 12, -20]) cube([1.5*d+2, l, 20]);
|
||||||
|
|
||||||
|
// MODX-8 button clearance
|
||||||
|
union() {
|
||||||
|
translate([0, 24, 0]) rotate([-20, 0, 0]) translate([-1, 0, -12]) cube([1.5*d+2, 20, 20.5]);
|
||||||
|
translate([-1, 26.90, -12]) cube([1.5*d+2, l-50, 20]);
|
||||||
|
translate([0, l-20, 0]) mirror([0, 1, 0]) rotate([-20, 0, 0]) translate([-1, 0, -12]) cube([1.5*d+2, 20, 20.5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// side-cuts
|
||||||
|
translate([-8, 0, 0]) rotate([0, 10, 0]) translate([0, -1, -20]) cube([10, l+2, 50]);
|
||||||
|
color("red") translate([1.5*d, 0, 0]) mirror([1, 0, 0]) translate([-8, 0, 0])rotate([0, 10, 0]) translate([0, -1, -20]) cube([10, l+2, 50]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//translate([2*d, 0, 0]) version1();
|
||||||
|
version2();
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
|||||||
|
include <../lib/threads/threads.scad>
|
||||||
|
|
||||||
|
$fn=256;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
translate([0, 0, 3.5]) cylinder(d1=34.3, d2=35.7, h=82, $fn=256);
|
||||||
|
cylinder(d1=28, d2=34.3, h=3.5, $fn=256);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0, 0, 3.5]) cylinder(d=31, h=90, $fn=128);
|
||||||
|
translate([0, 0, -1]) cylinder(d=27.6, h=10, $fn=128);
|
||||||
|
|
||||||
|
translate([0, 0, 82 + 3.5 - 20 - 4.3])
|
||||||
|
difference() {
|
||||||
|
AugerThread(outer_diam=36, inner_diam=29.8, height=20, pitch=3, tooth_angle=25, tip_min_fract=15);
|
||||||
|
//ScrewThread(outer_diam=33, height=20, pitch=3, tooth_angle=5, tooth_height=0.8);
|
||||||
|
|
||||||
|
color("red")
|
||||||
|
difference() {
|
||||||
|
translate([0, 0, -1]) cylinder(d=40, h=22);
|
||||||
|
translate([0, 0, -2]) cylinder(d=33, h=24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0, 0, 82 + 3.5 - 4.4]) cylinder(d=33, h=90, $fn=128);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
include <./insert-box.scad>;
|
||||||
|
|
||||||
|
$fn=64;
|
||||||
|
dowelDiameter = 12.7; // 0.5 inch
|
||||||
|
module dowel() {
|
||||||
|
color("Sienna") rotate([0, 90, ])
|
||||||
|
cylinder(h=innerSide, d=dowelDiameter, center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
outerBox();
|
||||||
|
supportingFelt();
|
||||||
|
|
||||||
|
translate([feltThickness + boardThickness, 0, feltThickness + boardThickness])
|
||||||
|
union() {
|
||||||
|
// Everything within this union is referenced off of the inner box. The outer
|
||||||
|
// translate accounts for the felt and walls.
|
||||||
|
|
||||||
|
translate([innerSide/2, 0, innerSide - dowelDiameter*1.5]) // center dowels on X, raise Z
|
||||||
|
union() {
|
||||||
|
translate([0, kallaxDepth*0.25, 0]) dowel();
|
||||||
|
translate([0, kallaxDepth*0.75, 0]) dowel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
dowelDiameter = 12.7; // 1/2 inch in mm
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
$fn = 32;
|
||||||
|
|
||||||
|
l = 76;
|
||||||
|
w = 50;
|
||||||
|
th = 1;
|
||||||
|
|
||||||
|
color("black") cube([l, w, th], center=true);
|
||||||
|
// color("white") translate([0, 0, th]) linear_extrude(0.2) text("Ethernet", font="monofur", halign="center", valign="center",size=12);
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
kallaxSide = 335; // Full width of a Kallax shelf
|
||||||
|
kallaxDepth = 390; // Full depth of a Kallax shelf
|
||||||
|
|
||||||
|
shelfHeight = 160; // Height of a Kallax half-shelf (shelf insert)
|
||||||
|
shelfWidth = 320; // Width of a Kallax half-shelf (shelf insert)
|
||||||
|
shelfDepth = kallaxDepth - 20;
|
||||||
|
|
||||||
|
// boardThickness = 4.7; // 1/8" plywood
|
||||||
|
boardThickness = 7.35;
|
||||||
|
feltThickness = 2.5;
|
||||||
|
feltWidth = 12;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
|||||||
|
include <./constants.scad>;
|
||||||
|
|
||||||
|
boardThickness = 6.4;
|
||||||
|
feltThickness = 2.4;
|
||||||
|
feltWidth = 12;
|
||||||
|
innerSide = kallaxSide - 2 * (feltThickness + boardThickness);
|
||||||
|
|
||||||
|
module feltStrip() {
|
||||||
|
color("DimGray") cube([feltThickness, kallaxDepth, feltWidth]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module sideBoard() {
|
||||||
|
difference() {
|
||||||
|
color ("BurlyWood") cube([boardThickness, kallaxDepth, kallaxSide - 2*feltThickness]);
|
||||||
|
color("black") translate([0.2, 100, 30]) rotate([90, 0, -90]) linear_extrude(0.3)
|
||||||
|
text(font="Iosevka", size=16, halign="center", valign="center", "side - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module horizontalBoard() {
|
||||||
|
difference() {
|
||||||
|
color ("Wheat") cube([innerSide, kallaxDepth, boardThickness]);
|
||||||
|
color("black") translate([110, 30, boardThickness - 0.2]) rotate([0, 0, 0]) linear_extrude(0.3)
|
||||||
|
text(font="Iosevka", size=16, halign="center", valign="center", "top/bot - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module outerBox() {
|
||||||
|
translate([feltThickness, 0, feltThickness]) union() {
|
||||||
|
// left and right side boards
|
||||||
|
translate([0, 0, 0]) sideBoard();
|
||||||
|
translate([innerSide + boardThickness , 0, 0]) sideBoard();
|
||||||
|
|
||||||
|
// top and bottom horizontal boards
|
||||||
|
translate([boardThickness, 0, 0]) horizontalBoard();
|
||||||
|
translate([boardThickness, 0, innerSide + boardThickness]) horizontalBoard();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module supportingFelt() {
|
||||||
|
// felt strips for the left side
|
||||||
|
translate([0, 0, feltThickness + 20]) feltStrip();
|
||||||
|
translate([0, 0, (innerSide - feltThickness)/2]) feltStrip();
|
||||||
|
translate([0, 0, feltThickness + innerSide - feltWidth - 20]) feltStrip();
|
||||||
|
|
||||||
|
// felt strips for the right side
|
||||||
|
translate([innerSide + feltThickness + 2*boardThickness, 0, feltThickness + 20]) feltStrip();
|
||||||
|
translate([innerSide + feltThickness + 2*boardThickness, 0, (innerSide - feltThickness)/2]) feltStrip();
|
||||||
|
translate([innerSide + feltThickness + 2*boardThickness, 0, feltThickness + innerSide - feltWidth - 20]) feltStrip();
|
||||||
|
|
||||||
|
// felt strips for the top
|
||||||
|
translate([feltWidth + boardThickness + 20, 0, 0]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
translate([(kallaxSide - feltWidth)/2, 0, 0]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
translate([kallaxSide - feltWidth - 20, 0, 0]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
|
||||||
|
// felt strips for the bottom
|
||||||
|
translate([feltWidth + 20, 0, kallaxSide - feltThickness]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
translate([(kallaxSide - feltWidth)/2, 0, kallaxSide - feltThickness]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
translate([kallaxSide - feltWidth - 20, 0, kallaxSide - feltThickness]) rotate([0, -90, 0]) feltStrip();
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
include <../lib/chamfered-cube.scad>
|
||||||
|
include <../lib/rounded-cube.scad>
|
||||||
|
include <./constants.scad>
|
||||||
|
|
||||||
|
$fn=128;
|
||||||
|
l=shelfWidth/2;
|
||||||
|
h=shelfHeight/2;
|
||||||
|
|
||||||
|
ep = 0.01;
|
||||||
|
|
||||||
|
horizontalBoardWidth = 141.5;
|
||||||
|
drawerSideHeight = 53;
|
||||||
|
sideOffset = 2*feltThickness + boardThickness;
|
||||||
|
|
||||||
|
module faceBlank() {
|
||||||
|
size = [shelfWidth/2, shelfHeight/2, 8];
|
||||||
|
chamfer = 4;
|
||||||
|
difference() {
|
||||||
|
roundedCube([l, h, 8], [1, 1, 1]);
|
||||||
|
|
||||||
|
// front face chamfers
|
||||||
|
for (i = [1,3]) {
|
||||||
|
// X-axis
|
||||||
|
translate([-ep, size[1] * floor(i/2), size[2] * (i%2) - chamfer])
|
||||||
|
rotate([45, 0, 0]) cube([size[0] + 2*ep, 1.414*chamfer, 1.414*chamfer]);
|
||||||
|
|
||||||
|
// Y-axis
|
||||||
|
translate([size[0] * floor(i/2) - chamfer, -ep, size[2] * (i%2)])
|
||||||
|
rotate([0, 45, 0]) cube([1.414*chamfer, size[1] + 2*ep, 1.414*chamfer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameplate cutouts
|
||||||
|
translate([(shelfWidth/2 - 76.4)/2, 30, 7]) cube([76.4, 36, 1 + ep]);
|
||||||
|
translate([(shelfWidth/2 - 76.4)/2, 30 + 36, 7])
|
||||||
|
rotate([30, 0, 0]) cube([76.4, 4, 4]);
|
||||||
|
|
||||||
|
// screw holes
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
color("red")
|
||||||
|
translate([shelfWidth/4 + i*20, 16, -ep]) cylinder(d=3.4, h=8 + 2*ep);
|
||||||
|
translate([shelfWidth/4 + i*20, 16, -ep]) cylinder(d=6.2, h=3 + ep);
|
||||||
|
translate([shelfWidth/4 + i*20, 16, 3 - ep]) cylinder(d1=6.2, d2=3.4, h=1 + 2*ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module handle() {
|
||||||
|
handleLen = 64;
|
||||||
|
//difference() {
|
||||||
|
chamferedCube([handleLen, 12, 12], chamfer=3);
|
||||||
|
|
||||||
|
// screw holes
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
difference() {
|
||||||
|
translate([handleLen/2 + i*20, 6, 12-ep]) cylinder(d=6, h=8 + ep);
|
||||||
|
translate([handleLen/2 + i*20, 6, 12-ep]) cylinder(d=3, h=8 + 2*ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module lowerRight() {
|
||||||
|
difference() {
|
||||||
|
faceBlank();
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([shelfWidth/4 + 6, shelfHeight/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "LR");
|
||||||
|
|
||||||
|
// horizontal board recess
|
||||||
|
translate([sideOffset, sideOffset, -ep])
|
||||||
|
cube([horizontalBoardWidth, boardThickness, 4+ep]);
|
||||||
|
|
||||||
|
// vertical board recesses
|
||||||
|
translate([sideOffset, sideOffset + boardThickness, -ep])
|
||||||
|
cube([boardThickness, 62, 4+ep]);
|
||||||
|
translate([sideOffset + horizontalBoardWidth - boardThickness, sideOffset + boardThickness, -ep])
|
||||||
|
cube([boardThickness, 62, 4+ep]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module lowerLeft() {
|
||||||
|
difference() {
|
||||||
|
faceBlank();
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([shelfWidth/4 + 6, shelfHeight/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "LL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module upperRight() {
|
||||||
|
difference() {
|
||||||
|
faceBlank();
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([shelfWidth/4 + 6, shelfHeight/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "UR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module upperLeft() {
|
||||||
|
difference() {
|
||||||
|
faceBlank();
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([shelfWidth/4 + 6, shelfHeight/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "UL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lowerRight();
|
||||||
|
translate([0, 200, 0]) handle();
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,525 @@
|
|||||||
|
// System to divide a Kallax half-shelf into four equal drawers
|
||||||
|
// All units measured in millimeters
|
||||||
|
include <../lib/mortice-and-tenon.scad>
|
||||||
|
include <./constants.scad>
|
||||||
|
|
||||||
|
$fn = 32;
|
||||||
|
|
||||||
|
module sampleBox(dims, wallThickness) {
|
||||||
|
// base
|
||||||
|
cube([dims[0], dims[1], wallThickness]);
|
||||||
|
|
||||||
|
// top
|
||||||
|
translate([0, 0, dims[2] - wallThickness])
|
||||||
|
cube([dims[0], dims[1], wallThickness]);
|
||||||
|
|
||||||
|
// middle shelf
|
||||||
|
translate([0, 0, (dims[2] - wallThickness) / 2])
|
||||||
|
cube([dims[0], dims[1], wallThickness]);
|
||||||
|
|
||||||
|
// left wall
|
||||||
|
cube([wallThickness, dims[1], dims[2]]);
|
||||||
|
|
||||||
|
// middle divider
|
||||||
|
translate([(dims[0] - wallThickness) / 2, 0, 0])
|
||||||
|
cube([wallThickness, dims[1], dims[2]]);
|
||||||
|
|
||||||
|
// right wall
|
||||||
|
translate([dims[0] - wallThickness, 0, 0])
|
||||||
|
cube([wallThickness, dims[1], dims[2]]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module tally(count, rightAlign = false) {
|
||||||
|
groups = floor(count / 5);
|
||||||
|
rem = count % 5;
|
||||||
|
xAlign = rightAlign ? -(6 * groups) - (rem * 1.2) : 0;
|
||||||
|
translate([xAlign, 0, 0])
|
||||||
|
union() {
|
||||||
|
if (count > 4) {
|
||||||
|
for (i = [0: max(0, groups - 1)]) {
|
||||||
|
translate([6*i, 0, 0]) for (j = [0:3])
|
||||||
|
translate([j*1.2, 0, 0])
|
||||||
|
cube([0.6, 4, 0.41]);
|
||||||
|
translate([6*i - 0.8, 0.6, 0]) rotate([0, 0, -60]) cube([0.6, 6.2, 0.41]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rem != 0) {
|
||||||
|
translate([6*groups, 0, 0])
|
||||||
|
for (j = [0: rem - 1])
|
||||||
|
translate([j*1.2, 0, 0])
|
||||||
|
cube([0.6, 4, 0.41]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wallThickness = 4; // Thickness of walls
|
||||||
|
feltClearance = 2.5; // Clearance for felt pads
|
||||||
|
|
||||||
|
// Dimensions for the box that fits inside a Kallax half-shelf
|
||||||
|
boxWidth = kallaxSide - 2 * feltClearance;
|
||||||
|
boxDepth = kallaxDepth;
|
||||||
|
boxHeight = shelfHeight - 2 * feltClearance;
|
||||||
|
|
||||||
|
drawerWidth = (boxWidth - 3 * wallThickness) / 2;
|
||||||
|
drawerHeight = (boxHeight - 3 * wallThickness) / 2;
|
||||||
|
|
||||||
|
tenonThickness = wallThickness * 0.6;
|
||||||
|
//tenon([6, 8, 2.6]);
|
||||||
|
//morticeBlank([6, 8, 2.6], 0.1);
|
||||||
|
|
||||||
|
|
||||||
|
// Frame for the box will be made in sections to fit on the print bed
|
||||||
|
// There are three identical horizontal layers (base, middle shelf, top) that
|
||||||
|
// will each be made of four pieces. Looking down overhead from the Z axis they
|
||||||
|
// are:
|
||||||
|
//
|
||||||
|
// x1 x2
|
||||||
|
// ├──┴──┼─┴─┤
|
||||||
|
// ┌─────┬───┐ ┬
|
||||||
|
// │ C │ D │ │
|
||||||
|
// ├─────┼───┤ ├y
|
||||||
|
// │ A │ B │ │
|
||||||
|
// └─────┴───┘ ┴
|
||||||
|
//
|
||||||
|
// There are three identical drawer sides for the lower drawers that are split
|
||||||
|
// into two pieces. Looking from the side, along the X axis they are:
|
||||||
|
//
|
||||||
|
// ├───y───┤
|
||||||
|
// ┌───┬───┐ ┬
|
||||||
|
// │ F │ E │ ├drawerHeight
|
||||||
|
// └───┴───┘ ┴
|
||||||
|
//
|
||||||
|
// There are three identical drawer sides for the upper drawers that are split
|
||||||
|
// into two pieces. Looking from the side, along the X axis they are:
|
||||||
|
//
|
||||||
|
// ├───y───┤
|
||||||
|
// ┌───┬───┐ ┬
|
||||||
|
// │ H │ G │ ├drawerHeight
|
||||||
|
// └───┴───┘ ┴
|
||||||
|
|
||||||
|
x1 = boxWidth * 0.6;
|
||||||
|
x2 = boxWidth - x1;
|
||||||
|
y = boxDepth / 2;
|
||||||
|
tenonDims = [6, 8, tenonThickness];
|
||||||
|
tenonZOffset = (wallThickness - tenonThickness) / 2;
|
||||||
|
verticalTenonDims = [6, wallThickness, tenonThickness];
|
||||||
|
throughTenonDims = [6, 8 + wallThickness, tenonThickness];
|
||||||
|
morticeClearance = 0.1;
|
||||||
|
|
||||||
|
module leftSideHorizontalPiece(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
cube([x1, y, wallThickness]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
union() {
|
||||||
|
// cutouts to save materials
|
||||||
|
translate([2*wallThickness, 2*wallThickness, -0.1])
|
||||||
|
cube([drawerWidth - 2*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
|
||||||
|
translate([2*wallThickness, y/2 + wallThickness, -0.1])
|
||||||
|
cube([drawerWidth - 2*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
|
||||||
|
translate([drawerWidth + 3*wallThickness, 2*wallThickness, -0.1])
|
||||||
|
cube([x1 - drawerWidth - 5*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
|
||||||
|
translate([drawerWidth + 3*wallThickness, y/2 + 2*wallThickness, -0.1])
|
||||||
|
cube([x1 - drawerWidth - 5*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module rightSideHorizontalPiece(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
cube([x2, y, wallThickness]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
union() {
|
||||||
|
// cutouts to save materials
|
||||||
|
translate([2*wallThickness, 2*wallThickness, -0.1])
|
||||||
|
cube([x2 - 4*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
translate([2*wallThickness, y/2 + wallThickness, -0.1])
|
||||||
|
cube([x2 - 4*wallThickness, y/2 - 3*wallThickness, wallThickness + 0.2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module sidePiece(cutWeight = true) {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
cube([wallThickness, y, drawerHeight]);
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
// cutouts to save materials
|
||||||
|
translate([-0.1, 2*wallThickness, 2*wallThickness])
|
||||||
|
cube([wallThickness + 0.2, y - 4*wallThickness, drawerHeight - 3*wallThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cutWeight) {
|
||||||
|
translate([0, wallThickness, 1.414*wallThickness])
|
||||||
|
rotate([-41, 0, 0])
|
||||||
|
cube([wallThickness, wallThickness, drawerHeight * 1.19]);
|
||||||
|
|
||||||
|
translate([0, y - 2*wallThickness, 1.414*wallThickness])
|
||||||
|
rotate([65, 0, 0])
|
||||||
|
cube([wallThickness, wallThickness, drawerHeight * 1.97]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceA(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
leftSideHorizontalPiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to piece C
|
||||||
|
translate([x1*0.2, y, tenonZOffset]) tenon(tenonDims);
|
||||||
|
translate([x1*0.7, y, tenonZOffset]) tenon(tenonDims);
|
||||||
|
|
||||||
|
// tenons for joining to piece B
|
||||||
|
translate([x1, y*0.2, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90]) tenon(tenonDims);
|
||||||
|
translate([x1, y*0.7, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90]) tenon(tenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortices for joining to piece vertical pieces
|
||||||
|
translate([tenonZOffset, y* 0.3, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([tenonZOffset, y* 0.8, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
translate([drawerWidth + wallThickness + tenonZOffset, y* 0.3, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([drawerWidth + wallThickness + tenonZOffset, y* 0.8, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([2, 2, wallThickness - 0.4]) tally(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceB(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
rightSideHorizontalPiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to piece D
|
||||||
|
translate([x2*0.2, y, tenonZOffset]) tenon(tenonDims);
|
||||||
|
translate([x2*0.7, y, tenonZOffset]) tenon(tenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortices for joining to piece A
|
||||||
|
translate([0, y*0.2, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
translate([0, y*0.7, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// mortices for joining to piece vertical pieces
|
||||||
|
translate([x2 - wallThickness + tenonZOffset, y* 0.3, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
translate([x2 - wallThickness + tenonZOffset, y* 0.8, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([2, 2, wallThickness - 0.4]) tally(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceC(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
leftSideHorizontalPiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to piece D
|
||||||
|
translate([x1, y*0.2, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90]) tenon(tenonDims);
|
||||||
|
translate([x1, y*0.7, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90]) tenon(tenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
|
||||||
|
// mortices for joining to piece A
|
||||||
|
translate([x1*0.2, 0, tenonZOffset])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
translate([x1*0.7, 0, tenonZOffset])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// mortices for joining to piece F/H
|
||||||
|
translate([tenonZOffset, y* 0.3, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([tenonZOffset, y* 0.8, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
translate([drawerWidth + wallThickness + tenonZOffset, y* 0.3, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([drawerWidth + wallThickness + tenonZOffset, y* 0.8, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([2, 2, wallThickness - 0.4]) tally(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceD(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
rightSideHorizontalPiece(cutWeight);
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortices for joining to piece C
|
||||||
|
translate([0, y*0.2, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
translate([0, y*0.7, tenonZOffset])
|
||||||
|
mirror([0, 1, 0]) rotate([0, 0, -90])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// mortices for joining to piece B
|
||||||
|
translate([x2*0.2, 0, tenonZOffset])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
translate([x2*0.7, 0, tenonZOffset])
|
||||||
|
morticeBlank(tenonDims, morticeClearance);
|
||||||
|
// mortices for joining to piece F/H
|
||||||
|
translate([x2 - wallThickness + tenonZOffset, y* 0.3, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
translate([x2 - wallThickness + tenonZOffset, y* 0.8, 0])
|
||||||
|
rotate([90, 0, 90]) morticeBlank(tenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([2, 2, wallThickness - 0.4]) tally(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceE(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
sidePiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to horizontal pieces
|
||||||
|
translate([tenonZOffset, y*0.3, 0]) mirror([1, 0, 0])
|
||||||
|
rotate([-90, 0, 90]) tenon(verticalTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, 0]) mirror([1, 0, 0])
|
||||||
|
rotate([-90, 0, 90]) tenon(verticalTenonDims);
|
||||||
|
|
||||||
|
// tenon for joining to piece F
|
||||||
|
translate([tenonZOffset, y, drawerHeight/2]) mirror([0, 0, 1])
|
||||||
|
rotate([0, 90, 00]) tenon(tenonDims);
|
||||||
|
|
||||||
|
// tenons for joining to piece G
|
||||||
|
translate([tenonZOffset, y*0.3, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(throughTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(throughTenonDims);
|
||||||
|
//translate([tenonZOffset, y*0.8, 0]) mirror([1, 0, 0])
|
||||||
|
// rotate([-90, 0, 90]) tenon(verticalTenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([0.4, 2, 2]) rotate([90, 0, -90]) tally(5, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceF(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
sidePiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to horizontal pieces
|
||||||
|
translate([tenonZOffset, y*0.3, 0]) mirror([1, 0, 0])
|
||||||
|
rotate([-90, 0, 90]) tenon(verticalTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, 0]) mirror([1, 0, 0])
|
||||||
|
rotate([-90, 0, 90]) tenon(verticalTenonDims);
|
||||||
|
|
||||||
|
// tenons for joining to piece H
|
||||||
|
translate([tenonZOffset, y*0.3, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(throughTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(throughTenonDims);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortice for joining to piece E
|
||||||
|
translate([tenonZOffset, 0, drawerHeight/2]) mirror([0, 0, 1])
|
||||||
|
rotate([0, 90, 00]) tenon(tenonDims);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([0.4, 2, 2]) rotate([90, 0, -90]) tally(6, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceG(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
sidePiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to vertical pieces above
|
||||||
|
translate([tenonZOffset, y*0.3, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(verticalTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(verticalTenonDims);
|
||||||
|
|
||||||
|
// tenon for joining to piece H
|
||||||
|
translate([tenonZOffset, y, drawerHeight/2]) mirror([0, 0, 1])
|
||||||
|
rotate([0, 90, 00]) tenon(tenonDims);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortices for joining to piece E
|
||||||
|
translate([tenonZOffset, y*0.3, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([tenonZOffset, y*0.8, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([0.4, 2, 2]) rotate([90, 0, -90]) tally(7, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module pieceH(cutWeight = true) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
sidePiece(cutWeight);
|
||||||
|
|
||||||
|
// tenons for joining to vertical pieces above
|
||||||
|
translate([tenonZOffset, y*0.3, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(verticalTenonDims);
|
||||||
|
translate([tenonZOffset, y*0.8, drawerHeight]) rotate([90, 0, 90])
|
||||||
|
tenon(verticalTenonDims);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// mortices for joining to piece F
|
||||||
|
translate([tenonZOffset, y*0.3, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
translate([tenonZOffset, y*0.8, 0]) rotate([90, 0, 90])
|
||||||
|
morticeBlank(verticalTenonDims, morticeClearance);
|
||||||
|
|
||||||
|
// mortice for joining to piece G
|
||||||
|
translate([tenonZOffset, 0, drawerHeight/2]) mirror([0, 0, 1])
|
||||||
|
rotate([0, 90, 00]) tenon(tenonDims);
|
||||||
|
|
||||||
|
// piece label
|
||||||
|
translate([0.4, 2, 2]) rotate([90, 0, -90]) tally(8, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mortice and tenon test pieces
|
||||||
|
// rotate([0, 90, 0]) union() {
|
||||||
|
// cube([10, 16, wallThickness]);
|
||||||
|
// translate([2, 16, tenonZOffset]) tenon(tenonDims);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// translate([10, 0, 0]) rotate([0, 90, 0]) difference() {
|
||||||
|
// cube([10, 16, wallThickness]);
|
||||||
|
// translate([2 - 0.1, 16 - 0.1, tenonZOffset - 0.1])
|
||||||
|
// mirror([0, 1, 0]) morticeBlank(tenonDims, morticeClearance);
|
||||||
|
// }
|
||||||
|
|
||||||
|
module completeBox(gap = 10, cutWeight = true) {
|
||||||
|
|
||||||
|
// vertical layers
|
||||||
|
for (i = [0:2]) {
|
||||||
|
z = i * (wallThickness + 1.5*gap + drawerHeight);
|
||||||
|
translate([0, 0, z]) pieceA(cutWeight);
|
||||||
|
translate([x1 + gap, 0, z]) pieceB(cutWeight);
|
||||||
|
translate([0, y + gap, z]) pieceC(cutWeight);
|
||||||
|
translate([x1 + gap, y + gap, z]) pieceD(cutWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower box walls
|
||||||
|
for (i = [0:2]) {
|
||||||
|
x = i * (wallThickness + drawerWidth) +
|
||||||
|
(i == 2 ? gap : 0);
|
||||||
|
|
||||||
|
translate([x, 0, wallThickness + gap]) pieceE(cutWeight);
|
||||||
|
translate([x, y + gap, wallThickness + gap]) pieceF(cutWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// upper box walls
|
||||||
|
for (i = [0:2]) {
|
||||||
|
x = i * (wallThickness + drawerWidth) +
|
||||||
|
(i == 2 ? gap : 0);
|
||||||
|
|
||||||
|
translate([x, 0, drawerHeight + 2*wallThickness + 2*gap]) pieceG(cutWeight);
|
||||||
|
translate([x, y + gap, drawerHeight + 2*wallThickness + 2*gap]) pieceH(cutWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module printStack() {
|
||||||
|
for (i = [0:2]) {
|
||||||
|
translate([0, 0, i * (wallThickness + 0.4)]) pieceA();
|
||||||
|
translate([0, 0, (i+3) * (wallThickness + 0.4)]) pieceC();
|
||||||
|
translate([0, 0, (i+6) * (wallThickness + 0.4)]) pieceB();
|
||||||
|
translate([0, 0, (i+9) * (wallThickness + 0.4)]) pieceD();
|
||||||
|
|
||||||
|
translate([
|
||||||
|
0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
i * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceE();
|
||||||
|
|
||||||
|
translate([0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
(i+3) * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceF();
|
||||||
|
|
||||||
|
translate([
|
||||||
|
0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
(i+6) * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceG();
|
||||||
|
|
||||||
|
translate([
|
||||||
|
0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
(i+9) * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceH();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module testStack() {
|
||||||
|
for (i = [0:2]) {
|
||||||
|
translate([0, 0, i * (wallThickness + 0.4)]) pieceA();
|
||||||
|
translate([0, 0, (i+3) * (wallThickness + 0.4)]) pieceB();
|
||||||
|
|
||||||
|
translate([
|
||||||
|
0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
i * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceE();
|
||||||
|
|
||||||
|
translate([0,
|
||||||
|
y + drawerHeight +throughTenonDims[1] + 4,
|
||||||
|
(i+3) * (wallThickness + 0.4) + wallThickness])
|
||||||
|
rotate([90, 90, 0]) pieceF();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completeBox(gap = 10, cutWeight = false);
|
||||||
|
// testStack();
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,632 @@
|
|||||||
|
include <./constants.scad>
|
||||||
|
include <../lib/metric-machine-screws.scad>
|
||||||
|
include <../lib/chamfered-cube.scad>
|
||||||
|
include <../lib/rounded-cube.scad>
|
||||||
|
|
||||||
|
// all measurements in mm
|
||||||
|
$fn=128;
|
||||||
|
ep = 0.01;
|
||||||
|
clipThickness = boardThickness + 2*feltThickness;
|
||||||
|
clipWallThickness = 4;
|
||||||
|
clipFlangeLength = 24;
|
||||||
|
clipFlangeWidth = 16;
|
||||||
|
drawerSideOffset = 2*feltThickness + boardThickness;
|
||||||
|
|
||||||
|
// measurements for the wooden panels to cut:
|
||||||
|
//
|
||||||
|
// ───────────── - top board (A)
|
||||||
|
// │ │ │
|
||||||
|
// │───────────│
|
||||||
|
// │ │ │
|
||||||
|
// │───────────│
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// top board: 320.0 x 370.0
|
||||||
|
// bottom board: 305.6 x 370.0 (320 - 2*4.7 - 2*2.5) x 370
|
||||||
|
// side boards: 152.8 x 370.0 (160 - 4.7 - 2.5) x 370
|
||||||
|
// inner boards: 70.45 x 370.0 ((160 - 3*4.7 - 2*2.5)/2) x 370
|
||||||
|
//
|
||||||
|
|
||||||
|
function drawerWidth(boxDims) = (boxDims[0] - 3*boardThickness - 4*feltThickness)/2 + 2;
|
||||||
|
function drawerHeight(boxDims) = (boxDims[2] - 3*boardThickness - 4*feltThickness)/2;
|
||||||
|
|
||||||
|
module fastenerBlank() {
|
||||||
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
m3Nut(h=2.41);
|
||||||
|
|
||||||
|
translate([0, 2.4, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
m3Nut(h=2.41);
|
||||||
|
|
||||||
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d = 3.2, center = false, $fn=128,
|
||||||
|
h = 0.2 + 2 * clipWallThickness + boardThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
module dowelBlank() {
|
||||||
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d = 3.175, center = false, $fn=128,
|
||||||
|
h = 0.2 + 2 * clipWallThickness + boardThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
module cornerClipA() {
|
||||||
|
difference() {
|
||||||
|
cube([clipFlangeLength, clipFlangeLength, clipFlangeLength]);
|
||||||
|
|
||||||
|
translate([clipWallThickness, clipWallThickness, clipWallThickness])
|
||||||
|
union() {
|
||||||
|
cube([clipFlangeLength, boardThickness, clipFlangeLength]);
|
||||||
|
cube([boardThickness, clipFlangeLength, clipFlangeLength]);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([
|
||||||
|
boardThickness + 2*clipWallThickness,
|
||||||
|
boardThickness + 2*clipWallThickness,
|
||||||
|
-1 ])
|
||||||
|
cube([clipFlangeLength, clipFlangeLength, clipFlangeLength + 2]);
|
||||||
|
|
||||||
|
for (i = [-1, 0]) {
|
||||||
|
rotate([0, 0, i * 180])
|
||||||
|
mirror([i * 1, i * 1, 0])
|
||||||
|
translate([
|
||||||
|
clipFlangeLength - clipWallThickness,
|
||||||
|
0,
|
||||||
|
clipFlangeLength - clipWallThickness])
|
||||||
|
dowelBlank();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module cornerClip() {
|
||||||
|
difference() {
|
||||||
|
cube([clipThickness, clipThickness, clipThickness]);
|
||||||
|
|
||||||
|
translate([feltThickness, feltThickness, feltThickness])
|
||||||
|
cube([boardThickness, clipThickness, clipThickness]);
|
||||||
|
|
||||||
|
translate([feltThickness, feltThickness, feltThickness])
|
||||||
|
cube([clipThickness, boardThickness, clipThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module sideClipA() {
|
||||||
|
translate([clipFlangeLength, 0, 0])
|
||||||
|
difference() {
|
||||||
|
translate([-clipFlangeLength, 0, 0])
|
||||||
|
cube([2 * clipFlangeLength, clipFlangeLength, clipFlangeLength + boardThickness]);
|
||||||
|
|
||||||
|
translate([0, clipWallThickness, clipWallThickness])
|
||||||
|
union() {
|
||||||
|
translate([-0.1 - clipFlangeLength, 0, 0])
|
||||||
|
cube([2*clipFlangeLength + 0.2, clipFlangeLength, boardThickness]);
|
||||||
|
|
||||||
|
translate([-boardThickness/2, 0, 0])
|
||||||
|
cube([boardThickness, clipFlangeLength, clipFlangeLength + boardThickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [0, 1]) {
|
||||||
|
mirror([i, 0, 0])
|
||||||
|
translate([
|
||||||
|
clipWallThickness + boardThickness/2,
|
||||||
|
-0.1,
|
||||||
|
2*clipWallThickness + boardThickness])
|
||||||
|
cube(clipFlangeLength+0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [0:2]) {
|
||||||
|
translate([0, 0, boardThickness/2 + clipWallThickness])
|
||||||
|
rotate([0, i*-90, 0])
|
||||||
|
translate([
|
||||||
|
clipFlangeLength - 2*clipWallThickness,
|
||||||
|
clipFlangeLength - 2*clipWallThickness,
|
||||||
|
-boardThickness/2 - clipWallThickness])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
dowelBlank();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module sideClip() {
|
||||||
|
difference() {
|
||||||
|
cube([clipThickness, 2 * clipThickness, clipThickness]);
|
||||||
|
|
||||||
|
translate([-0.1, feltThickness, feltThickness])
|
||||||
|
cube([clipThickness + 0.2, boardThickness, clipThickness]);
|
||||||
|
|
||||||
|
translate([feltThickness, feltThickness, feltThickness])
|
||||||
|
cube([boardThickness, 2 * clipThickness, clipThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module crossClipA() {
|
||||||
|
cutoutLength = 2*clipFlangeLength + boardThickness;
|
||||||
|
//translate([cutoutLength/2, 0, cutoutLength/2])
|
||||||
|
difference() {
|
||||||
|
translate([-cutoutLength/2, 0, -cutoutLength/2])
|
||||||
|
cube([cutoutLength, clipFlangeLength, cutoutLength]);
|
||||||
|
|
||||||
|
translate([-cutoutLength/2-0.1, clipWallThickness, -boardThickness/2])
|
||||||
|
cube([2*clipFlangeLength + boardThickness + 0.2, clipFlangeLength, boardThickness]);
|
||||||
|
|
||||||
|
translate([-boardThickness/2, clipWallThickness, -cutoutLength/2-0.1])
|
||||||
|
cube([boardThickness, clipFlangeLength, 2*clipFlangeLength + boardThickness + 0.2]);
|
||||||
|
|
||||||
|
for (i = [0:3]) {
|
||||||
|
rotate([0, i*90, 0])
|
||||||
|
translate([
|
||||||
|
clipWallThickness + boardThickness/2,
|
||||||
|
-0.1,
|
||||||
|
clipWallThickness + boardThickness/2])
|
||||||
|
cube(clipFlangeLength+0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [0:3]) {
|
||||||
|
rotate([0, i*-90, 0])
|
||||||
|
translate([clipFlangeLength - clipWallThickness, clipFlangeLength - 1.5*clipWallThickness, -clipWallThickness - boardThickness/2])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
dowelBlank();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module printableSet() {
|
||||||
|
difference() {
|
||||||
|
translate([0, 0, -1.4])
|
||||||
|
union() {
|
||||||
|
for (i = [0:7])
|
||||||
|
translate([i * (clipThickness + 2), clipThickness, 0])
|
||||||
|
rotate([45, 0, 0])
|
||||||
|
cornerClip();
|
||||||
|
|
||||||
|
for (i = [0:7])
|
||||||
|
translate([i * (clipThickness + 2), 3 * clipThickness, 0])
|
||||||
|
rotate([0, 0, 0])
|
||||||
|
sideClip();
|
||||||
|
|
||||||
|
for (i = [0:1])
|
||||||
|
translate([i * (2 * clipThickness + 2), 7 * clipThickness, 0])
|
||||||
|
rotate([45, 0, 0])
|
||||||
|
crossClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([-1, -1, -1.4]) cube([100, 100, 1.4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module printableSetA() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
translate([20, 0, -4.82])
|
||||||
|
for (i = [0:7])
|
||||||
|
translate([i%4 * (clipFlangeLength + 16), 2*floor(i/4) * clipFlangeLength, 0])
|
||||||
|
rotate([45, -45, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
|
translate([0, 0, -2])
|
||||||
|
for (i = [0:7])
|
||||||
|
translate([i%4 * (2*clipFlangeLength + 16), (4 + 2*floor(i/4)) * clipFlangeLength, 0])
|
||||||
|
rotate([45, 0, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
|
for (i = [0:1])
|
||||||
|
translate([30 + i * (2 * clipFlangeLength + 16), 8.5 * clipFlangeLength, 0])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
crossClipA();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([-20, -20, -10]) cube([500, 300, 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module containingBox(boxDims) {
|
||||||
|
difference() {
|
||||||
|
cube([boxDims[0] + 12, boxDims[1], boxDims[2] + 12]);
|
||||||
|
translate([6, -0.1, 6])
|
||||||
|
cube([boxDims[0], boxDims[1] + 0.2, boxDims[2]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module feltClearanceBox(boxDims) {
|
||||||
|
difference() {
|
||||||
|
cube([boxDims[0], boxDims[1], boxDims[2]]);
|
||||||
|
|
||||||
|
translate([feltThickness, -0.1, feltThickness])
|
||||||
|
cube([boxDims[0] - 2*feltThickness, boxDims[1] + 0.2, boxDims[2] - 2*feltThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module topPanel(boxDims) {
|
||||||
|
difference() {
|
||||||
|
color("BurlyWood") cube([boxDims[0], boxDims[1], boardThickness]);
|
||||||
|
color("black") translate([10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", size=16, "top - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module sidePanel(boxDims) {
|
||||||
|
difference() {
|
||||||
|
color("Wheat") cube([boxDims[2] - boardThickness, boxDims[1], boardThickness]);
|
||||||
|
color("black") rotate([0, 0, -90]) translate([-10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", halign = "right", size=16, "side - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module innerPanel(boxDims) {
|
||||||
|
difference() {
|
||||||
|
color("BlanchedAlmond") cube([(boxDims[2] - 3*boardThickness) / 2, boxDims[1], boardThickness]);
|
||||||
|
color("black") rotate([0, 0, -90]) translate([-10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", halign = "right", size=16, "inner panel - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bottomPanel(boxDims) {
|
||||||
|
difference() {
|
||||||
|
color ("Tan") cube([boxDims[0] - 2*boardThickness, boxDims[1], boardThickness]);
|
||||||
|
color("black") translate([10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", size=16, "bottom - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module drawerFacePlateBlank(boxDims) {
|
||||||
|
size = [boxDims[0]/2 - 1, boxDims[2]/2 - 1, 8];
|
||||||
|
chamfer = 4;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
roundedCube(size, [1, 1, 1]);
|
||||||
|
|
||||||
|
// front face chamfers
|
||||||
|
for (i = [1,3]) {
|
||||||
|
// X-axis
|
||||||
|
translate([-ep, size[1] * floor(i/2), size[2] * (i%2) - chamfer])
|
||||||
|
rotate([45, 0, 0]) cube([size[0] + 2*ep, 1.414*chamfer, 1.414*chamfer]);
|
||||||
|
|
||||||
|
// Y-axis
|
||||||
|
translate([size[0] * floor(i/2) - chamfer, -ep, size[2] * (i%2)])
|
||||||
|
rotate([0, 45, 0]) cube([1.414*chamfer, size[1] + 2*ep, 1.414*chamfer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameplate cutouts
|
||||||
|
translate([(boxDims[0]/2 - 76)/2, 30, 7]) cube([76, 36, 1 + ep]);
|
||||||
|
translate([(boxDims[0]/2 - 76)/2, 30 + 36, 7])
|
||||||
|
rotate([30, 0, 0]) cube([76, 4, 4]);
|
||||||
|
|
||||||
|
// screw holes
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
color("red")
|
||||||
|
translate([boxDims[0]/4 + i*20, 16, -ep]) cylinder(d=3.4, h=8+2*ep);
|
||||||
|
translate([boxDims[0]/4 + i*20, 16, -ep]) cylinder(d=6.2, h=3+ep);
|
||||||
|
//translate([boxDims[0]/4 + i*20, 16, 3 - ep]) cylinder(d1=6.2, d2=3.4, h=1+2*ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module lowerLeftDrawerFace(outerDims, boxDims) {
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
difference() {
|
||||||
|
drawerFacePlateBlank(outerDims);
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([outerDims[0]/4 + 6, outerDims[2]/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "LL");
|
||||||
|
|
||||||
|
// horizontal board recess
|
||||||
|
translate([drawerSideOffset, drawerSideOffset, -ep])
|
||||||
|
cube([drawerWidth(boxDims), boardThickness, 4+ep]);
|
||||||
|
|
||||||
|
// vertical board recesses
|
||||||
|
translate([drawerSideOffset, drawerSideOffset + boardThickness - ep, -ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
translate([
|
||||||
|
drawerSideOffset + drawerWidth(boxDims) - boardThickness,
|
||||||
|
drawerSideOffset + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module lowerRightDrawerFace(outerDims, boxDims) {
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
difference() {
|
||||||
|
translate([1, 0, 0])
|
||||||
|
drawerFacePlateBlank(outerDims);
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([outerDims[0]/4 + 6, outerDims[2]/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "LR");
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// horizontal board recess
|
||||||
|
translate([feltThickness + boardThickness/2, drawerSideOffset, -ep])
|
||||||
|
cube([drawerWidth(boxDims), boardThickness, 4+ep]);
|
||||||
|
|
||||||
|
// vertical board recesses
|
||||||
|
translate([feltThickness + boardThickness/2, drawerSideOffset + boardThickness - ep, -ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
translate([
|
||||||
|
feltThickness + boardThickness/2 + drawerWidth(boxDims) - boardThickness,
|
||||||
|
feltThickness + boardThickness/2 + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate([-1, -1, 4-ep]) cube([outerDims[0], outerDims[2], 5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module upperRightDrawerFace(outerDims, boxDims) {
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
difference() {
|
||||||
|
translate([1, 0, 0])
|
||||||
|
drawerFacePlateBlank(outerDims);
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([outerDims[0]/4 + 6, outerDims[2]/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "UR");
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// horizontal board recess
|
||||||
|
translate([feltThickness + boardThickness/2, feltThickness + boardThickness/2, -ep])
|
||||||
|
cube([drawerWidth(boxDims), boardThickness, 4+ep]);
|
||||||
|
|
||||||
|
// vertical board recesses
|
||||||
|
translate([
|
||||||
|
feltThickness + boardThickness/2,
|
||||||
|
feltThickness + boardThickness/2 + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
translate([
|
||||||
|
feltThickness + boardThickness/2 + drawerWidth(boxDims) - boardThickness,
|
||||||
|
feltThickness + boardThickness/2 + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate([-1, -1, 4-ep]) cube([outerDims[0], outerDims[2], 5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module upperLeftDrawerFace(outerDims, boxDims) {
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
difference() {
|
||||||
|
drawerFacePlateBlank(outerDims);
|
||||||
|
|
||||||
|
// label
|
||||||
|
color("blue")
|
||||||
|
translate([boxDims[0]/4 + 6, boxDims[2]/4 - 6, -0.2]) mirror([1, 0, 0])
|
||||||
|
linear_extrude(0.4) text(font="Iosevka", size=6, "UL");
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// horizontal board recess
|
||||||
|
translate([drawerSideOffset, feltThickness + boardThickness/2, -ep])
|
||||||
|
cube([drawerWidth(boxDims), boardThickness, 4+ep]);
|
||||||
|
|
||||||
|
// vertical board recesses
|
||||||
|
translate([
|
||||||
|
drawerSideOffset,
|
||||||
|
feltThickness + boardThickness/2 + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
translate([
|
||||||
|
drawerSideOffset + drawerWidth(boxDims) - boardThickness,
|
||||||
|
feltThickness + boardThickness/2 + boardThickness - ep,
|
||||||
|
-ep])
|
||||||
|
cube([boardThickness, drawerHeight(boxDims) - boardThickness + ep, 4+ep]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate([-1, -1, 4-ep]) cube([outerDims[0], outerDims[2], 5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module drawerHandle() {
|
||||||
|
handleLen = 64;
|
||||||
|
//difference() {
|
||||||
|
chamferedCube([handleLen, 12, 12], chamfer=3);
|
||||||
|
|
||||||
|
// screw holes
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
difference() {
|
||||||
|
translate([handleLen/2 + i*20, 6, 12-ep]) cylinder(d=6, h=8 + ep);
|
||||||
|
translate([handleLen/2 + i*20, 6, 12-ep]) cylinder(d=2.8, h=8 + 2*ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module drawerBottom(boxDims, includeClips = false) {
|
||||||
|
difference() {
|
||||||
|
color ("Tan")
|
||||||
|
cube([
|
||||||
|
drawerWidth(boxDims),
|
||||||
|
boxDims[1], boardThickness]);
|
||||||
|
color("black") translate([10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", size=16, "drawer bottom - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module drawerSide(boxDims, includeClips = false) {
|
||||||
|
difference() {
|
||||||
|
color("Wheat")
|
||||||
|
cube([
|
||||||
|
drawerHeight(boxDims) - boardThickness, boxDims[1], boardThickness]);
|
||||||
|
color("black") rotate([0, 0, -90]) translate([-10, 10, boardThickness - 1]) linear_extrude(1.1)
|
||||||
|
text(font="Iosevka", halign = "right", size=16, "drawer side - plywood");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module assembled(outerBoxDims, includeClips = false) {
|
||||||
|
translate([-6, 0, -6])
|
||||||
|
color("darkgrey")
|
||||||
|
containingBox(outerBoxDims);
|
||||||
|
|
||||||
|
color("brown")
|
||||||
|
feltClearanceBox(outerBoxDims);
|
||||||
|
|
||||||
|
clipOffset = includeClips ? clipWallThickness : 0;
|
||||||
|
|
||||||
|
innerBoxDims = includeClips ?
|
||||||
|
[ outerBoxDims[0] - 2*feltThickness - 2*clipWallThickness,
|
||||||
|
outerBoxDims[1] - 2*clipWallThickness,
|
||||||
|
outerBoxDims[2] - 2*feltThickness - 2*clipWallThickness ] :
|
||||||
|
[ outerBoxDims[0] - 2*feltThickness,
|
||||||
|
outerBoxDims[1],
|
||||||
|
outerBoxDims[2] - 2*feltThickness ];
|
||||||
|
|
||||||
|
translate([feltThickness, 0, feltThickness])
|
||||||
|
union() {
|
||||||
|
translate([ clipOffset, clipOffset, clipOffset])
|
||||||
|
union() {
|
||||||
|
translate([0, 0, innerBoxDims[2] - boardThickness]) topPanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([boardThickness, 0, 0]) rotate([0, -90, 0]) sidePanel(innerBoxDims);
|
||||||
|
translate([innerBoxDims[0], 0, 0]) rotate([0, -90, 0]) sidePanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([(innerBoxDims[0] + boardThickness)/2, 0, boardThickness]) rotate([0, -90, 0]) innerPanel(innerBoxDims);
|
||||||
|
translate([(innerBoxDims[0] + boardThickness)/2, 0, 2*boardThickness + (innerBoxDims[2] - 3*boardThickness)/2]) rotate([0, -90, 0]) innerPanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([boardThickness, 0, boardThickness + (innerBoxDims[2] - 3*boardThickness)/2]) bottomPanel(innerBoxDims);
|
||||||
|
translate([boardThickness, 0, 0]) bottomPanel(innerBoxDims);
|
||||||
|
|
||||||
|
// drawers
|
||||||
|
translate([boardThickness + feltThickness, 0, boardThickness + feltThickness])
|
||||||
|
for (i = [0:3]) {
|
||||||
|
// felt box
|
||||||
|
color("brown")
|
||||||
|
translate([
|
||||||
|
(i%2)*(innerBoxDims[0]-boardThickness)/2 - feltThickness,
|
||||||
|
0.01,
|
||||||
|
floor(i/2)*(innerBoxDims[2]-boardThickness)/2 - feltThickness])
|
||||||
|
feltClearanceBox([
|
||||||
|
innerBoxDims[0]/2 - 1.5*boardThickness,
|
||||||
|
innerBoxDims[1],
|
||||||
|
innerBoxDims[2]/2 - 1.5*boardThickness]);
|
||||||
|
|
||||||
|
//bottom
|
||||||
|
translate([
|
||||||
|
(i%2)*(innerBoxDims[0]-boardThickness)/2,
|
||||||
|
0,
|
||||||
|
floor(i/2)*(innerBoxDims[2]-boardThickness)/2])
|
||||||
|
drawerBottom(innerBoxDims);
|
||||||
|
|
||||||
|
// side
|
||||||
|
for (j = [0,1]) {
|
||||||
|
translate([
|
||||||
|
boardThickness + (i%2)*(innerBoxDims[0]-boardThickness)/2 +
|
||||||
|
j*(drawerWidth(innerBoxDims) - boardThickness),
|
||||||
|
0,
|
||||||
|
boardThickness + floor(i/2)*(innerBoxDims[2]-boardThickness)/2])
|
||||||
|
rotate([0, -90, 0]) drawerSide(innerBoxDims);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([-feltThickness, 0, -feltThickness])
|
||||||
|
lowerLeftDrawerFace(outerBoxDims, innerBoxDims);
|
||||||
|
|
||||||
|
translate([outerBoxDims[0]/2 - feltThickness, 0, -feltThickness])
|
||||||
|
lowerRightDrawerFace(outerBoxDims, innerBoxDims);
|
||||||
|
|
||||||
|
translate([-feltThickness, 0, outerBoxDims[2] / 2 - feltThickness])
|
||||||
|
upperLeftDrawerFace(outerBoxDims, innerBoxDims);
|
||||||
|
|
||||||
|
translate([outerBoxDims[0]/2 - feltThickness, 0, outerBoxDims[2] / 2 - feltThickness])
|
||||||
|
upperRightDrawerFace(outerBoxDims, innerBoxDims);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeClips) {
|
||||||
|
for(i = [0:1]) {
|
||||||
|
translate([0, i * (2 * clipWallThickness + innerBoxDims[1]), 0])
|
||||||
|
mirror([0, i * 1, 0])
|
||||||
|
union() {
|
||||||
|
rotate([-90, -90, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
|
translate([0, 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
|
rotate([-90, 0, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
|
translate([2 * clipWallThickness + innerBoxDims[0], 0, 0])
|
||||||
|
rotate([-90, -180, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
|
translate([2 * clipWallThickness + innerBoxDims[0], 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
|
rotate([-90, -270, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
|
translate([clipWallThickness + innerBoxDims[0]/2 - clipFlangeLength, 0, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
|
translate([clipWallThickness + innerBoxDims[0]/2 + clipFlangeLength, 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
|
rotate([0, 180, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
|
translate([0, 0, innerBoxDims[2]/2 + clipFlangeLength + clipWallThickness])
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
|
translate([innerBoxDims[0] + 2*clipWallThickness, 0, innerBoxDims[2]/2 - clipFlangeLength + clipWallThickness])
|
||||||
|
rotate([0, 270, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
|
translate([innerBoxDims[0]/2 + clipWallThickness, 0, innerBoxDims[2]/2 + clipWallThickness])
|
||||||
|
crossClipA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module allCutParts(outerBoxDims, includeClips = false) {
|
||||||
|
innerBoxDims = includeClips ?
|
||||||
|
[ outerBoxDims[0] - 2*feltThickness - 2*clipWallThickness,
|
||||||
|
outerBoxDims[1] - 2*clipWallThickness,
|
||||||
|
outerBoxDims[2] - 2*feltThickness - 2*clipWallThickness ] :
|
||||||
|
[ outerBoxDims[0] - 2*feltThickness,
|
||||||
|
outerBoxDims[1],
|
||||||
|
outerBoxDims[2] - 2*feltThickness ];
|
||||||
|
|
||||||
|
topPanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([innerBoxDims[0] + 8, 0, 0])
|
||||||
|
bottomPanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([0, innerBoxDims[1] + 8, 0])
|
||||||
|
sidePanel(innerBoxDims);
|
||||||
|
|
||||||
|
translate([innerBoxDims[2], innerBoxDims[1] + 8, 0])
|
||||||
|
innerPanel(innerBoxDims);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
shelfDims = [shelfWidth, shelfDepth, shelfHeight];
|
||||||
|
//assembled(shelfDims);
|
||||||
|
|
||||||
|
//translate([shelfWidth + 20, 0, 0])
|
||||||
|
//allCutParts(shelfDims);
|
||||||
|
|
||||||
|
//translate([300, shelfDepth + 40, 0])
|
||||||
|
//rotate([0, 0, 90])
|
||||||
|
//printableSetA();
|
||||||
|
|
||||||
|
innerBoxDims =
|
||||||
|
[ shelfDims[0] - 2*feltThickness,
|
||||||
|
shelfDims[1],
|
||||||
|
shelfDims[2] - 2*feltThickness ];
|
||||||
|
|
||||||
|
|
||||||
|
//drawerBottom(innerBoxDims);
|
||||||
|
//lowerLeftDrawerFace(shelfDims, innerBoxDims);
|
||||||
|
//lowerRightDrawerFace(shelfDims, innerBoxDims);
|
||||||
|
//upperLeftDrawerFace(shelfDims, innerBoxDims);
|
||||||
|
upperRightDrawerFace(shelfDims, innerBoxDims);
|
||||||
|
//drawerHandle();
|
||||||
@@ -3,20 +3,16 @@ module chamferedCube(size = [1, 1, 1], chamfer = 1) {
|
|||||||
difference() {
|
difference() {
|
||||||
cube(size);
|
cube(size);
|
||||||
|
|
||||||
// X-axis
|
|
||||||
for (i = [0:3]) {
|
for (i = [0:3]) {
|
||||||
|
// X-axis
|
||||||
translate([-ep, size[1] * floor(i/2), size[2] * (i%2) - chamfer])
|
translate([-ep, size[1] * floor(i/2), size[2] * (i%2) - chamfer])
|
||||||
rotate([45, 0, 0]) cube([size[0] + 2*ep, 1.414*chamfer, 1.414*chamfer]);
|
rotate([45, 0, 0]) cube([size[0] + 2*ep, 1.414*chamfer, 1.414*chamfer]);
|
||||||
}
|
|
||||||
|
|
||||||
// Y-axis
|
// Y-axis
|
||||||
for (i = [0:3]) {
|
|
||||||
translate([size[0] * floor(i/2) - chamfer, -ep, size[2] * (i%2)])
|
translate([size[0] * floor(i/2) - chamfer, -ep, size[2] * (i%2)])
|
||||||
rotate([0, 45, 0]) cube([1.414*chamfer, size[1] + 2*ep, 1.414*chamfer]);
|
rotate([0, 45, 0]) cube([1.414*chamfer, size[1] + 2*ep, 1.414*chamfer]);
|
||||||
}
|
|
||||||
|
|
||||||
// Z-axis
|
// Z-axis
|
||||||
for (i = [0:3]) {
|
|
||||||
translate([size[0] * floor(i/2), size[1] * (i%2) - chamfer, -ep])
|
translate([size[0] * floor(i/2), size[1] * (i%2) - chamfer, -ep])
|
||||||
rotate([0, 0, 45]) cube([1.414*chamfer, 1.414*chamfer, size[2] + 2*ep]);
|
rotate([0, 0, 45]) cube([1.414*chamfer, 1.414*chamfer, size[2] + 2*ep]);
|
||||||
}
|
}
|
||||||
|
|||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
// Create a tenon with chamfered edges on the front face. The tenon is facing
|
||||||
|
// the positive Y direction. It is offset by -0.01 in Y to make it easy to
|
||||||
|
// ensure that it intersects with the main body it is attached to.
|
||||||
|
module tenon(dims) {
|
||||||
|
translate([0, -0.01, 0])
|
||||||
|
difference() {
|
||||||
|
cube([dims[0], dims[1] + 0.01, dims[2]]);
|
||||||
|
|
||||||
|
// chamfers
|
||||||
|
color("blue") union() {
|
||||||
|
translate([-0.5, dims[1] + 0.1, dims[2] - 1.1]) rotate([45, 0, 0]) cube([dims[0] + 1, 2, 2]);
|
||||||
|
translate([-0.5, dims[1] + 0.1, -1.7]) rotate([45, 0, 0]) cube([dims[0] + 1, 2, 2]);
|
||||||
|
translate([-0.4, dims[1]-1, -0.5]) rotate([0, 0, 45]) cube([2, 2, dims[2] + 1]);
|
||||||
|
translate([dims[0]+0.4, dims[1]-1, -0.5]) rotate([0, 0, 45]) cube([2, 2, dims[2] + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module morticeBlank(dims, clearance = 0) {
|
||||||
|
translate([-clearance, -clearance-0.01, -clearance])
|
||||||
|
cube([dims[0] + 2 * clearance, dims[1] + 2 * clearance+0.01, dims[2] + 2 * clearance]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module rectDowel(dim = [6, 16, 3]) {
|
||||||
|
// rectangular dowel
|
||||||
|
translate([-dim[0]/2, -dim[1]/2, -dim[2]/2])
|
||||||
|
cube(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cube with a mortice cut out of the center for a snap fit tenon.
|
||||||
|
// The mortice is aligned on the Y-axis: the dimension in X determines the
|
||||||
|
// width of the piece and mortice, the dimension in Y determines the depth or
|
||||||
|
// length of the piece, and the dimension in Z determines the height thickness.
|
||||||
|
//
|
||||||
|
// The morticeDim dimensions will be enlarged slightly to allow for adequate
|
||||||
|
// fitment of the tenon based on the clearance (defaults to 0.2).
|
||||||
|
module morticeWithSnap(
|
||||||
|
dim = [10, 20, 5],
|
||||||
|
morticeDim = [6, 8, 3],
|
||||||
|
snapDepth = 2,
|
||||||
|
snapHeight = 1,
|
||||||
|
clearance = 0.3) {
|
||||||
|
|
||||||
|
mDim = [morticeDim[0] + 2*clearance,
|
||||||
|
morticeDim[1] + clearance,
|
||||||
|
morticeDim[2] + clearance];
|
||||||
|
difference() {
|
||||||
|
// block
|
||||||
|
translate([-dim[0]/2, 0, -dim[2]/2]) cube(dim);
|
||||||
|
|
||||||
|
// cutout
|
||||||
|
translate([-mDim[0]/2, -clearance, -mDim[2]/2]) union() {
|
||||||
|
cube(mDim); // mortice cutout
|
||||||
|
|
||||||
|
// snap fit cutout
|
||||||
|
translate([0, morticeDim[1] - snapDepth, morticeDim[2] + clearance - 0.01])
|
||||||
|
cube([morticeDim[0] + clearance,
|
||||||
|
snapDepth + clearance,
|
||||||
|
snapHeight + clearance + 0.01]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cube with a tenon and cantilevered snap fit on one side.
|
||||||
|
// The tenon is aligned on the Y-axis: the dimension in X determines the
|
||||||
|
// width of the piece and tenon, the dimension in Y determines the depth or
|
||||||
|
// length of the piece, and the dimension in Z determines the height thickness.
|
||||||
|
module tenonWithSnap(
|
||||||
|
dim = [10, 20, 5],
|
||||||
|
tenonDim = [6, 8, 3],
|
||||||
|
snapDepth = 2,
|
||||||
|
snapHeight = 1) {
|
||||||
|
|
||||||
|
// block
|
||||||
|
translate([-dim[0]/2, 0, -dim[2]/2]) cube(dim);
|
||||||
|
|
||||||
|
// tenon
|
||||||
|
translate([-tenonDim[0]/2, dim[1] - 0.01, -tenonDim[2]/2]) union() {
|
||||||
|
// main tenon body
|
||||||
|
tenonFlexArmThickness = min(tenonDim[2] / 2, 1);
|
||||||
|
color("blue") translate([0, 0, tenonDim[2] - tenonFlexArmThickness])
|
||||||
|
cube([tenonDim[0], tenonDim[1], tenonFlexArmThickness]);
|
||||||
|
|
||||||
|
// fillet on front edge of tenon
|
||||||
|
/*
|
||||||
|
translate([0, tenonDim[1] / 4 - 0.05, tenonDim[2] / 4 + 0.03])
|
||||||
|
difference() {
|
||||||
|
color("blue") cube([tenonDim[0], tenonDim[1] / 8, tenonDim[2] / 4]);
|
||||||
|
color("green") translate([tenonDim[0] /2, tenonDim[1]/8 - tenonDim[2]/16, 0]) rotate([0, 90, 0])
|
||||||
|
cylinder(r = tenonDim[2] / 4, h = tenonDim[0] + 0.02, center=true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 45-degree chamfer on top edges of tenon base (alignment feature)
|
||||||
|
difference() {
|
||||||
|
cube([tenonDim[0], tenonDim[1]*0.4, tenonDim[2]]);
|
||||||
|
translate([-0.01, tenonDim[1]*0.4, -tenonDim[2]/2]) rotate([45, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, tenonDim[1] / 4, tenonDim[2] / 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cantilevered snap fit
|
||||||
|
translate([0, tenonDim[1] - snapDepth, tenonDim[2] - 0.01])
|
||||||
|
difference() {
|
||||||
|
cube([tenonDim[0], snapDepth, snapHeight + 0.01]);
|
||||||
|
color("red") union() {
|
||||||
|
// front-edge chamfer
|
||||||
|
translate([-0.01, -snapDepth, snapHeight*0.66]) rotate([-10, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, snapDepth, snapHeight + 0.01]);
|
||||||
|
|
||||||
|
// back-edge chamfer
|
||||||
|
translate([-0.01, snapDepth, snapHeight / 8]) rotate([15, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, snapDepth, snapHeight + 0.01]);
|
||||||
|
|
||||||
|
// side chamfers
|
||||||
|
translate([-tenonDim[0]/4, 0, snapHeight*0.66]) rotate([0, 10, 0])
|
||||||
|
cube([tenonDim[0] / 4, snapDepth + 0.02, snapHeight]);
|
||||||
|
translate([tenonDim[0], 0, snapHeight*0.60]) rotate([0, -10, 0])
|
||||||
|
cube([tenonDim[0] / 4, snapDepth + 0.02, snapHeight]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the tail of a dovetail for a dovetail joint. The tail is oriented in
|
||||||
|
// the positive Y direction. It is exactly (tailHeight + 0.01) tall (in the Y
|
||||||
|
// direction) and positioned so that its base is at Y=-0.01 to make it easy to
|
||||||
|
// overlap with the main body it is attached to.
|
||||||
|
module dovetail(tailHeight, tailWidthMin, tailWidthMax, depth) {
|
||||||
|
angle = atan((tailWidthMax - tailWidthMin) / (2 * tailHeight));
|
||||||
|
|
||||||
|
translate([0, tailHeight, 0])
|
||||||
|
mirror([0, 1, 0])
|
||||||
|
difference() {
|
||||||
|
cube([tailWidthMax, tailHeight + 0.01, depth + 0.01]);
|
||||||
|
color("blue") translate([tailWidthMax, 0, -0.1]) rotate([0, 0, angle]) cube([tailWidthMax, tailHeight*2, depth+0.2]);
|
||||||
|
color("blue") rotate([0, 0, -angle]) translate([-tailWidthMax, 0, -0.1]) cube([tailWidthMax, tailHeight*2, depth+0.2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
module m3Nut(h = 2.4, clearance = 0, center=false) {
|
||||||
|
$fn=6;
|
||||||
|
cylinder(d=6.35 + 2*clearance, h=h, center=center);
|
||||||
|
}
|
||||||
|
|
||||||
|
module m4Nut(h = 3.2, clearance = 0, center=false) {
|
||||||
|
$fn=6;
|
||||||
|
cylinder(d=8.08 + 2*clearance, h=h, center=center);
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
module tenon(dims) {
|
||||||
|
translate([0, -0.01, 0])
|
||||||
|
difference() {
|
||||||
|
cube([dims[0], dims[1] + 0.01, dims[2]]);
|
||||||
|
|
||||||
|
// chamfers
|
||||||
|
color("blue") union() {
|
||||||
|
translate([-0.5, dims[1]*0.95, dims[2]*0.9]) rotate([45, 0, 0])
|
||||||
|
translate([0, 0, -dims[2]/2]) cube([dims[0] + 1, 2, 2]);
|
||||||
|
translate([-0.5, dims[1]*0.95, -dims[2]*0.8]) rotate([45, 0, 0])
|
||||||
|
translate([0, 0, -dims[2]/2]) cube([dims[0] + 1, 2, 2]);
|
||||||
|
translate([-0.4, dims[1]-1, -0.5]) rotate([0, 0, 45])
|
||||||
|
cube([2, 2, dims[2] + 1]);
|
||||||
|
translate([dims[0]+0.4, dims[1]-1, -0.5]) rotate([0, 0, 45])
|
||||||
|
cube([2, 2, dims[2] + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module morticeBlank(dims, clearance) {
|
||||||
|
translate([-clearance, -clearance-0.01, -clearance])
|
||||||
|
cube([dims[0] + 2 * clearance, dims[1] + 2 * clearance+0.01, dims[2] + 2 * clearance]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module rectDowel(dim = [6, 16, 3]) {
|
||||||
|
// rectangular dowel
|
||||||
|
translate([-dim[0]/2, -dim[1]/2, -dim[2]/2])
|
||||||
|
cube(dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cube with a mortice cut out of the center for a snap fit tenon.
|
||||||
|
// The mortice is aligned on the Y-axis: the dimension in X determines the
|
||||||
|
// width of the piece and mortice, the dimension in Y determines the depth or
|
||||||
|
// length of the piece, and the dimension in Z determines the height thickness.
|
||||||
|
//
|
||||||
|
// The morticeDim dimensions will be enlarged slightly to allow for adequate
|
||||||
|
// fitment of the tenon based on the clearance (defaults to 0.2).
|
||||||
|
module morticeWithSnap(
|
||||||
|
dim = [10, 20, 5],
|
||||||
|
morticeDim = [6, 8, 3],
|
||||||
|
snapDepth = 2,
|
||||||
|
snapHeight = 1,
|
||||||
|
clearance = 0.3) {
|
||||||
|
|
||||||
|
mDim = [morticeDim[0] + 2*clearance,
|
||||||
|
morticeDim[1] + clearance,
|
||||||
|
morticeDim[2] + clearance];
|
||||||
|
difference() {
|
||||||
|
// block
|
||||||
|
translate([-dim[0]/2, 0, -dim[2]/2]) cube(dim);
|
||||||
|
|
||||||
|
// cutout
|
||||||
|
translate([-mDim[0]/2, -clearance, -mDim[2]/2]) union() {
|
||||||
|
cube(mDim); // mortice cutout
|
||||||
|
|
||||||
|
// snap fit cutout
|
||||||
|
translate([0, morticeDim[1] - snapDepth, morticeDim[2] + clearance - 0.01])
|
||||||
|
cube([morticeDim[0] + clearance,
|
||||||
|
snapDepth + clearance,
|
||||||
|
snapHeight + clearance + 0.01]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cube with a tenon and cantilevered snap fit on one side.
|
||||||
|
// The tenon is aligned on the Y-axis: the dimension in X determines the
|
||||||
|
// width of the piece and tenon, the dimension in Y determines the depth or
|
||||||
|
// length of the piece, and the dimension in Z determines the height thickness.
|
||||||
|
module tenonWithSnap(
|
||||||
|
dim = [10, 20, 5],
|
||||||
|
tenonDim = [6, 8, 3],
|
||||||
|
snapDepth = 2,
|
||||||
|
snapHeight = 1) {
|
||||||
|
|
||||||
|
// block
|
||||||
|
translate([-dim[0]/2, 0, -dim[2]/2]) cube(dim);
|
||||||
|
|
||||||
|
// tenon
|
||||||
|
translate([-tenonDim[0]/2, dim[1] - 0.01, -tenonDim[2]/2]) union() {
|
||||||
|
// main tenon body
|
||||||
|
tenonFlexArmThickness = min(tenonDim[2] / 2, 1);
|
||||||
|
color("blue") translate([0, 0, tenonDim[2] - tenonFlexArmThickness])
|
||||||
|
cube([tenonDim[0], tenonDim[1], tenonFlexArmThickness]);
|
||||||
|
|
||||||
|
// fillet on front edge of tenon
|
||||||
|
/*
|
||||||
|
translate([0, tenonDim[1] / 4 - 0.05, tenonDim[2] / 4 + 0.03])
|
||||||
|
difference() {
|
||||||
|
color("blue") cube([tenonDim[0], tenonDim[1] / 8, tenonDim[2] / 4]);
|
||||||
|
color("green") translate([tenonDim[0] /2, tenonDim[1]/8 - tenonDim[2]/16, 0]) rotate([0, 90, 0])
|
||||||
|
cylinder(r = tenonDim[2] / 4, h = tenonDim[0] + 0.02, center=true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 45-degree chamfer on top edges of tenon base (alignment feature)
|
||||||
|
difference() {
|
||||||
|
cube([tenonDim[0], tenonDim[1]*0.4, tenonDim[2]]);
|
||||||
|
translate([-0.01, tenonDim[1]*0.4, -tenonDim[2]/2]) rotate([45, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, tenonDim[1] / 4, tenonDim[2] / 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cantilevered snap fit
|
||||||
|
translate([0, tenonDim[1] - snapDepth, tenonDim[2] - 0.01])
|
||||||
|
difference() {
|
||||||
|
cube([tenonDim[0], snapDepth, snapHeight + 0.01]);
|
||||||
|
color("red") union() {
|
||||||
|
// front-edge chamfer
|
||||||
|
translate([-0.01, -snapDepth, snapHeight*0.66]) rotate([-10, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, snapDepth, snapHeight + 0.01]);
|
||||||
|
|
||||||
|
// back-edge chamfer
|
||||||
|
translate([-0.01, snapDepth, snapHeight / 8]) rotate([15, 0, 0])
|
||||||
|
cube([tenonDim[0] + 0.02, snapDepth, snapHeight + 0.01]);
|
||||||
|
|
||||||
|
// side chamfers
|
||||||
|
translate([-tenonDim[0]/4, 0, snapHeight*0.66]) rotate([0, 10, 0])
|
||||||
|
cube([tenonDim[0] / 4, snapDepth + 0.02, snapHeight]);
|
||||||
|
translate([tenonDim[0], 0, snapHeight*0.60]) rotate([0, -10, 0])
|
||||||
|
cube([tenonDim[0] / 4, snapDepth + 0.02, snapHeight]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
module roundedCube(dims = [10, 10, 10], cornerRadii = [2, 2, 2]) {
|
||||||
|
innerDims = [
|
||||||
|
dims[0] - cornerRadii[0]*2,
|
||||||
|
dims[1] - cornerRadii[1]*2,
|
||||||
|
dims[2] - cornerRadii[2]*2 ];
|
||||||
|
|
||||||
|
// X-Y
|
||||||
|
translate(cornerRadii)
|
||||||
|
scale([cornerRadii[0], cornerRadii[1], 1])
|
||||||
|
cylinder(r=1, h = innerDims[2]);
|
||||||
|
translate([cornerRadii[0], cornerRadii[1] + innerDims[1], cornerRadii[2]])
|
||||||
|
scale([cornerRadii[0], cornerRadii[1], 1])
|
||||||
|
cylinder(r=1, h = innerDims[2]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1] + innerDims[1], cornerRadii[2]])
|
||||||
|
scale([cornerRadii[0], cornerRadii[1], 1])
|
||||||
|
cylinder(r=1, h = innerDims[2]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2]])
|
||||||
|
scale([cornerRadii[0], cornerRadii[1], 1])
|
||||||
|
cylinder(r=1, h = innerDims[2]);
|
||||||
|
|
||||||
|
translate([cornerRadii[0], cornerRadii[1], 0]) cube([innerDims[0], innerDims[1], dims[2]]);
|
||||||
|
|
||||||
|
// X-Z
|
||||||
|
translate(cornerRadii)
|
||||||
|
scale([cornerRadii[0], 1, cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 0]) cylinder(r=1, h = innerDims[1]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2]])
|
||||||
|
scale([cornerRadii[0], 1, cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 0]) cylinder(r=1, h = innerDims[1]);
|
||||||
|
translate([cornerRadii[0], cornerRadii[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale([cornerRadii[0], 1, cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 0]) cylinder(r=1, h = innerDims[1]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale([cornerRadii[0], 1, cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 0]) cylinder(r=1, h = innerDims[1]);
|
||||||
|
|
||||||
|
translate([cornerRadii[0], 0, cornerRadii[2]]) cube([innerDims[0], dims[1], innerDims[2]]);
|
||||||
|
|
||||||
|
// Y-Z
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1] + innerDims[1], cornerRadii[2]])
|
||||||
|
scale([1, cornerRadii[1], cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 90]) cylinder(r=1, h = innerDims[0]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2]])
|
||||||
|
scale([1, cornerRadii[1], cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 90]) cylinder(r=1, h = innerDims[0]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1] + innerDims[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale([1, cornerRadii[1], cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 90]) cylinder(r=1, h = innerDims[0]);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale([1, cornerRadii[1], cornerRadii[2]])
|
||||||
|
rotate([-90, 0, 90]) cylinder(r=1, h = innerDims[0]);
|
||||||
|
|
||||||
|
translate([0, cornerRadii[1], cornerRadii[2]]) cube([dims[0], innerDims[1], innerDims[2]]);
|
||||||
|
|
||||||
|
|
||||||
|
// corners
|
||||||
|
translate(cornerRadii)
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1] + innerDims[1], cornerRadii[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0], cornerRadii[1] + innerDims[1], cornerRadii[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
|
||||||
|
translate([cornerRadii[0], cornerRadii[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0] + innerDims[0], cornerRadii[1] + innerDims[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
translate([cornerRadii[0], cornerRadii[1] + innerDims[1], cornerRadii[2] + innerDims[2]])
|
||||||
|
scale(cornerRadii) sphere(r=1);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
module prism(l, w, h) {
|
||||||
|
polyhedron(// pt 0 1 2 3 4 5
|
||||||
|
points=[[0,0,0], [0,w,h], [l,w,h], [l,0,0], [0,w,0], [l,w,0]],
|
||||||
|
// top sloping face (A)
|
||||||
|
faces=[[0,1,2,3],
|
||||||
|
// vertical rectangular face (B)
|
||||||
|
[2,1,4,5],
|
||||||
|
// bottom face (C)
|
||||||
|
[0,3,5,4],
|
||||||
|
// rear triangular face (D)
|
||||||
|
[0,4,1],
|
||||||
|
// front triangular face (E)
|
||||||
|
[3,2,5]]
|
||||||
|
);}
|
||||||
Submodule
+1
Submodule lib/threads added at 4ae9aeb3b1
@@ -0,0 +1,72 @@
|
|||||||
|
$fn = 256;
|
||||||
|
|
||||||
|
d_i = 10.8; // Inner diameter of the cymbal mount hole
|
||||||
|
|
||||||
|
d_o_top = 24; // Diameter of the outer top of the cymbal support
|
||||||
|
h_top = 11; // Height of the top part of the cymbal support
|
||||||
|
|
||||||
|
d_o_bot = 19; // Diameter of the outer bottom of the cymbal support
|
||||||
|
h_bot = 10.2; // Height of the bottom part of the cymbal support
|
||||||
|
|
||||||
|
h_dome = 6.8; // Height of the dome part of the cymbal support
|
||||||
|
h_neck = 5; // Height of the neck part of the cymbal support
|
||||||
|
|
||||||
|
h_flange = 17.5;
|
||||||
|
w_flange = 3;
|
||||||
|
|
||||||
|
h_full = h_bot + h_neck + h_top + h_dome;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// Bottom part of the cymbal support
|
||||||
|
translate([0, 0, h_bot/2 + 0.1])
|
||||||
|
cylinder(h = h_bot + 0.2, d = d_o_bot, center = true);
|
||||||
|
|
||||||
|
// Neck of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck / 2])
|
||||||
|
cylinder(h = h_neck, d1 = d_o_bot, d2 = d_o_top, center = true);
|
||||||
|
|
||||||
|
// Top part of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top/2 + 0.1])
|
||||||
|
cylinder(h = h_top + 0.2, d = d_o_top, center = true);
|
||||||
|
|
||||||
|
// Dome on top of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top])
|
||||||
|
scale([1, 1, (2*h_dome + 2) / d_o_top])
|
||||||
|
sphere(d = d_o_top);
|
||||||
|
|
||||||
|
// Flange at the bottom of the cymbal support
|
||||||
|
translate([-w_flange / 2, d_i / 2, 0]) cube([w_flange, 22, h_flange]);
|
||||||
|
|
||||||
|
// screw support
|
||||||
|
translate([d_o_bot / 2 - 0.2, 0, 9.2 / 2])
|
||||||
|
rotate([0, -90, 0]) cylinder(h = 1, d = 9.2, center = true);
|
||||||
|
|
||||||
|
translate([d_o_bot / 2 - 0.7, -9.2 / 2, 9.2 / 2])
|
||||||
|
cube([1, 9.2, h_bot]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut out the inner hole for mounting
|
||||||
|
translate([0, 0, 13])
|
||||||
|
cylinder(h = 26.02, d = d_i, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, 27])
|
||||||
|
cylinder(h = 2, d1 = d_i, d2 = 8.4, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, 27 + (h_full - 27)/2])
|
||||||
|
cylinder(h = 1 + h_full - 27, d = 8.4, center = true);
|
||||||
|
|
||||||
|
// Cut out the screw hole
|
||||||
|
translate([d_o_bot / 2 - 0.2, 0, 9.2 / 2])
|
||||||
|
rotate([0, -90, 0]) cylinder(h = d_o_bot + 1, d = 4.6, center = true);
|
||||||
|
|
||||||
|
// Cut off the top (flatten the dome)
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top + h_dome+ 2]) cube([d_o_top, d_o_top, 4], center = true);
|
||||||
|
|
||||||
|
// Cut off the flange at an angle
|
||||||
|
translate([0, d_i/2 + 9, 0])
|
||||||
|
rotate([33.18, 0, 0])
|
||||||
|
translate([-(w_flange + 0.2) / 2, 0, -10])
|
||||||
|
cube([w_flange + 0.2, h_flange + 0.2, 10]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
$fn=36;
|
||||||
|
|
||||||
|
ep = 0.01;
|
||||||
|
height = 4.5;
|
||||||
|
|
||||||
|
iDepth = 3.5;
|
||||||
|
oDepth = 9;
|
||||||
|
|
||||||
|
iWidth = 13;
|
||||||
|
oWidth = 20;
|
||||||
|
|
||||||
|
clipWidth=5;
|
||||||
|
|
||||||
|
overhang=5;
|
||||||
|
|
||||||
|
pinClear = 2.2; // pin clearance
|
||||||
|
slideClear = 1.8;
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// base bracket
|
||||||
|
difference() {
|
||||||
|
translate([-oWidth/2, 0, 0]) cube([oWidth, oDepth, height + ep]);
|
||||||
|
|
||||||
|
translate([-iWidth/2, -ep, -ep]) cube([iWidth, iDepth + ep, height + 3*ep]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clip
|
||||||
|
difference() {
|
||||||
|
translate([-clipWidth/2, -overhang, height]) cube([clipWidth, oDepth + overhang, 4]);
|
||||||
|
|
||||||
|
color("red") union() {
|
||||||
|
translate([-oWidth/2, -2.5, height + 1.25]) rotate([0, 90, 0]) cylinder(d=3, h=oWidth);
|
||||||
|
translate([-clipWidth/2 - ep, -overhang - ep, height - ep]) cube([clipWidth + 2*ep, overhang + ep, 1.5 + ep]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// all measurements in mm
|
||||||
|
$fn=128;
|
||||||
|
|
||||||
|
// Version History
|
||||||
|
// 1 - id=25.6, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0.4
|
||||||
|
// 2 - id=27, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0.1
|
||||||
|
// 3 - id=27, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0
|
||||||
|
// 4 - id=26, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0
|
||||||
|
// 5 - id=26, od1=31, od2=29, h=44, tabHeight=13, tabClearance=-0.1, angle in tab
|
||||||
|
version = "5";
|
||||||
|
|
||||||
|
id = 26;
|
||||||
|
od1 = 31;
|
||||||
|
od2 = 29;
|
||||||
|
h = 44;
|
||||||
|
tabClearance = -0.1;
|
||||||
|
tabHeight = 13;
|
||||||
|
|
||||||
|
module tab() {
|
||||||
|
translate([id/2 + 0.2, 0, -6.5]) rotate([0, 0, 7]) difference() {
|
||||||
|
// tab
|
||||||
|
translate([0, -0.01, 0]) cube([1.6, 4.01, tabHeight]);
|
||||||
|
// tab chamfers
|
||||||
|
union() {
|
||||||
|
translate([0 - 0.2, 2, 0]) rotate([-75, 0, 0]) cube([2, 4, 4]);
|
||||||
|
translate([0 - 0.2, 2, tabHeight]) mirror([0, 0, 1]) rotate([-75, 0, 0]) cube([2, 4, 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module tabCutout() {
|
||||||
|
translate([-id/2 - 3, -5, -(tabHeight + tabClearance)/2]) cube([6, 5.01, tabHeight + tabClearance]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module catchRing() {
|
||||||
|
translate([0, 0, 9]) difference() {
|
||||||
|
cylinder(h=0.8, d=od2, center = true);
|
||||||
|
translate([0, 0, -0.05]) cylinder(h=1, d=id - 0.8, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module mainCylinderBody() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
// outer cylinder
|
||||||
|
cylinder(h=h, d1=od1, d2=od2, center = true);
|
||||||
|
|
||||||
|
// cylinder bore and top chamfer
|
||||||
|
union() {
|
||||||
|
// inner bore
|
||||||
|
translate([0, 0, -0.01]) cylinder(h=h + 0.1, d=id, center = true);
|
||||||
|
|
||||||
|
// top chamfer
|
||||||
|
translate([0, 0, h/2-0.02]) difference() {
|
||||||
|
cylinder(h=2.2, d1=od1+3, d2=od2+3, center = true);
|
||||||
|
translate([0, 0, -0.01]) cylinder(h=2.24, d1=od2+0.1, d2=id-0.2, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catchRing();
|
||||||
|
}
|
||||||
|
// cutout half
|
||||||
|
translate([-(od2+4)/2, 0, -h/2 - 1]) cube([od1 + 4, od1, h + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
mainCylinderBody();
|
||||||
|
tab();
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
tabCutout();
|
||||||
|
translate([0, -0.2-id/2, 4-h/2]) rotate([90, 0, 180])
|
||||||
|
linear_extrude(0.8)
|
||||||
|
text(str("v", version), size=6, halign="center", valign="center", font="Iosevka");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
$fn=180;
|
$fn=180;
|
||||||
ow=23; // outer width
|
ow=23; // outer width
|
||||||
od=18; // outer depth
|
od=18; // outer depth
|
||||||
oh=10; // outer height
|
oh=10; // outer height
|
||||||
ep = 0.01;
|
ep = 0.01;
|
||||||
|
|
||||||
iw=17.4; // inner width
|
iw=17.4; // inner width
|
||||||
id=12.5; // inner depth
|
id=12.5; // inner depth
|
||||||
ih=7.6; // inner height
|
ih=7.6; // inner height
|
||||||
|
|
||||||
sphMul = 4;
|
sphMul = 4;
|
||||||
@@ -51,6 +51,10 @@ difference() {
|
|||||||
ct = 1.3; // cross thickness
|
ct = 1.3; // cross thickness
|
||||||
|
|
||||||
// inner cylinder
|
// inner cylinder
|
||||||
|
// there are conflicting constraints here: the diameter needs to be thick
|
||||||
|
// enough to have strong walls, particularly at the points where the
|
||||||
|
// cross cutaway comes close to them, but the whole cylinder also needs
|
||||||
|
// to fit into the recess allowed in the keypost
|
||||||
color("DimGray") translate([ow/2, od/2, 1.4]) cylinder(d=5.3, h=ih - 1.4);
|
color("DimGray") translate([ow/2, od/2, 1.4]) cylinder(d=5.3, h=ih - 1.4);
|
||||||
|
|
||||||
// inner cross recess (post hole)
|
// inner cross recess (post hole)
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
// measurements in inches
|
||||||
|
width = 40;
|
||||||
|
height = 99.5;
|
||||||
|
depth = 19.5;
|
||||||
|
|
||||||
|
cubeSize = 13.5;
|
||||||
|
|
||||||
|
shelfThickness = 0.5;
|
||||||
|
wallThickness = 1;
|
||||||
|
|
||||||
|
module shelvingUnit(includeFitTest = false) {
|
||||||
|
color("#242424") union() {
|
||||||
|
// sides
|
||||||
|
cube([wallThickness, depth, height]);
|
||||||
|
translate([width - wallThickness, 0, 0]) cube([wallThickness, depth, height]);
|
||||||
|
|
||||||
|
// top and bottom
|
||||||
|
cube([width, depth, wallThickness]);
|
||||||
|
translate([0, 0, height - wallThickness]) cube([width, depth, wallThickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
color("#384048") union() {
|
||||||
|
// shelves
|
||||||
|
for (i = [1 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))]) {
|
||||||
|
translate([wallThickness, 0, i*cubeSize + (i-1)*shelfThickness + wallThickness])
|
||||||
|
cube([width - 2 * wallThickness, depth, shelfThickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dividers
|
||||||
|
for (i = [1 : floor((width - 2 * wallThickness) / (cubeSize + wallThickness))]) {
|
||||||
|
translate([i * (cubeSize + wallThickness), 0, wallThickness])
|
||||||
|
cube([wallThickness, depth, height - 2 * wallThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeFitTest) {
|
||||||
|
// test box fits
|
||||||
|
color("CornflowerBlue") union() {
|
||||||
|
// main boxes
|
||||||
|
translate([wallThickness, 0.01, wallThickness])
|
||||||
|
for (i = [0 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))])
|
||||||
|
for (j = [0 : floor((width - 2 * wallThickness) / (cubeSize + wallThickness)) - 1])
|
||||||
|
translate([j * (cubeSize + wallThickness), 0, i * (cubeSize + shelfThickness)])
|
||||||
|
cube([cubeSize, depth, cubeSize]);
|
||||||
|
|
||||||
|
// corner box
|
||||||
|
translate([30, 0.01, wallThickness])
|
||||||
|
for (i = [0 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))])
|
||||||
|
translate([0, 0, i * (cubeSize + shelfThickness)]) cube([9, depth, cubeSize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
shelvingUnit();
|
||||||
|
|
||||||
|
// cutout for corner box
|
||||||
|
union() {
|
||||||
|
translate([39, depth + 0.01, -1]) rotate([0, 0, 180]) difference() {
|
||||||
|
cube([9, depth - wallThickness, height + 2]);
|
||||||
|
translate([9, 0, -1]) rotate([0, 0, atan(9 / (depth - 2*wallThickness))]) cube([9, depth*2, height + 4]);
|
||||||
|
}
|
||||||
|
translate([width - wallThickness - 0.1, -0.1, -0.1]) cube([wallThickness + 0.2, depth + 0.2, height + 0.2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user