// Last edited on 2022-04-17 20:56:01 by stolfi #include "holder.inc" #include "light_box.inc" #include "test_tube.inc" #macro holder_with_tubes(N,M,libox_show,libox_disp) // Test tube holder for {N} tubes, with the first {M} present. // Origin is at back left bottom corner. // Width is along {Y}, height is along {Z}, back is {Y=0}. // All dimensions in mm. // {libox_show} true to include the light box. // {libox_disp} displacement 3-vector for light box. // Test tube dimensions and placement: #local tube_od = 15.8; // Outer diameter of tubes. #local tube_ht = 150.0; // Tube height including round bottom. #local tube_spy = 12; // {Y} spacing between tubes (wall to wall). #local tube_gap = 1.0; // Gap between tube and hole edge, all around. // Material thickness: #local base_thk = 5.0; // Thickness of base plate. #local top_thk = 5.0; // Thickness of top plate. #local bot_thk = 5.0; // Thickness of bottom holding plate. #local side_thk = 5.0; // Thickness of side plates. #local sep_thk = 3.0; // Thickness of separator plates. // Holder dimensions: #local holder_spx_front = 5.0; // {X} spacing between front of holder and tubes. #local holder_spx_back = 15.0; // {X} spacing between back of holder and tubes. #local holder_base_ewd = 80.0; // Extra {X} width of base plate on each side. #local holder_tbz = 120.0; // {Z} dist between bot plate and top plate. // Holder hole geometry: #local hole_d = tube_od + 2*tube_gap; // Diameter or holes on top plate. #local hole_x = holder_spx_back + tube_od/2; // {X} coord of hole centers. #local hole_dy = tube_od + tube_spy; // {Y} dist between hole centers. #local hole0_y = (hole_dy - sep_thk)/2 + side_thk; // {Y} of center of 1st hole. #local cup_dp = 1.0; // {Z} depth of depression below each test tube. #local holder_sx = holder_spx_front + tube_od + holder_spx_back; // {X} size of holder excl extra bot plate width. #local holder_sy = 2*hole0_y + (N-1)*hole_dy; // {Y} size of holder. #local holder_sz = bot_thk + holder_tbz + top_thk; // {Z} size of holder. #local holder_dim = < holder_sx, holder_sy, holder_sz >; // Light box dimensions and geometry: #local libox_sx = 60.0; // {X} size of light box; #local libox_sy = holder_sy; // {Y} size of light box. #local libox_sz = holder_sz - bot_thk; // {Z} size of light box above holder base. #local libox_dim = < libox_sx, libox_sy, libox_sz >; union{ object{ holder( N, holder_dim, hole_d, hole_x, hole_dy, holder_base_ewd, base_thk, bot_thk, top_thk, side_thk, sep_thk, cup_dp ) } #if (libox_show) object{ light_box( libox_dim, bot_thk, top_thk, side_thk ) translate < -libox_sx, 0, bot_thk > translate libox_disp translate xplode*< -4*libox_sx, 0, +4*libox_sz > } #end #local tube_k = 0; // Tube number. #local tube_x = hole_x; // {X} or test tube center. #local tube_y = hole0_y; // {Y} of test tube center. #local tube_z = bot_thk + base_thk - cup_dp; // {Z} or test tube bottom. #while (tube_k < M) #local tube_hue = tube_k/M; object{ test_tube( tube_od, tube_ht, tube_hue ) translate < tube_x, tube_y, tube_z > translate xplode*5*tube_ht*z } #local tube_k = tube_k + 1; #local tube_y = tube_y + hole_dy; #end } #end