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();