// Last edited on 2020-04-08 17:04:05 by jstolfi #macro tube_stool_seat( tagg, seat_side, wood_th, holes_wd ) // The seat of the tube stool. // {tagg} Prefix for piece names. // {seat_side} Side of seat, before rounding corners off. // {wood_th} Thickness of each layer of seat. // {holes_wd} Distance between hole centers along diagonal. // The seat is a square box with rounded corners. // The base is at Z=0 and it is centered on the Z axis. // It consists of two layers of plywood. // The four screw holes are on the diagonals. #local tx_wood = texture_wood( < 0.800, 1.000, 0.600 >, < 0.800, 0.750, 0.400 >, 0.2 ) #local tx_drill = texture_matte( < 1.000, 0.200, 0.000 > ) #local seat_th = 2* wood_th; // Total thickness of seat. #local corner_rd = 30; // Radius of corner roundings. #local seat_hs = seat_side/2; // Half-side of seat. // Fudging for proper CSG ops: #local eps = 0.001; #local eps3 = < eps, eps, eps >; // Gouger to round off the corner. // Extends from 0 to {wood_th} in Z. // Placed assuming that the corner is at origin in X and Y. #local corner_rasp = difference{ box{ < 0, 0, 0 - eps >, < corner_rd + eps, corner_rd + eps, wood_th + eps > } cylinder{ < 0, 0, 0 - 2*eps >, < 0, 0, wood_th + 2*eps >, corner_rd - eps } translate -corner_rd * < 1, 1, 0 > } // Gouger to put a chamfer around the seat edges: #local router_rd = wood_th/2; // Gouger for the straight section of the edge, bottom of bot plate, -Y side: #local straight_router = difference{ box{ < - seat_hs + corner_rd - eps, - seat_hs - eps, 0 - eps >, < + seat_hs - corner_rd + eps, - seat_hs + router_rd + eps, router_rd + eps > } cylinder{ < - seat_hs + corner_rd - 2*eps, - seat_hs + router_rd, router_rd >, < + seat_hs - corner_rd + 2*eps, - seat_hs + router_rd, router_rd >, router_rd } } // Gouger for the low corner edge: #local corner_router = difference{ intersection{ cylinder{ < - seat_hs + corner_rd, - seat_hs + corner_rd, 0 - eps >, < - seat_hs + corner_rd, - seat_hs + corner_rd, router_rd + eps >, corner_rd + eps } box{ < - seat_hs - eps, - seat_hs - eps, 0 -2*eps >, < - seat_hs + corner_rd + eps, - seat_hs + corner_rd + eps, router_rd + 2*eps > } } cylinder{ < - seat_hs + corner_rd, - seat_hs + corner_rd, 0 - 2*eps >, < - seat_hs + corner_rd, - seat_hs + corner_rd, router_rd + 2*eps >, corner_rd - router_rd + eps } torus{ corner_rd - router_rd, router_rd + eps rotate 90*x translate < - seat_hs + corner_rd, - seat_hs + corner_rd, router_rd > } } #local router = union{ object{ straight_router } object{ straight_router scale < +1, -1, +1 > } object{ straight_router rotate 90*z } object{ straight_router scale < +1, -1, +1 > rotate 90*z } object{ corner_router scale < +1, +1, +1 > } object{ corner_router scale < -1, +1, +1 > } object{ corner_router scale < +1, -1, +1 > } object{ corner_router scale < -1, -1, +1 > } } // Drill to make a bolt hole through both plates, // centered on X axis, base is at Z=0: #local hole_hd = round_to_int(holes_wd/sqrt(2)/2); // Half-side of holes square. #debug concat("!! hole_hd = ", str(hole_hd, 4,1), "\n") #local hole_rd = 3; // Radius of hole for bolt stem. #local head_dp = 8; // Depth of countersink hole for bolt head. #local head_rd = 8; // Radius of countersink hole for bolt head. #local bolt_drill = union{ cylinder{ < 0, 0, - 3*eps >, < 0, 0, 2*wood_th + 3*eps >, hole_rd + eps } cylinder{ < 0, 0, - head_dp + eps >, < 0, 0, + 3*eps >, head_rd + eps translate 2*wood_th*z } } // Set of four drills properly positioned in X,Y with base at Z=0: #local bolt_drills = union{ object{ bolt_drill translate hole_hd * < +1, +1, 0 > } object{ bolt_drill translate hole_hd * < -1, +1, 0 > } object{ bolt_drill translate hole_hd * < +1, -1, 0 > } object{ bolt_drill translate hole_hd * < -1, -1, 0 > } } // Single plate of plywood with rounded corners, at Z=0, chamfered on bot side: #local plate_gen = difference{ box{ < - seat_hs, - seat_hs, 0 > + eps3, < + seat_hs, + seat_hs, wood_th > - eps3 } object{ corner_rasp scale < +1, +1, +1 > translate seat_hs * < +1, +1, 0 > } object{ corner_rasp scale < -1, +1, +1 > translate seat_hs * < -1, +1, 0 > } object{ corner_rasp scale < +1, -1, +1 > translate seat_hs * < +1, -1, 0 > } object{ corner_rasp scale < -1, -1, +1 > translate seat_hs * < -1, -1, 0 > } object{ router } } // Bottom plate, sitting at Z=0: #local plate0 = difference{ object{ plate_gen } object{ bolt_drills } texture{ tx_wood scale 2 rotate 90*y } } // Top plate, sitting at {Z = wood_th}: #local plate1 = difference{ object{ plate_gen scale < +1, +1, -1 > translate 2*wood_th*z } object{ bolt_drills } texture{ tx_wood scale 2 rotate 90*y rotate 90*z } } write_pieces( "plywd", tagg, 2, 2*seat_hs, 2*seat_hs, wood_th, "Seat layer.") // Completed seat: #local seat = union{ object{ plate0 } object{ plate1 translate xplode*2*wood_th*z } } // #local seat = object{ router texture{ tx_drill } } seat #end