Compare commits

...

18 Commits

63 changed files with 3016490 additions and 26 deletions
+3
View File
@@ -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
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
+637
View File
@@ -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();
+75
View File
@@ -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.
+289
View File
@@ -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.
+19
View File
@@ -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.
+18
View File
@@ -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);
+49
View File
@@ -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);
*/
+6
View File
@@ -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.)--&gt; 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.
+68
View File
@@ -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
+27
View File
@@ -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();
}
}
+1
View File
@@ -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);
+11
View File
@@ -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
+61
View File
@@ -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
+632
View File
@@ -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();
+20 -24
View File
@@ -1,24 +1,20 @@
module chamferedCube(size = [1, 1, 1], chamfer = 1) {
ep = 0.01;
difference() {
cube(size);
// X-axis
for (i = [0:3]) {
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
for (i = [0:3]) {
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]);
}
// Z-axis
for (i = [0:3]) {
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]);
}
}
}
module chamferedCube(size = [1, 1, 1], chamfer = 1) {
ep = 0.01;
difference() {
cube(size);
for (i = [0: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]);
// Z-axis
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]);
}
}
}
+140
View File
@@ -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]);
}
}
+9
View File
@@ -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);
}
+125
View File
@@ -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]);
}
}
}
}
+75
View File
@@ -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);
}
+14
View File
@@ -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");
}
}
+6 -2
View File
@@ -1,11 +1,11 @@
$fn=180;
ow=23; // outer width
od=18; // outer depth
oh=10; // outer height
oh=10; // outer height
ep = 0.01;
iw=17.4; // inner width
id=12.5; // inner depth
id=12.5; // inner depth
ih=7.6; // inner height
sphMul = 4;
@@ -51,6 +51,10 @@ difference() {
ct = 1.3; // cross thickness
// 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);
// 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]);
}
}