#macro sawhorse_strap( open_ang, is_open, wood_wd, wood_th, tape_wd, tape_th, what ) // One half-strap of the sawhorse. // It fits in the notch of the bottom cross beam. // The cylinder that forms the rounded-off part of that notch is "the knee". // {free_len} length of the unsupported part of the half-strap when open. // {open_ang} max opening angle, in degrees. // {is_open} true iff the sawhorse is open. // {wood_wd} width of wood beams. // {wood_th} thickness of wood beams. // {knee_rad} radius of knee. // {tape_wd} width of tape. // {tape_th} tape thickness. ??? Revise below // Notch on cross-beam for strap. // The cylinder that makes up the rounded part at top is the "knee". #local sh_wd = tape_wd + 2.0; // Width of strap notch. #local sh_dp = 3; // Depth of strap notch on outer side. #local sh_rd = 0.5*(wood_th - sh_dp); // Radius of strap notch. #local sh_cx = -0.5*wood_th + sh_rd; // X of center of strap notch knee. #local sh_dy = round_to_half( strap_cy - 0.5*sh_wd ); // Y of outer edge of strap notch. #debug concat( "\n!! strap notch dy = ", str(sh_dy,5,1), "\n" ) #debug concat( "\n!! strap notch dp = ", str(sh_dp,3,1), "\n" ) #debug concat( "\n!! strap notch wd = ", str(sh_wd,4,0), "\n" ) ??? Revise below to account for displacement of half-horse in ??? the +X direction by {hinge_ww/2} // Straps: #local strap_aa = bot_cross_ht + wood_wd - sh_rd; // Z pos of center of notch cyl, closed. #local strap_bb = closed_ht - hinge_rd - strap_aa; // Z dist from hinge to ctr ofnotch cyl, closed. #local strap_cc = wood_th + sh_rd; // X pos of ctr of notch cyl, closed. #local strap_free_len = strap_bb*sang + strap_cc*cang; // Free length of strap. // Z of strap (top of strap notch knee) #if (is_open) #local strap_dz = strap_aa * cang + strap_cc*sang + sh_rd; // Z disp of strap. #else #local strap_dz = strap_aa + sh_rd; #end // The strap is centered in Y with the top of the round part of the notch // at Z = 0. #local eps = 0.01; // Fudge displacement to avoid coincindent surfaces. #local eps3 = < eps, eps, eps >; // Fudge 3D. // Cosine and sine of opening half-angle: #local cang = cos( radians( open_ang/2 ) ); #local sang = sin( radians( open_ang/2 ) ); #local knee_cz = - knee_rad; // Z of knee axis in final strap. // Part of tape that wounds around knee, full round: #local small_bend_cyl = difference{ cylinder{ < 0, -tape_wd/2 + eps, 0 >, < 0, +tape_wd/2- eps, 0 >, knee_rad + tape_th - eps } cylinder{ < 0, -tape_wd/2 - eps, 0 >, < 0, +tape_wd/2 + eps, 0 >, knee_rad + eps } } // Part of tape fixed to the bottom cross beam, vertical: #local bound_part_vert = box{ < 0 + eps, -tape_wd/2 + eps, -(wood_wd - knee_rad) + eps >, < tape_th - eps, +tape_wd/2 - eps, 0 + eps > translate knee_rad*x } // Defines strap pieces: // {knee_cx} X of knee axis. // {small_bend} part of tape wrapped over knee. // {free_part} unsupported part of tape. // The last two have the Y axis as the axis of the knee. #if (is_open) #local knee_cx = free_len; #local bound_part = object{ bound_part_vert rotate -(open_ang/2)*y } #local small_bend = difference{ object{ small_bend_cyl } box{ < -wood_th, -tape_wd, -wood_th >, < +wood_th, +tape_wd, 0 - eps > rotate 0.5*open_ang*y } box{ < -wood_th, -tape_wd, -wood_th >, < 0 + eps, +tape_wd, +wood_th > } } #local free_part = box{ < -free_len - eps, -tape_wd/2 + eps, 0 + eps >, < 0 + eps, +tape_wd/2 - eps, tape_th - eps > translate knee_rad*z } #else #local knee_cx = wood_th + knee_rad; #local bound_part = object{ bound_part_vert } #local small_bend = difference{ object{ small_bend_cyl } box{ < -wood_th, -tape_wd, -wood_th >, < +wood_th, +tape_wd, 0 - eps > } } // Extra length of tape wrapped around knee: #local small_extra_len = (knee_rad + tape_th/2)*radians(90 - open_ang/2); // Bottom bend, full round, centered on Y axis: #local bot_bend_cyl = difference{ cylinder{ < 0, -tape_wd/2 + eps, 0 >, < 0, +tape_wd/2- eps, 0 >, wood_th - eps } cylinder{ < 0, -tape_wd/2 - eps, 0 >, < 0, +tape_wd/2 + eps, 0 >, wood_th - tape_th + eps } } // Length of bottom half-loop: #local bot_bend_len = (wood_th - tape_th/2)*radians(90); // Bottom half-loop: #local bot_bend = intersection{ object{ bot_bend_cyl } box{ < 0 - eps, -tape_wd, -2*wood_th >, < 2*wood_th, +tape_wd, 0 + eps > } } // length of straight dangling part: #local free_part_ht = free_len - small_extra_len- bot_bend_len; #local free_part = union{ object{ bot_bend translate -(wood_th + knee_rad)* x translate -free_part_ht*z } box{ < -tape_th + eps, -tape_wd/2 + eps, -free_part_ht - eps >, < 0 - eps, +tape_wd/2 - eps, 0 + eps > translate -knee_rad*x } } #end #local obj = union{ object{ bound_part } object{ small_bend } object{ free_part } translate < knee_cx, 0, knee_cz > texture{ tx_tape } } obj #end