Bunch of updates.
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
$fn=128;
|
||||||
|
length=95;
|
||||||
|
|
||||||
|
rotate([90, 0, 0]) translate([0, length / 2, 0]) difference() {
|
||||||
|
union() {
|
||||||
|
rotate([90, 0, 0]) cylinder(d=30, h=length, center=true);
|
||||||
|
translate([10, 0, 0]) cube([20, length, 30], center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
translate([0, -0.01, 0]) rotate([90, 0, 0]) cylinder(d=20, h=length + 0.2, center=true);
|
||||||
|
translate([20, -0.01, 0]) cube([40, length + 0.2, 20], center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//translate([-4, -4, 0]) cylinder(d=14, h=5.2);
|
||||||
|
|
||||||
|
//translate([-1, -1]) cylinder(d=4, h=15);
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
include <../lib/metric-machine-screws.scad>
|
||||||
|
|
||||||
|
$fn=128;
|
||||||
|
|
||||||
|
h_handle = 200; // Length of the handle
|
||||||
|
h_tilted = h_handle / sqrt(2);
|
||||||
|
|
||||||
|
d_handle = 20; // Diameter of the handle
|
||||||
|
screw_distance_on_center = 88.5;
|
||||||
|
|
||||||
|
//translate([0, 0, h_tilted / 2])
|
||||||
|
//rotate([45, 0, 0])
|
||||||
|
//translate([0, d_handle / 2, 0])
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cylinder(d=d_handle, h=h_handle, center=true); // Main handle body
|
||||||
|
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
translate([0, 17, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d=10, h=18, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = [-1, 1]) {
|
||||||
|
translate([0, 5, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
m3Nut(h=d_handle + 10, center=true, clearance=0.2);
|
||||||
|
|
||||||
|
translate([0, 7, i * (screw_distance_on_center / 2)])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d=3.2, h=40, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
translate([0, -0.2, h_tilted / 2])
|
||||||
|
difference() {
|
||||||
|
cube([1, h_tilted, h_tilted], center=true);
|
||||||
|
|
||||||
|
color("blue")
|
||||||
|
translate([0, h_tilted / 2, h_tilted / 2])
|
||||||
|
rotate([45, 0, 0])
|
||||||
|
cube([2, h_handle, h_handle], center=true);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([0, -h_tilted / 2, 40])
|
||||||
|
cube([40, 1, 80], center=true);
|
||||||
|
*/
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
difference() {
|
||||||
|
cube([]);
|
||||||
|
|
||||||
|
union() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@ kallaxDepth = 390; // Full depth of a Kallax shelf
|
|||||||
|
|
||||||
shelfHeight = 160; // Height of a Kallax half-shelf (shelf insert)
|
shelfHeight = 160; // Height of a Kallax half-shelf (shelf insert)
|
||||||
shelfWidth = 320; // Width of a Kallax half-shelf (shelf insert)
|
shelfWidth = 320; // Width of a Kallax half-shelf (shelf insert)
|
||||||
|
shelfDepth = kallaxDepth - 20;
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -1,525 +1,387 @@
|
|||||||
// 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>
|
include <./constants.scad>
|
||||||
|
include <../lib/metric-machine-screws.scad>
|
||||||
|
|
||||||
$fn = 32;
|
// all measurements in mm
|
||||||
|
// boardThickness = 4.7; // 1/8" plywood
|
||||||
|
boardThickness = 7.35;
|
||||||
|
feltThickness = 2.5;
|
||||||
|
feltWidth = 12;
|
||||||
|
clipThickness = boardThickness + 2*feltThickness;
|
||||||
|
clipWallThickness = 4;
|
||||||
|
clipFlangeLength = 24;
|
||||||
|
clipFlangeWidth = 16;
|
||||||
|
|
||||||
module sampleBox(dims, wallThickness) {
|
// measurements for the wooden panels to cut:
|
||||||
// base
|
//
|
||||||
cube([dims[0], dims[1], wallThickness]);
|
// ───────────── - 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
|
||||||
|
//
|
||||||
|
|
||||||
// top
|
module fastenerBlank() {
|
||||||
translate([0, 0, dims[2] - wallThickness])
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
cube([dims[0], dims[1], wallThickness]);
|
rotate([90, 0, 0])
|
||||||
|
m3Nut(h=2.41);
|
||||||
|
|
||||||
// middle shelf
|
translate([0, 2.4, 0])
|
||||||
translate([0, 0, (dims[2] - wallThickness) / 2])
|
rotate([90, 0, 0])
|
||||||
cube([dims[0], dims[1], wallThickness]);
|
m3Nut(h=2.41);
|
||||||
|
|
||||||
// left wall
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
cube([wallThickness, dims[1], dims[2]]);
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d = 3.2, center = false, $fn=128,
|
||||||
|
h = 0.2 + 2 * clipWallThickness + boardThickness);
|
||||||
|
}
|
||||||
|
|
||||||
// middle divider
|
module dowelBlank() {
|
||||||
translate([(dims[0] - wallThickness) / 2, 0, 0])
|
translate([0, 0.1 + 2 * clipWallThickness + boardThickness, 0])
|
||||||
cube([wallThickness, dims[1], dims[2]]);
|
rotate([90, 0, 0])
|
||||||
|
cylinder(d = 3.175, center = false, $fn=128,
|
||||||
|
h = 0.2 + 2 * clipWallThickness + boardThickness);
|
||||||
|
}
|
||||||
|
|
||||||
// right wall
|
module cornerClipA() {
|
||||||
translate([dims[0] - wallThickness, 0, 0])
|
difference() {
|
||||||
cube([wallThickness, dims[1], dims[2]]);
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
module drawerFacePlate(outerBoxDims, includeClips = false) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module tally(count, rightAlign = false) {
|
module drawerBottom(outerBoxDims, includeClips = false) {
|
||||||
groups = floor(count / 5);
|
}
|
||||||
rem = count % 5;
|
|
||||||
xAlign = rightAlign ? -(6 * groups) - (rem * 1.2) : 0;
|
module drawerSide(outerBoxDims, includeClips = false) {
|
||||||
translate([xAlign, 0, 0])
|
}
|
||||||
|
|
||||||
|
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() {
|
union() {
|
||||||
if (count > 4) {
|
translate([ clipOffset, clipOffset, clipOffset])
|
||||||
for (i = [0: max(0, groups - 1)]) {
|
union() {
|
||||||
translate([6*i, 0, 0]) for (j = [0:3])
|
translate([0, 0, innerBoxDims[2] - boardThickness]) topPanel(innerBoxDims);
|
||||||
translate([j*1.2, 0, 0])
|
|
||||||
cube([0.6, 4, 0.41]);
|
translate([boardThickness, 0, 0]) rotate([0, -90, 0]) sidePanel(innerBoxDims);
|
||||||
translate([6*i - 0.8, 0.6, 0]) rotate([0, 0, -60]) cube([0.6, 6.2, 0.41]);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rem != 0) {
|
if (includeClips) {
|
||||||
translate([6*groups, 0, 0])
|
for(i = [0:1]) {
|
||||||
for (j = [0: rem - 1])
|
translate([0, i * (2 * clipWallThickness + innerBoxDims[1]), 0])
|
||||||
translate([j*1.2, 0, 0])
|
mirror([0, i * 1, 0])
|
||||||
cube([0.6, 4, 0.41]);
|
union() {
|
||||||
}
|
rotate([-90, -90, 0])
|
||||||
}
|
cornerClipA();
|
||||||
}
|
|
||||||
|
|
||||||
wallThickness = 4; // Thickness of walls
|
translate([0, 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
feltClearance = 2.5; // Clearance for felt pads
|
rotate([-90, 0, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
// Dimensions for the box that fits inside a Kallax half-shelf
|
translate([2 * clipWallThickness + innerBoxDims[0], 0, 0])
|
||||||
boxWidth = kallaxSide - 2 * feltClearance;
|
rotate([-90, -180, 0])
|
||||||
boxDepth = kallaxDepth;
|
cornerClipA();
|
||||||
boxHeight = shelfHeight - 2 * feltClearance;
|
|
||||||
|
|
||||||
drawerWidth = (boxWidth - 3 * wallThickness) / 2;
|
translate([2 * clipWallThickness + innerBoxDims[0], 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
drawerHeight = (boxHeight - 3 * wallThickness) / 2;
|
rotate([-90, -270, 0])
|
||||||
|
cornerClipA();
|
||||||
|
|
||||||
tenonThickness = wallThickness * 0.6;
|
translate([clipWallThickness + innerBoxDims[0]/2 - clipFlangeLength, 0, 0])
|
||||||
//tenon([6, 8, 2.6]);
|
sideClipA();
|
||||||
//morticeBlank([6, 8, 2.6], 0.1);
|
|
||||||
|
|
||||||
|
translate([clipWallThickness + innerBoxDims[0]/2 + clipFlangeLength, 0, 2 * clipWallThickness + innerBoxDims[2]])
|
||||||
|
rotate([0, 180, 0])
|
||||||
|
sideClipA();
|
||||||
|
|
||||||
// Frame for the box will be made in sections to fit on the print bed
|
translate([0, 0, innerBoxDims[2]/2 + clipFlangeLength + clipWallThickness])
|
||||||
// There are three identical horizontal layers (base, middle shelf, top) that
|
rotate([0, 90, 0])
|
||||||
// will each be made of four pieces. Looking down overhead from the Z axis they
|
sideClipA();
|
||||||
// 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;
|
translate([innerBoxDims[0] + 2*clipWallThickness, 0, innerBoxDims[2]/2 - clipFlangeLength + clipWallThickness])
|
||||||
x2 = boxWidth - x1;
|
rotate([0, 270, 0])
|
||||||
y = boxDepth / 2;
|
sideClipA();
|
||||||
tenonDims = [6, 8, tenonThickness];
|
|
||||||
tenonZOffset = (wallThickness - tenonThickness) / 2;
|
|
||||||
verticalTenonDims = [6, wallThickness, tenonThickness];
|
|
||||||
throughTenonDims = [6, 8 + wallThickness, tenonThickness];
|
|
||||||
morticeClearance = 0.1;
|
|
||||||
|
|
||||||
module leftSideHorizontalPiece(cutWeight = true) {
|
translate([innerBoxDims[0]/2 + clipWallThickness, 0, innerBoxDims[2]/2 + clipWallThickness])
|
||||||
difference() {
|
crossClipA();
|
||||||
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) {
|
module allCutParts(outerBoxDims, includeClips = false) {
|
||||||
union() {
|
innerBoxDims = includeClips ?
|
||||||
difference() {
|
[ outerBoxDims[0] - 2*feltThickness - 2*clipWallThickness,
|
||||||
cube([wallThickness, y, drawerHeight]);
|
outerBoxDims[1] - 2*clipWallThickness,
|
||||||
|
outerBoxDims[2] - 2*feltThickness - 2*clipWallThickness ] :
|
||||||
|
[ outerBoxDims[0] - 2*feltThickness,
|
||||||
|
outerBoxDims[1],
|
||||||
|
outerBoxDims[2] - 2*feltThickness ];
|
||||||
|
|
||||||
if (cutWeight) {
|
topPanel(innerBoxDims);
|
||||||
// cutouts to save materials
|
|
||||||
translate([-0.1, 2*wallThickness, 2*wallThickness])
|
|
||||||
cube([wallThickness + 0.2, y - 4*wallThickness, drawerHeight - 3*wallThickness]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cutWeight) {
|
translate([innerBoxDims[0] + 8, 0, 0])
|
||||||
translate([0, wallThickness, 1.414*wallThickness])
|
bottomPanel(innerBoxDims);
|
||||||
rotate([-41, 0, 0])
|
|
||||||
cube([wallThickness, wallThickness, drawerHeight * 1.19]);
|
|
||||||
|
|
||||||
translate([0, y - 2*wallThickness, 1.414*wallThickness])
|
translate([0, innerBoxDims[1] + 8, 0])
|
||||||
rotate([65, 0, 0])
|
sidePanel(innerBoxDims);
|
||||||
cube([wallThickness, wallThickness, drawerHeight * 1.97]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module pieceA(cutWeight = true) {
|
translate([innerBoxDims[2], innerBoxDims[1] + 8, 0])
|
||||||
difference() {
|
innerPanel(innerBoxDims);
|
||||||
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() {
|
shelfDims = [shelfWidth, shelfDepth, shelfHeight];
|
||||||
for (i = [0:2]) {
|
//assembled(shelfDims);
|
||||||
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([
|
//translate([shelfWidth + 20, 0, 0])
|
||||||
0,
|
//allCutParts(shelfDims);
|
||||||
y + drawerHeight +throughTenonDims[1] + 4,
|
|
||||||
i * (wallThickness + 0.4) + wallThickness])
|
|
||||||
rotate([90, 90, 0]) pieceE();
|
|
||||||
|
|
||||||
translate([0,
|
//translate([300, shelfDepth + 40, 0])
|
||||||
y + drawerHeight +throughTenonDims[1] + 4,
|
//rotate([0, 0, 90])
|
||||||
(i+3) * (wallThickness + 0.4) + wallThickness])
|
printableSetA();
|
||||||
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();
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
$fn = 256;
|
||||||
|
|
||||||
|
d_i = 10.8; // Inner diameter of the cymbal mount hole
|
||||||
|
|
||||||
|
d_o_top = 24; // Diameter of the outer top of the cymbal support
|
||||||
|
h_top = 11; // Height of the top part of the cymbal support
|
||||||
|
|
||||||
|
d_o_bot = 19; // Diameter of the outer bottom of the cymbal support
|
||||||
|
h_bot = 10.2; // Height of the bottom part of the cymbal support
|
||||||
|
|
||||||
|
h_dome = 6.8; // Height of the dome part of the cymbal support
|
||||||
|
h_neck = 5; // Height of the neck part of the cymbal support
|
||||||
|
|
||||||
|
h_flange = 17.5;
|
||||||
|
w_flange = 3;
|
||||||
|
|
||||||
|
h_full = h_bot + h_neck + h_top + h_dome;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
// Bottom part of the cymbal support
|
||||||
|
translate([0, 0, h_bot/2 + 0.1])
|
||||||
|
cylinder(h = h_bot + 0.2, d = d_o_bot, center = true);
|
||||||
|
|
||||||
|
// Neck of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck / 2])
|
||||||
|
cylinder(h = h_neck, d1 = d_o_bot, d2 = d_o_top, center = true);
|
||||||
|
|
||||||
|
// Top part of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top/2 + 0.1])
|
||||||
|
cylinder(h = h_top + 0.2, d = d_o_top, center = true);
|
||||||
|
|
||||||
|
// Dome on top of the cymbal support
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top])
|
||||||
|
scale([1, 1, (2*h_dome + 2) / d_o_top])
|
||||||
|
sphere(d = d_o_top);
|
||||||
|
|
||||||
|
// Flange at the bottom of the cymbal support
|
||||||
|
translate([-w_flange / 2, d_i / 2, 0]) cube([w_flange, 22, h_flange]);
|
||||||
|
|
||||||
|
// screw support
|
||||||
|
translate([d_o_bot / 2 - 0.2, 0, 9.2 / 2])
|
||||||
|
rotate([0, -90, 0]) cylinder(h = 1, d = 9.2, center = true);
|
||||||
|
|
||||||
|
translate([d_o_bot / 2 - 0.7, -9.2 / 2, 9.2 / 2])
|
||||||
|
cube([1, 9.2, h_bot]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut out the inner hole for mounting
|
||||||
|
translate([0, 0, 13])
|
||||||
|
cylinder(h = 26.02, d = d_i, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, 27])
|
||||||
|
cylinder(h = 2, d1 = d_i, d2 = 8.4, center = true);
|
||||||
|
|
||||||
|
translate([0, 0, 27 + (h_full - 27)/2])
|
||||||
|
cylinder(h = 1 + h_full - 27, d = 8.4, center = true);
|
||||||
|
|
||||||
|
// Cut out the screw hole
|
||||||
|
translate([d_o_bot / 2 - 0.2, 0, 9.2 / 2])
|
||||||
|
rotate([0, -90, 0]) cylinder(h = d_o_bot + 1, d = 4.6, center = true);
|
||||||
|
|
||||||
|
// Cut off the top (flatten the dome)
|
||||||
|
translate([0, 0, h_bot + h_neck + h_top + h_dome+ 2]) cube([d_o_top, d_o_top, 4], center = true);
|
||||||
|
|
||||||
|
// Cut off the flange at an angle
|
||||||
|
translate([0, d_i/2 + 9, 0])
|
||||||
|
rotate([33.18, 0, 0])
|
||||||
|
translate([-(w_flange + 0.2) / 2, 0, -10])
|
||||||
|
cube([w_flange + 0.2, h_flange + 0.2, 10]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
$fn=36;
|
||||||
|
|
||||||
|
ep = 0.01;
|
||||||
|
height = 4.5;
|
||||||
|
|
||||||
|
iDepth = 3.5;
|
||||||
|
oDepth = 9;
|
||||||
|
|
||||||
|
iWidth = 13;
|
||||||
|
oWidth = 20;
|
||||||
|
|
||||||
|
clipWidth=5;
|
||||||
|
|
||||||
|
overhang=5;
|
||||||
|
|
||||||
|
pinClear = 2.2; // pin clearance
|
||||||
|
slideClear = 1.8;
|
||||||
|
|
||||||
|
union() {
|
||||||
|
// base bracket
|
||||||
|
difference() {
|
||||||
|
translate([-oWidth/2, 0, 0]) cube([oWidth, oDepth, height + ep]);
|
||||||
|
|
||||||
|
translate([-iWidth/2, -ep, -ep]) cube([iWidth, iDepth + ep, height + 3*ep]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clip
|
||||||
|
difference() {
|
||||||
|
translate([-clipWidth/2, -overhang, height]) cube([clipWidth, oDepth + overhang, 4]);
|
||||||
|
|
||||||
|
color("red") union() {
|
||||||
|
translate([-oWidth/2, -2.5, height + 1.25]) rotate([0, 90, 0]) cylinder(d=3, h=oWidth);
|
||||||
|
translate([-clipWidth/2 - ep, -overhang - ep, height - ep]) cube([clipWidth + 2*ep, overhang + ep, 1.5 + ep]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// all measurements in mm
|
||||||
|
$fn=128;
|
||||||
|
|
||||||
|
// Version History
|
||||||
|
// 1 - id=25.6, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0.4
|
||||||
|
// 2 - id=27, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0.1
|
||||||
|
// 3 - id=27, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0
|
||||||
|
// 4 - id=26, od1=31, od2=29, h=44, tabHeight=13, tabClearance=0
|
||||||
|
// 5 - id=26, od1=31, od2=29, h=44, tabHeight=13, tabClearance=-0.1, angle in tab
|
||||||
|
version = "5";
|
||||||
|
|
||||||
|
id = 26;
|
||||||
|
od1 = 31;
|
||||||
|
od2 = 29;
|
||||||
|
h = 44;
|
||||||
|
tabClearance = -0.1;
|
||||||
|
tabHeight = 13;
|
||||||
|
|
||||||
|
module tab() {
|
||||||
|
translate([id/2 + 0.2, 0, -6.5]) rotate([0, 0, 7]) difference() {
|
||||||
|
// tab
|
||||||
|
translate([0, -0.01, 0]) cube([1.6, 4.01, tabHeight]);
|
||||||
|
// tab chamfers
|
||||||
|
union() {
|
||||||
|
translate([0 - 0.2, 2, 0]) rotate([-75, 0, 0]) cube([2, 4, 4]);
|
||||||
|
translate([0 - 0.2, 2, tabHeight]) mirror([0, 0, 1]) rotate([-75, 0, 0]) cube([2, 4, 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module tabCutout() {
|
||||||
|
translate([-id/2 - 3, -5, -(tabHeight + tabClearance)/2]) cube([6, 5.01, tabHeight + tabClearance]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module catchRing() {
|
||||||
|
translate([0, 0, 9]) difference() {
|
||||||
|
cylinder(h=0.8, d=od2, center = true);
|
||||||
|
translate([0, 0, -0.05]) cylinder(h=1, d=id - 0.8, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module mainCylinderBody() {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
// outer cylinder
|
||||||
|
cylinder(h=h, d1=od1, d2=od2, center = true);
|
||||||
|
|
||||||
|
// cylinder bore and top chamfer
|
||||||
|
union() {
|
||||||
|
// inner bore
|
||||||
|
translate([0, 0, -0.01]) cylinder(h=h + 0.1, d=id, center = true);
|
||||||
|
|
||||||
|
// top chamfer
|
||||||
|
translate([0, 0, h/2-0.02]) difference() {
|
||||||
|
cylinder(h=2.2, d1=od1+3, d2=od2+3, center = true);
|
||||||
|
translate([0, 0, -0.01]) cylinder(h=2.24, d1=od2+0.1, d2=id-0.2, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catchRing();
|
||||||
|
}
|
||||||
|
// cutout half
|
||||||
|
translate([-(od2+4)/2, 0, -h/2 - 1]) cube([od1 + 4, od1, h + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
mainCylinderBody();
|
||||||
|
tab();
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
tabCutout();
|
||||||
|
translate([0, -0.2-id/2, 4-h/2]) rotate([90, 0, 180])
|
||||||
|
linear_extrude(0.8)
|
||||||
|
text(str("v", version), size=6, halign="center", valign="center", font="Iosevka");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
$fn=180;
|
$fn=180;
|
||||||
ow=23; // outer width
|
ow=23; // outer width
|
||||||
od=18; // outer depth
|
od=18; // outer depth
|
||||||
oh=10; // outer height
|
oh=10; // outer height
|
||||||
ep = 0.01;
|
ep = 0.01;
|
||||||
|
|
||||||
iw=17.4; // inner width
|
iw=17.4; // inner width
|
||||||
id=12.5; // inner depth
|
id=12.5; // inner depth
|
||||||
ih=7.6; // inner height
|
ih=7.6; // inner height
|
||||||
|
|
||||||
sphMul = 4;
|
sphMul = 4;
|
||||||
@@ -51,6 +51,10 @@ difference() {
|
|||||||
ct = 1.3; // cross thickness
|
ct = 1.3; // cross thickness
|
||||||
|
|
||||||
// inner cylinder
|
// inner cylinder
|
||||||
|
// there are conflicting constraints here: the diameter needs to be thick
|
||||||
|
// enough to have strong walls, particularly at the points where the
|
||||||
|
// cross cutaway comes close to them, but the whole cylinder also needs
|
||||||
|
// to fit into the recess allowed in the keypost
|
||||||
color("DimGray") translate([ow/2, od/2, 1.4]) cylinder(d=5.3, h=ih - 1.4);
|
color("DimGray") translate([ow/2, od/2, 1.4]) cylinder(d=5.3, h=ih - 1.4);
|
||||||
|
|
||||||
// inner cross recess (post hole)
|
// inner cross recess (post hole)
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
// measurements in inches
|
||||||
|
width = 40;
|
||||||
|
height = 99.5;
|
||||||
|
depth = 19.5;
|
||||||
|
|
||||||
|
cubeSize = 13.5;
|
||||||
|
|
||||||
|
shelfThickness = 0.5;
|
||||||
|
wallThickness = 1;
|
||||||
|
|
||||||
|
module shelvingUnit(includeFitTest = false) {
|
||||||
|
color("#242424") union() {
|
||||||
|
// sides
|
||||||
|
cube([wallThickness, depth, height]);
|
||||||
|
translate([width - wallThickness, 0, 0]) cube([wallThickness, depth, height]);
|
||||||
|
|
||||||
|
// top and bottom
|
||||||
|
cube([width, depth, wallThickness]);
|
||||||
|
translate([0, 0, height - wallThickness]) cube([width, depth, wallThickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
color("#384048") union() {
|
||||||
|
// shelves
|
||||||
|
for (i = [1 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))]) {
|
||||||
|
translate([wallThickness, 0, i*cubeSize + (i-1)*shelfThickness + wallThickness])
|
||||||
|
cube([width - 2 * wallThickness, depth, shelfThickness]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dividers
|
||||||
|
for (i = [1 : floor((width - 2 * wallThickness) / (cubeSize + wallThickness))]) {
|
||||||
|
translate([i * (cubeSize + wallThickness), 0, wallThickness])
|
||||||
|
cube([wallThickness, depth, height - 2 * wallThickness]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeFitTest) {
|
||||||
|
// test box fits
|
||||||
|
color("CornflowerBlue") union() {
|
||||||
|
// main boxes
|
||||||
|
translate([wallThickness, 0.01, wallThickness])
|
||||||
|
for (i = [0 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))])
|
||||||
|
for (j = [0 : floor((width - 2 * wallThickness) / (cubeSize + wallThickness)) - 1])
|
||||||
|
translate([j * (cubeSize + wallThickness), 0, i * (cubeSize + shelfThickness)])
|
||||||
|
cube([cubeSize, depth, cubeSize]);
|
||||||
|
|
||||||
|
// corner box
|
||||||
|
translate([30, 0.01, wallThickness])
|
||||||
|
for (i = [0 : floor((height - 2 * wallThickness) / (cubeSize + wallThickness))])
|
||||||
|
translate([0, 0, i * (cubeSize + shelfThickness)]) cube([9, depth, cubeSize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
shelvingUnit();
|
||||||
|
|
||||||
|
// cutout for corner box
|
||||||
|
union() {
|
||||||
|
translate([39, depth + 0.01, -1]) rotate([0, 0, 180]) difference() {
|
||||||
|
cube([9, depth - wallThickness, height + 2]);
|
||||||
|
translate([9, 0, -1]) rotate([0, 0, atan(9 / (depth - 2*wallThickness))]) cube([9, depth*2, height + 4]);
|
||||||
|
}
|
||||||
|
translate([width - wallThickness - 0.1, -0.1, -0.1]) cube([wallThickness + 0.2, depth + 0.2, height + 0.2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user