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