diff --git a/projects/garage/BMW Z4M.stl b/projects/garage/BMW Z4M.stl new file mode 100644 index 0000000..3c75721 Binary files /dev/null and b/projects/garage/BMW Z4M.stl differ diff --git a/projects/garage/Z4M.scad b/projects/garage/Z4M.scad new file mode 100644 index 0000000..663b998 --- /dev/null +++ b/projects/garage/Z4M.scad @@ -0,0 +1,16 @@ +module scale_uniform(f) { + scale([f, f, f]) + children(); +} + +module z4m() { + // reference dimensions + // cube([73, 171, 51]); + + scale_uniform(1.36) + translate([43, 63, 1.4]) + rotate([0.4, 0, 180]) + import("BMW Z4M.stl"); +} + +z4m(); \ No newline at end of file diff --git a/projects/garage/box.scad b/projects/garage/box.scad new file mode 100644 index 0000000..fac6e04 --- /dev/null +++ b/projects/garage/box.scad @@ -0,0 +1,50 @@ +function sorted(arr) = !(len(arr)>0) ? [] : let( + pivot = arr[floor(len(arr)/2)], + lesser = [ for (y = arr) if (y < pivot) y ], + equal = [ for (y = arr) if (y == pivot) y ], + greater = [ for (y = arr) if (y > pivot) y ] +) concat( + sorted(lesser), equal, sorted(greater) +); + +module ccube(dimensions) { + ds = sorted(dimensions); + echo(ds.y, ds.z, 1, "// thickness", ds.x); + cube(dimensions); +} + +module topbottom(dimensions, thickness, back_inset) { + ccube([dimensions.x + (thickness * 2), dimensions.y + (thickness * 2) + back_inset, thickness]); +} + +module side(dimensions, thickness) { + ccube([thickness, dimensions.y, dimensions.z]); +} + +module frontback(dimensions, thickness) { + ccube([dimensions.x + (thickness * 2), thickness, dimensions.z]); +} + +module box(dimensions, thickness, back_inset=0) { + translate([0, 0, 0]); + topbottom(dimensions, thickness, back_inset); + + translate([0, 0, dimensions.z + thickness]) + topbottom(dimensions, thickness, back_inset); + + translate([0, thickness, thickness]) + side(dimensions, thickness); + + translate([dimensions.x + thickness, thickness, thickness]) + side(dimensions, thickness); + + translate([0, dimensions.y + thickness, thickness]) + frontback(dimensions, thickness); + + translate([0, thickness, thickness]) + rotate([0, 0, -15]) + mirror([0, 1, 0]) + frontback(dimensions, thickness); +} + +box([5, 5, 5], 0.5, 1); diff --git a/projects/garage/casters.scad b/projects/garage/casters.scad new file mode 100644 index 0000000..bd8ba9b --- /dev/null +++ b/projects/garage/casters.scad @@ -0,0 +1,82 @@ +function caster_axel(wheel_r, axel_r) = [1 + axel_r, wheel_r + axel_r, 0]; + +module caster_bracket(wheel_r, wheel_h, axel_r, plate_t, padding=0.125, $fn=$fn) { + plate_side = wheel_r + axel_r + 1; + + module caster_plate( + wheel_r, + axel_r, + plate_t, + ) { + difference() { + linear_extrude(plate_t) + polygon([ + [0, 0], + [0, plate_side], + [2 + axel_r * 2, plate_side], + [plate_side, 2 + axel_r * 2], + [plate_side, 0], + ]); + + axel = caster_axel(wheel_r, axel_r); + translate(axel) + cylinder(r=axel_r, h=plate_t, $fn=$fn); + } + } + + translate([0, -plate_t, 0]) + union() { + translate([0, plate_t, 0]); + caster_plate(wheel_r, axel_r, plate_t); + + translate([0, plate_t, wheel_h + (plate_t + padding * 2)]) + caster_plate(wheel_r, axel_r, plate_t); + + cube([plate_side, plate_t, wheel_h + ((plate_t + padding) * 2)]); + } +} + +module caster( + wheel_r, + wheel_h, + axel_r, + axel_h, + bearing_r=0, + bearing_h=0, + plate_t=0.125, + padding=0.125, + $fn=$fn, +) { + rotate([-90, 0, -90]) + translate([-(caster_axel(wheel_r, axel_r).y), bearing_h - (wheel_r * 2) - 1 + plate_t + padding, -((wheel_h/2) + plate_t + padding)]) + union() { + caster_bracket(wheel_r, wheel_h, axel_r, plate_t, padding, $fn=$fn); + + translate(caster_axel(wheel_r, axel_r)) { + translate([0, 0, plate_t + padding]) + cylinder(r = wheel_r, h=wheel_h, $fn=$fn); + + translate([0, 0, -padding]) { + cylinder(r = axel_r, h = (wheel_h + (2* plate_t) + (padding*4)), $fn=$fn); + } + } + + translate([caster_axel(wheel_r, axel_r).y, 0, (wheel_h/2) + plate_t + padding]) + rotate([90, 0, 0]) { + cylinder(r = bearing_r, h=bearing_h); + + translate([0, 0, bearing_h]) + cylinder(r=axel_r, h=axel_h, $fn=$fn); + } + } +} + +caster( + // wheel (r, h) + 5, 1, + // axel (r, h) + 0.5, 1, + // bearing (r, h) + 0.75, 0.25, + $fn=16 +); \ No newline at end of file diff --git a/projects/garage/garage.scad b/projects/garage/garage.scad new file mode 100644 index 0000000..7f4f3bb --- /dev/null +++ b/projects/garage/garage.scad @@ -0,0 +1,192 @@ +use +use +use +use + +// Note 16" stud spacing +// Note 2.5" downgrade over run of garage; height to minimums + +module pass() { +} + +module do() { + children(); +} + +module garage_perimeter() { + union() { + polygon([ + [0, 0], + [0, 232], + [40, 232], + [40, 238], + [-6, 238], + [-6, -6], + [5, -6], + [5, 0], + [0, 0], + ]); + + polygon([ + [201, 0], + [196, 0], + [196, -6], + [207, -6], + [207, 198], + [207 - 72, 198], + [207 - 72, 238], + [207 - 72 - 62, 238], + [207 - 72 - 62, 232], + [207 - 72 - 6, 232], + [207 - 72 - 6, 192], + [201, 192], + ]); + } +} + +// walls +union() { + // FIXME: Draw the walls downgrade + linear_extrude(height=96) + garage_perimeter(); + + // FIXME: Draw the floor + + // Garage door frame + translate([0, -6, 90]) + cube([201, 6, 6]); + + // Pedestrian door frame + translate([0, 232, 84]) + cube([129, 6, 12]); +} + +module label(text="label", + textsize=4, + pos=[0,0,0], + dpos=[10,0,10], + linesize=0.2, + length=20, + anglexyz=[0,45,90]) +{ + p1 = pos + dpos; + if ($preview) + color("black") { + line(pos, p1, linesize); + translate(p1) + rotate($vpr) + text(text, size = textsize); + } +} + +module line(p1=[0,0,0], p2=[0,0,10], r=.1) { + hull() { + translate(p1) sphere(r); + translate(p2) sphere(r); + } +} + +// car (rough, assuming driver side door open) +translate([45 + 24 + 18, 10, 0]) +color("blue") +z4m(); + +// south side workspace + +//// power pulls +translate([0, 0, 44]) { + let(outlets=4) { + translate([1, 232, 2]) + rotate([90, 0, 0]) + cylinder(r=0.5, h=16 + 48 * (outlets - 1)); + + for(i=[0:outlets-1]) { + translate([0, 232 - 4 - 16 - i*48, 0]) + cube([3, 4, 4]); + } + } +} + +//// printer rack +translate([4, 232 - 37, 0]) { + pass() + do() { + cube([42, 24, 92]); + label("servers", pos=[21, 12, 92]); + } + do() { + translate([33, 0, 0]) + rotate([0, 0, 90]) + printer_rack(); + label("printers", pos=[19, 21, 80]); + } +} + +toolchest_size=44; + +//// tool chest +translate([4, 232 - 37 - 1 - toolchest_size, 0]) { + do() { + color("red") + cube([18.6, toolchest_size, 42.5]); + + label("Tool chest", pos=[9.3, 25, 45.2]); + } +} + +//// worktop +let(tops=2) +translate([24 + 1, 232 - 1 - 37 - 1 - toolchest_size - 1- (48 * tops), 0]) { + rotate([0, 0, 90]) + shelving(48 * tops, 24, 32, shelves=3); + label("Worktop", pos=[-12, (48*tops)/2, 32]); +} + +//// bike hanger +pass() +cube([50, 33, 60]); + +// north side storage +translate([201 - 24 - 1, 1, 0]) { + for (i=[0:2]) { + translate([0, (48 + 1) * i, 0]) { + color("red") + shelving(24, 48, 78); + label("Deep storage", pos=[12, 24, 90]); + } + } +} + +// Current tire rack +translate([201, 148, 65]) { + rotate([0, 0, 90]) + tire_loft(); + label("Tire storage", pos=[-14.5, 22, 30]); +} + +translate([201, 148, 32]) +rotate([0, 0, 90]) +tire_loft(); + +// sherpa +translate([201 - 13, 192, 0]) +rotate([0, 0, 270]) +cube([42, 12, 25]); + +// trash can +translate([90, 232-14, 0]) { + let (height=28, wall=0.25) + difference() { + cylinder(h=height, d=23); + translate([0, 0, wall]) + cylinder(h=height, d=23 - (wall * 2)); + } +} + +// IT gear +translate([129-19, 232-32, 0]) { + translate([0, 0, 84]) + cube([19, 24, 15]); + + cube([24, 24, 32]); +} diff --git a/projects/garage/printer-rack.scad b/projects/garage/printer-rack.scad new file mode 100644 index 0000000..f5faf7d --- /dev/null +++ b/projects/garage/printer-rack.scad @@ -0,0 +1,48 @@ +use +use + +padding = 1.5; +mdf_thickness = 0.75; +pin_inset = 3; + +function padded(dims, padding) = [for(e=dims) e+padding]; + +// dimensions for things +prusa = padded([31.5, 31.5, 35.5], padding); +cr10 = padded([19, 27, 25], padding); +repbox = padded([19, 12.5, 12.5], padding); +cart = [prusa.x, prusa.y, 6.75 + mdf_thickness]; + +module cart() { + for(x=[pin_inset, cart.x - pin_inset]) + for(y=[pin_inset, cart.y - pin_inset]) + translate([x, y, 0]) + caster( + // wheel (r, h) + 3, 1, + // axel (r, h) + 0.5, 1, + // bearing (r, h) + 0.75, 0.25, + $fn=16 + ); + + translate([0, 0, cart.z - mdf_thickness]) + ccube([prusa.x + (mdf_thickness * 2), prusa.y + (mdf_thickness * 2), mdf_thickness]); +} + +module printer_rack() { + translate([0, 0, 0]) + cart(); + + //translate([0, 0, cart.z]) + //box(prusa, mdf_thickness); + + translate([0, 0, cart.z]) + box([prusa.x, prusa.y, repbox.z], mdf_thickness); + + translate([0, 0, cart.z + repbox.z + mdf_thickness * 2]) + box([prusa.x, prusa.y, cr10.z], mdf_thickness); +} + +printer_rack(); \ No newline at end of file diff --git a/projects/garage/steel-shelving.scad b/projects/garage/steel-shelving.scad new file mode 100644 index 0000000..41f1c8d --- /dev/null +++ b/projects/garage/steel-shelving.scad @@ -0,0 +1,45 @@ +module shelving_leg(height) { + linear_extrude(height) + polygon([ + [0, 0], + [1, 0], + [1, 0.125], + [0.125, 0.125], + [0.125, 1], + [0, 1], + ]); +} + +module shelving_legs(width, depth, height) { + union() { + translate([0, 0, 0]) + rotate([0, 0, 0]) + shelving_leg(height); + + translate([width, 0, 0]) + rotate([0, 0, 90]) + shelving_leg(height); + + translate([0, depth, 0]) + rotate([0, 0, -90]) + shelving_leg(height); + + translate([width, depth, 0]) + rotate([0, 0, 180]) + shelving_leg(height); + } +} + +module shelving_shelves(width, depth, height, shelves) { + for (i = [0:((height-2)/(shelves - 1)):height-2]) { + translate([0, 0, i]) + cube([width, depth, 2]); + } +} + +module shelving(width, depth, height, shelves=4) { + shelving_legs(width, depth, height); + shelving_shelves(width, depth, height, shelves); +} + +shelving(48, 24, 78); \ No newline at end of file diff --git a/projects/garage/tire-loft.scad b/projects/garage/tire-loft.scad new file mode 100644 index 0000000..11ff733 --- /dev/null +++ b/projects/garage/tire-loft.scad @@ -0,0 +1,54 @@ +// HyLoft 01031 Folding Storage TireLoft, + +module rounded_cylinder(r, h, n) { + rotate_extrude(convexity=1) { + offset(r=n) offset(delta=-n) square([r,h]); + square([n,h]); + } +} + +module tire(dia, w, iw) { + difference() { + rounded_cylinder(dia/2, w, 1); + cylinder(r=(iw/2), h=w); + } +} + +module loft_end() { + cube([1, 22.5, 1]); + cube([1, 1, 24.5]); + + translate([-0.125, 22.5, -0.75]) + rotate([45, 0, 0]) + cube([0.125, 1, 32]); +} + +module tire_loft() { + color("silver") { + loft_end(); + + translate([0, 4, 0.5]) + rotate([0, 90, 0]) + cylinder(d=1, h=42); + + translate([0, 22, 0.5]) + rotate([0, 90, 0]) + cylinder(d=1, h=42); + + translate([42, 0, 0]) + mirror([1, 0, 0]) + loft_end(); + } + + // tires + for(i=[0:10:30]) { + let(dr=2) { + translate([i + 1, (28.3/2)-dr, (28.3/2)-dr]) + rotate([0, 90]) + color("black") + tire(28.3, 9.3, 19); + } + } +} + +tire_loft(); \ No newline at end of file