diff --git a/2d/box/box.scad b/2d/box/box.scad index 533433d..fa15647 100644 --- a/2d/box/box.scad +++ b/2d/box/box.scad @@ -1,149 +1,207 @@ -mode = "project"; // default -//mode = "parts"; +mode = "2D"; // default +//mode = "layout"; //mode = "assembly"; -thickness = 3.25; // 3.25mm = 1/8" -spacing = 3.25; - -outer_width = 52*0.75; -outer_height = 52*3*0.75; -outer_depth = 52*1.333*0.75; - golden_ratio = 1.61803398875; -notch_size = golden_ratio*thickness; -notches_w = round((outer_width - 6*thickness) / (2*notch_size)); -notches_h = round((outer_height - 6*thickness) / (2*notch_size)); -notches_d = round((outer_depth - 6*thickness) / (2*notch_size)); +inch = 25.4/*mm*/; -module label(label_text) { - if (mode != "project") text(label_text, halign="center", valign="center"); -} +thickness = 3.25; // 3.25mm = 1/8" medium draftboard +spacing = thickness; +explode = $t*(5*thickness); + +outer_width = 5*inch; +outer_depth = outer_width/golden_ratio; +outer_height = outer_depth/golden_ratio; + +inc_top = true; +inc_bottom = true; +inc_left = true; +inc_right = true; +inc_front = true; +inc_back = true; + +notch_margin = 3*thickness; +notch_size = golden_ratio*thickness; + +notches_w = round((outer_width - 2*notch_margin) / (2*notch_size)); +notches_h = round((outer_height - 2*notch_margin) / (2*notch_size)); +notches_d = round((outer_depth - 2*notch_margin) / (2*notch_size)); + +inc_labels = mode == "layout" || mode == "assembly"; +label_size = min(outer_width, min(outer_depth, outer_height)) / 5; // 2D notch pattern for an edge from [-width/2,0] to [width/2,0] in the XY plane with a +Y normal. // Meant to be subtracted from the shape with difference(). -module notches_neg(n, width, depth=thickness) { - // n notches + n-1 spaces - notch_width = width / (2*n - 1); - space_width = notch_width; - for (i = [0 : n-1]) { - translate([-width/2 + i*notch_width + i*space_width + notch_width/2, -depth/2, 0]) - square([notch_width, depth], center=true); +module notches(n, width, depth=thickness) { + // The side with notches cut out and the remainder flush. + module notches_neg(n, width, depth=thickness) { + // n notches + n-1 spaces + notch_width = width / (2*n - 1); + space_width = notch_width; + for (i = [0 : n-1]) { + translate([-width/2 + i*notch_width + i*space_width + notch_width/2, -depth/2, 0]) + square([notch_width, depth], center=true); + } + } + + // The inverse of notches_neg() for the same parameters, for the mating edge. + module notches_pos(n, width, depth=thickness, extra_width=10000) { + // n spaces + n-1 notches + space_width = width / (2*n - 1); + notch_width = space_width; + translate([-extra_width/2 - width/2, -depth/2, 0]) square([extra_width, depth], center=true); + for (i = [0 : n-1]) { + translate([-width/2 + (i+1)*space_width + i*notch_width + notch_width/2, -depth/2, 0]) + square([notch_width, depth], center=true); + } + translate([extra_width/2 + width/2, -depth/2, 0]) square([extra_width, depth], center=true); + } + + if (n < 0) notches_neg(-n, width, depth); + else if (n > 0) notches_pos( n, width, depth); +} + +module panel(label_text, xsize, ysize, yp, xn, yn, xp) { + difference() { + square([xsize, ysize], center=true); + translate([0,ysize/2+0.005,0]) rotate([0,0,0]) notches(yp, xsize - 2*notch_margin); + translate([-xsize/2-0.005,0,0]) rotate([0,0,90]) notches(xn, ysize - 2*notch_margin); + translate([0,-ysize/2-0.005,0]) rotate([0,0,180]) notches(yn, xsize - 2*notch_margin); + translate([xsize/2+0.005,0,0]) rotate([0,0,270]) notches(xp, ysize - 2*notch_margin); + children(); + if (inc_labels) text(label_text, size=label_size, halign="center", valign="center"); } } -// The inverse of notches_neg() for the same parameters, for the mating edge. -module notches_pos(n, width, depth=thickness) { - // n spaces + n-1 notches - space_width = width / (2*n - 1); - notch_width = space_width; - translate([-1e6/2 - width/2, -depth/2, 0]) square([1e6, depth], center=true); - for (i = [0 : n-1]) { - translate([-width/2 + (i+1)*space_width + i*notch_width + notch_width/2, -depth/2, 0]) - square([notch_width, depth], center=true); - } - translate([10000/2 + width/2, -depth/2, 0]) square([10000, depth], center=true); -} - +module top_cutouts() {} module top_side() { - difference() { - square([outer_width, outer_depth], center=true); - translate([0,outer_depth/2+0.005,0]) rotate([0,0,0]) notches_neg(notches_w, outer_width - 6*thickness); - translate([-outer_width/2-0.005,0,0]) rotate([0,0,90]) notches_neg(notches_d, outer_depth - 6*thickness); - translate([0,-outer_depth/2-0.005,0]) rotate([0,0,180]) notches_neg(notches_w, outer_width - 6*thickness); - translate([outer_width/2+0.005,0,0]) rotate([0,0,270]) notches_neg(notches_d, outer_depth - 6*thickness); - label("Top"); + panel("Top", outer_width, outer_depth, + inc_back ? -notches_w : 0, + inc_left ? -notches_d : 0, + inc_front ? -notches_w : 0, + inc_right ? -notches_d : 0) { + top_cutouts(); } } +module bottom_cutouts() {} module bottom_side() { - difference() { - square([outer_width, outer_depth], center=true); - translate([0,outer_depth/2+0.005,0]) rotate([0,0,0]) notches_neg(notches_w, outer_width - 6*thickness); - translate([-outer_width/2-0.005,0,0]) rotate([0,0,90]) notches_neg(notches_d, outer_depth - 6*thickness); - translate([0,-outer_depth/2-0.005,0]) rotate([0,0,180]) notches_neg(notches_w, outer_width - 6*thickness); - translate([outer_width/2+0.005,0,0]) rotate([0,0,270]) notches_neg(notches_d, outer_depth - 6*thickness); - label("Bottom"); + panel("Bottom", outer_width, outer_depth, + inc_front ? -notches_w : 0, + inc_left ? -notches_d : 0, + inc_back ? -notches_w : 0, + inc_right ? -notches_d : 0) { + bottom_cutouts(); } } +module left_cutouts() {} module left_side() { - difference() { - square([outer_height, outer_depth], center=true); - translate([0,outer_depth/2+0.005,0]) rotate([0,0,0]) notches_neg(notches_h, outer_height - 6*thickness); - translate([-outer_height/2-0.005,0,0]) rotate([0,0,90]) notches_pos(notches_d, outer_depth - 6*thickness); - translate([0,-outer_depth/2-0.005,0]) rotate([0,0,180]) notches_neg(notches_h, outer_height - 6*thickness); - translate([outer_height/2+0.005,0,0]) rotate([0,0,270]) notches_pos(notches_d, outer_depth - 6*thickness); - label("Left"); + panel("Left", outer_depth, outer_height, + inc_top ? notches_d : 0, + inc_back ? -notches_h : 0, + inc_bottom ? notches_d : 0, + inc_front ? -notches_h : 0) { + left_cutouts(); } } +module right_cutouts() {} module right_side() { - difference() { - square([outer_height, outer_depth], center=true); - translate([0,outer_depth/2+0.005,0]) rotate([0,0,0]) notches_neg(notches_h, outer_height - 6*thickness); - translate([-outer_height/2-0.005,0,0]) rotate([0,0,90]) notches_pos(notches_d, outer_depth - 6*thickness); - translate([0,-outer_depth/2-0.005,0]) rotate([0,0,180]) notches_neg(notches_h, outer_height - 6*thickness); - translate([outer_height/2+0.005,0,0]) rotate([0,0,270]) notches_pos(notches_d, outer_depth - 6*thickness); - label("Right"); + panel("Right", outer_depth, outer_height, + inc_top ? notches_d : 0, + inc_front ? -notches_h : 0, + inc_bottom ? notches_d : 0, + inc_back ? -notches_h : 0) { + right_cutouts(); } } +module front_cutouts() {} module front_side() { - difference() { - square([outer_width, outer_height], center=true); - translate([0,outer_height/2+0.005,0]) rotate([0,0,0]) notches_pos(notches_w, outer_width - 6*thickness); - translate([-outer_width/2-0.005,0,0]) rotate([0,0,90]) notches_pos(notches_h, outer_height - 6*thickness); - translate([0,-outer_height/2-0.005,0]) rotate([0,0,180]) notches_pos(notches_w, outer_width - 6*thickness); - translate([outer_width/2+0.005,0,0]) rotate([0,0,270]) notches_pos(notches_h, outer_height - 6*thickness); - label("Front"); + panel("Front", outer_width, outer_height, + inc_top ? notches_w : 0, + inc_left ? notches_h : 0, + inc_bottom ? notches_w : 0, + inc_right ? notches_h : 0) { + front_cutouts(); } } +module back_cutouts() {} module back_side() { - difference() { - square([outer_width, outer_height], center=true); - translate([0,outer_height/2+0.005,0]) rotate([0,0,0]) notches_pos(notches_w, outer_width - 6*thickness); - translate([-outer_width/2-0.005,0,0]) rotate([0,0,90]) notches_pos(notches_h, outer_height - 6*thickness); - translate([0,-outer_height/2-0.005,0]) rotate([0,0,180]) notches_pos(notches_w, outer_width - 6*thickness); - translate([outer_width/2+0.005,0,0]) rotate([0,0,270]) notches_pos(notches_h, outer_height - 6*thickness); - label("Back"); + panel("Back", outer_width, outer_height, + inc_top ? notches_w : 0, + inc_right ? notches_h : 0, + inc_bottom ? notches_w : 0, + inc_left ? notches_h : 0) { + back_cutouts(); } } +// Optimized for height > depth > width. +module part_layout_hdw() { + if (inc_front) front_side(); + translate([-(outer_width/2 + spacing + outer_depth/2), 0, 0]) { + if (inc_left) left_side(); + translate([0, -(outer_height/2 + spacing + outer_width/2), 0]) { + if (inc_bottom) rotate([0,0,270]) bottom_side(); + } + translate([-(outer_depth/2 + spacing + outer_width/2), 0, 0]) { + if (inc_back) back_side(); + } + translate([0, outer_height/2 + spacing + outer_width/2, 0]) { + if (inc_top) rotate([0,0,90]) top_side(); + } + } + translate([outer_width/2 + spacing + outer_depth/2, 0, 0]) { + if (inc_right) right_side(); + } +} + +// Optimized for width > depth > height. +module part_layout_wdh() { + if (inc_front) front_side(); + translate([0, outer_height/2 + spacing + outer_depth/2, 0]) { + if (inc_top) top_side(); + translate([-(outer_width/2 + spacing + outer_height/2), 0, 0]) { + if (inc_left) rotate([0,0,270]) left_side(); + } + translate([0, outer_depth/2 + spacing + outer_height/2, 0]) { + if (inc_back) rotate([0,0,180]) back_side(); + } + translate([outer_width/2 + spacing + outer_height/2, 0, 0]) { + if (inc_right) rotate([0,0,90]) right_side(); + } + } + translate([0, -(outer_height/2 + spacing + outer_depth/2), 0]) { + if (inc_bottom) bottom_side(); + } +} + +module part_layout() { + if (outer_width > outer_height) + part_layout_wdh(); + else + part_layout_hdw(); +} + module thicken() { linear_extrude(height=thickness, center=true, convexity=10) children(); } -module std_part_layout() { - translate([0,0,0]) top_side(); - translate([-(outer_width/2 + outer_height/2 + spacing), 0, 0]) left_side(); - translate([ (outer_width/2 + outer_height/2 + spacing), 0, 0]) right_side(); - translate([0, -(outer_depth/2 + outer_height/2 + spacing), 0]) front_side(); - translate([0, (outer_depth/2 + outer_height/2 + spacing), 0]) back_side(); - translate([0, -(outer_depth + outer_height + 2*spacing), 0]) bottom_side(); -} - -module part_layout() { - translate([-2*(outer_depth/2 + outer_width/2 + spacing), 0, 0]) back_side(); - translate([-1*(outer_depth/2 + outer_width/2 + spacing), 0, 0]) rotate([0,0,90]) left_side(); - front_side(); - translate([outer_depth/2 + outer_width/2 + spacing, 0, 0]) rotate([0,0,90]) right_side(); - translate([outer_depth + outer_width + 2*spacing,(outer_height-outer_depth)/2,0]) top_side(); - translate([outer_depth + outer_width + 2*spacing,-(outer_height-outer_depth)/2,0]) bottom_side(); -} - module part_assembly() { - color("red") translate([0,0, outer_height/2 - thickness/2]) rotate([0,0,0]) thicken() top_side(); - color("green") translate([0,0,-outer_height/2 + thickness/2]) rotate([180,0,0]) thicken() bottom_side(); - color("blue") translate([-outer_width/2 + thickness/2,0,0]) rotate([0,-90,0]) thicken() left_side(); - color("cyan") translate([ outer_width/2 - thickness/2,0,0]) rotate([0, 90,0]) thicken() right_side(); - color("magenta") translate([0,-outer_depth/2 + thickness/2,0]) rotate([ 90,0,0]) thicken() front_side(); - color("yellow") translate([0, outer_depth/2 - thickness/2,0]) rotate([-90,0,0]) thicken() back_side(); + if (inc_left) color("red") translate([ -(outer_width/2 - thickness/2 + explode),0,0]) rotate([90,0,270]) thicken() left_side(); + if (inc_front) color("green") translate([0, -(outer_depth/2 - thickness/2 + explode),0]) rotate([90,0,0]) thicken() front_side(); + if (inc_right) color("blue") translate([ (outer_width/2 - thickness/2 + explode),0,0]) rotate([90,0,90]) thicken() right_side(); + if (inc_back) color("yellow") translate([0, (outer_depth/2 - thickness/2 + explode),0]) rotate([90,0,180]) thicken() back_side(); + if (inc_top) color("cyan") translate([0,0, (outer_height/2 - thickness/2 + explode)]) rotate([0,0,0]) thicken() top_side(); + if (inc_bottom) color("magenta") translate([0,0,-(outer_height/2 - thickness/2 + explode)]) rotate([180,0,0]) thicken() bottom_side(); } -if (mode == "project") - part_layout(); -else if (mode == "parts") +if (mode == "assembly") + part_assembly(); +else if (mode == "layout") thicken() part_layout(); else - part_assembly(); + part_layout();