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