include include //--->>>> Open the "Customizer" window to adjust parameters! /* [⛭️ basic properties and dimensions] */ //ᑎ lid=true; //⊚ hinge_type="snap"; //[snap, pin:pin ❨filament strand❩ ,print in place,no hinge] //🔒 closure_type="snap rim"; //[snap rim, latch, magnets, none] //[mm]️ X = 60; //[mm] Y = 50; //[mm] Z = 50; dimensions_for = "inside"; // [inside, outside] internal_dimensions = dimensions_for=="inside"?true:false; //[mm]⭾ wallthickness= 3; hinge=hinge_type=="no hinge"?false:true; /* [🖶 printer/slicer setup] */ //⌀ "line width" to be more specific nozzle_diameter = 0.42; //⭿ layer_height = 0.20; /* [∞ Gridfinity] */ //overides parameters to fit the gridfinity platform and adds slots at the bottom gridfinity_support=false; //[42mm]️ units_X = 2; //[42mm] units_Y = 1; //[7mm] units_Z = 6; fill_bottom=true; //works best with the lid turned off stacking_lip=false; //adds holes for magnets base_magnets = false; //[layer height] layers_below_magnet = 2; //[mm] base_magnet_tolerance = 0.2; //[mm] base_magnet_diameter = 6.0; //[mm] base_magnet_height = 2.0; //useful if 'layers below magnet = 0'; add_prying_notch = false; /* [⌗ divider settings] */ dividers = false; //[mm]⭾ //amount of dividers ‖ regular_spaced_X_divider = 2; //[0.0-1.0 of X] //irregular_spaced_X_divider = [0.0,0.0,0.0,0.0];//[0.0:0.01:1.0] //amount of dividers ═ regular_spaced_Y_divider = 1; //[0.0-1.0 of Y] //irregular_spaced_Y_divider = [0.0,0.0,0.0,0.0];//[0.0:0.01:1.0] divider_Z_height = 0.5;//[0:0.01:1] divider_thickness = 1.3; divider_rounding = 1.3; divider_chamfer = 0.8; /* [✦✨✦ aesthetic settings] */ //higher values will increase generation time! might cause timout! resolution=32; //[8:8:128] $fn=resolution; //🟊🌟🟊 exterior_type="textured";//["basic","textured","complex"] //chamfer on the top and bottom ◇ outer_chamfer= 3; inner_chamfer= max(outer_chamfer-wallthickness/2,0); //rounding on the Z edges ⛶ (0 is bugged) outer_rounding = 10; overrider_automatic_inner_rounding = false; inner_rounding = 6; /* [↳ ░░ texture type settings] */ texture_pattern = "stripes"; //["trunc diamonds", "diamonds", "stripes", "ribs", "round ribs", "noise", "wave", "cubes", "hexagon"] texture_scale = 12; //negative=>invert; affects both "textured" and "complex" tex_depth = 1.2; //⭮ rotate_texture = false; //how much of the tex depth should be added to the wallthickness? tex_depth_wallthickness_factor= 0.75; //[0:.05:1.0] /* [↳ ⌧ complex type settings] */ complex_pattern = "hex_scaffold";//[weave,hex_scaffold,gyroid] complex_scale = 12; //only works on some complex patterns scaffold_thickness = 0.40; //[0.01:0.01:0.99] add_texture_to_complex_shell = false; //0 => perforated walls extra_wall = 0.000 ; //[0:0.025:1] //will increase generation time complex_resolution = 5 ; //[1:1:20] /* [ᑎ lid shape and options] */ //⭿ also affects hingless boxes hinge_height_offset = 6; //whether "lid angle" or "lid downset" is used shape_method = "angle";//[angle,downset] //⦝ lid_angle = 35;//[0:90] //[mm] lid_downset = 10.0;// //factor hinge_inset = 0.33;//[0:0.1:1] hinge_inset_rounding = 0.5;//[0:0.1:1] //factor lip_inset = 0.33;//[0:0.1:1] lip_inset_rounding = 0.5;//[0:0.1:1] //[mm] lid_tolerance = 0.1; /* [ᑕ lid helpers] */ // thanks @quinoje lid_handle = false; lid_handle_alignment = "top"; //[top, lip] //[mm] lid_handle_outset = 1.0; //[mm] lid_handle_thickness = 1.0; //[mm] ⭿ negative possible lid_handle_offset = 1.0; //⎹⟷⎸ lid_handle_width_factor = 0.5;//[0.05:0.05:1] //[degrees] ⦝ lid_handle_angle = 45;//[0:5:65] lid_handle_radian = tan(lid_handle_angle); lid_handle_chamfer = 0.2; // thanks @Best_Geezus lid_groove = false; lid_groove_alignment = "lip"; //[top, lip] //[mm] lid_groove_depth = 2.0; //[mm] lid_groove_height = 6.0; //[mm] ⭿ negative possible lid_groove_offset = 1.0; //⎹⟷⎸ lid_groove_width_factor = 0.5;//[0.05:0.05:1] //[degrees] ⦝ lid_groove_angle = 45;//[0:5:90] lid_groove_chamfer = 0.2; /* [ ⃤ ▽ snap rim settings] */ invert_snap_rim = true; //0.2=>good fit , 0.3=> tight fit snap_rim_depth = 0.2; //best kept default snap_rim_height_factor = 6; //best kept default snap_rim_tolerance = 0.03; /* [▣ latch settings] */ latch_clamp_strength = 0.12; latch_amount = 1; //for latch amount>1 latch_gap = 20; //[mm] latch_inset = 2.0; //[mm] for latch inset >= wallthickness minimum_back_wall_thickness = 1.6; //[mm] latch_thickness = 4.0; latch_width = 20; latch_length = 25; latch_chamfer = 0.2; latch_tolerance = 0.2; latch_joint_tolerance = -0.2; //[mm] extra_finger_clearance = 4; /* [🧲 magnet settings] */ Y_magnet_alignment="center";//["center","inside","outside"] magnet_pause_helper=true; //only visual connect_magnets=true; magnet_chamfer=0.4; //see "🖶 printer/slicer setup" for layer height layers_over_magnet=4; //less=> more magnets minimum_magnet_gap=3; //⎹⟷⎸ magnet_array_width_factor=1;//[0.1:0.1:1] magnet_type= "cylinder"; //["cylinder","box"] //[mm] magnet_tolerance=0.2; //[mm] cylinder_diameter=6.0; //[mm] cylinder_height=2.0; //[mm] box_height=10.0; //[mm] box_depth=2.0; //[mm] box_length=20.0; /* [▢ rim settings] */ //does not work with "snap rim" rim=true; //[mm]⭿ rim_height=0.8; //makes the rim angled rim_offset=0.2;//[-.5:0.1:1] rim_tolerance=0.1; /* [🞅 general hinge barrel settings] */ // Zaznacz, aby wymusić własną liczbę zawiasów use_custom_barrel_count = false; // Wpisz ilość (Nieparzystą) zawiasów (działa tylko, gdy powyższe jest zaznaczone) custom_barrel_count = 2; //[mm]⌀ barrel_diameter= 4.6; // will try to stay as close to this as possible max_barrel_length=5.0; barrel_chamfer=0.2; //[mm]tolerance betweens the barrels barrel_tolerance=0.15; barrel_rotary_tolerance=0.2; //[degrees] allows for more rotation, does not affect pip hinge extra_clearance = 15;//[0:60] /* [⚑ Co drukowac / What to print] */ // Pokaz OBIE wkladki (ukrywa reszte) show_trays = false; // Pokaz TYLKO PIERWSZA wkladke show_only_tray_1 = false; // Pokaz TYLKO DRUGA wkladke (docinana) show_only_tray_2 = false; // Pokaz TYLKO dol pudelka (bez klipsa) show_only_box = false; // Pokaz TYLKO pokrywke show_only_lid = false; // Pokaz TYLKO sam klips (zatrzask) show_only_latch = false; // Wysokosc pierwszej wkladki w mm tray_depth = 15.0; // Grubosc scianki wkladki w mm tray_wall_thickness = 1.6; // Luz pomiedzy pudelkiem a wkladka (na kazda strone) tray_tolerance = 0.3; //ͼϾ /* [⨀ snap hinge settings] */ //[mm] extra tightness makes it not slip out snap_hinge_tolerance = -0.1; //[degrees] ∠ //slot_direction = 45; //[0:90] /* [🞇 pin hinge settings] */ //diameter of the pin, 2.2 works well for 1.75mm filament dpin = 2.2; //higher => pin insert hole more angeled pin_floppiness = 0.60;//[0:0.05:1] pin_insert_direction = 45;//[-180:90] /* [🞉 print in place (pip) hinge settings] */ //0=as close as possible; 1=barrel tangent to outer wall pip_barrel_outset=0.5;//[0:3] //[mm] ⭾ pip_body_lid_tolerance=0.1; /* [Hidden] */ {//for the gridfinity platform grid_pitch=42; height_unit=7; stacking_fix=gridfinity_support&&stacking_lip? (4.4-nozzle_diameter*2)/2:0; } {//some basic consts epsilon = 0.001; root3=sqrt(3); root2=sqrt(2); } {//magnet variables on a global level magnet_wallthickness=nozzle_diameter*2; magnet_top_buffer=layer_height*layers_over_magnet; } {// basic dimensions and co /* +textured walls needs to be thicker */ t_wallthickness =exterior_type=="basic"?wallthickness:wallthickness+abs(tex_depth)*tex_depth_wallthickness_factor; tmpX = internal_dimensions? X+t_wallthickness*2:X; tmpY = internal_dimensions? Y+t_wallthickness*2:Y; tmpZ = internal_dimensions? Z+wallthickness*2:Z; lid_tolerance_offset=lid&&hinge_type=="print in place"? round_to(lid_tolerance):lid_tolerance; min_tolerance = lid_tolerance_offset % layer_height; outerX = gridfinity_support?units_X*grid_pitch-.5:tmpX; outerY = gridfinity_support?units_Y*grid_pitch-.5:tmpY; tmpZ_2 = gridfinity_support?units_Z*height_unit:tmpZ; tmpZ_3 = round_to(tmpZ_2); outerZ = tmpZ_3 + min_tolerance; //(tmpZ_2>=tmpZ_3?min_tolerance:layer_height-min_tolerance); innerX=outerX-t_wallthickness*2; innerY=outerY-t_wallthickness*2; innerZ=outerZ-wallthickness*2; max_rounding = (min(outerX,outerY)/2)-0; outer_fillet = gridfinity_support?3.75*1:min(outer_rounding,max_rounding); inner_fillet = overrider_automatic_inner_rounding?inner_rounding:max(outer_fillet-t_wallthickness,1.6); //texutred sketch with an inset of .5 gives the most consisten results Tsketch = offset(rect([outerX,outerY],rounding=outer_fillet),delta=-abs(tex_depth)/2); } {//calculating some stuff for the hinges // To zostaje - określa ile miejsca mamy na zawias hinge_length = outerX-outer_fillet*2; lip_length = innerX-inner_fillet*2; // To jest stara logika automatu (obliczamy ją pomocniczo) tmp_barrel_count=floor(hinge_length/max_barrel_length); auto_barrel_count = max(tmp_barrel_count -(tmp_barrel_count % 2 == 0 ? 1 : 0), 3); // NOWOŚĆ: Wybór między Twoją liczbą a automatem barrel_count = use_custom_barrel_count ? custom_barrel_count : auto_barrel_count; // To zostaje - przelicza szerokość pojedynczego segmentu na bazie barrel_count barrel_length=hinge_length/barrel_count; dbarrel=barrel_diameter; // To zostaje - pozycjonowanie osi zawiasu pin_barrel_alignment_offset=(-dbarrel/2+t_wallthickness/2); pip_barrel_alignment_offset=pip_barrel_outset*dbarrel/2; } {//calculates stuff for the lid shape //global so it can be used by different modules //hinge_offset set to half outerZ true_hinge_downset=hinge_type=="print in place"?outerZ/2-stacking_fix: //if pin than barrel tangent to top //if no hinge wallthickness round_to(hinge_height_offset+(hinge?dbarrel:wallthickness)); true_hinge_upset = outerZ - true_hinge_downset - min_tolerance; hinge_kathete=innerY*(1-hinge_inset-lip_inset); lid_radian=shape_method == "angle"?tan(lid_angle):lid_downset/hinge_kathete; lip_kathete=round_to( min(lid_radian*hinge_kathete, max(outerZ-true_hinge_downset-wallthickness-(closure_type=="snap rim"?snap_rim_depth*snap_rim_height_factor:0),0))); //from top to lip lip_outer_downset=lip_kathete+true_hinge_downset; lid_hypotenuse=opp_adj_to_hyp(hinge_kathete,lip_kathete); //from bot to lip lip_outer_upset = outerZ - lip_outer_downset - min_tolerance; true_lip_inset_rounding=1.5*lip_inset_rounding*min(lip_inset*innerY,lid_hypotenuse); true_hinge_inset_rounding=1.5*hinge_inset_rounding*min(hinge_inset*innerY,lid_hypotenuse); //for finger groove; only calculates when actually needed } {//full 3d lid shape sample_gap=min(24/resolution,2); path_XY_profile = resample_path(spacing=sample_gap,keep_corners=90,closed=true, zrot(90,rect([innerY,innerX],rounding=inner_fillet))); raw_path_YZ_profile = [ [0,-outerY/2,outerZ-lip_outer_downset], [0,-innerY/2+innerY*lip_inset,outerZ-lip_outer_downset], [0,innerY/2-innerY*hinge_inset,true_hinge_upset], [0,outerY/2,true_hinge_upset] ]; radii_YZ_profile = [0,true_lip_inset_rounding,true_hinge_inset_rounding,0]; path_YZ_profile = round_corners(raw_path_YZ_profile,radius=radii_YZ_profile) ; yz_raw_table = [for (p = path_YZ_profile) [p.y, p.z]]; yz_lookup_table = sort(yz_raw_table); final_path_raw = [ for (pt = path_XY_profile) let ( new_z = lookup(pt.y, yz_lookup_table) ) [pt.x, pt.y, new_z] ]; final_path= path_merge_collinear(final_path_raw, closed=true, eps=1e-3); } {//bunch of functions, some even unused might need them later tho {function dividers() = !dividers?undef:let( frame_reg = make_region( difference([ rect([outerX,outerY]), offset(rect([innerX,innerY],rounding=inner_fillet),delta=.1,quality=32) ])), X_dividers_reg = regular_spaced_X_divider==0?[]:[ for (i = [1 : regular_spaced_X_divider]) let(pos = i * innerX/(regular_spaced_X_divider+1) - innerX/2) move([pos, 0], rect([divider_thickness, outerY])) ], Y_dividers_reg = regular_spaced_Y_divider==0?[]:[ for (i = [1 : regular_spaced_Y_divider]) let(pos = i * innerY/(regular_spaced_Y_divider+1) - innerY/2) move([0, pos], rect([outerX, divider_thickness])) ], all_regs = [for (r=[frame_reg, X_dividers_reg, Y_dividers_reg]) if (len(r) > 0) r], combined_region = union(all_regs), // 5. Apply offset to the entire combined structure final_region = offset(offset(combined_region, delta=divider_rounding,quality=1),r=-divider_rounding,$fn=resolution/2), )final_region;} function round_to(value,multiple=layer_height)=round(value/multiple)*multiple; function avrg(list) = sum(list) / len(list); function vnf_clamp_to_unit(vnf) = let( // Cut X axis v1 = vnf_halfspace([1,0,0,0],vnf), v2 = vnf_halfspace([-1,0,0,-1],v1), // Cut Y axis v3 = vnf_halfspace([0,1,0,0],v2), v4 = vnf_halfspace([0,-1,0,-1],v3), // Cut Z axis v5 = vnf_halfspace([0,0,1,0],v4), v6 = vnf_halfspace([0,0,-1,-1],v5) ) v6; function remove_border_faces(vnf, eps=0.001) = let( verts = vnf[0], faces = vnf[1], // Check if a specific value is on the Min (0) or Max (1) border is_min = function(x) abs(x) < eps, is_max = function(x) abs(x-1) < eps, // A face is a "border face" if ALL its vertices are on the same border plane keep_face = function(f) let( // Get all x and y coordinates for the vertices in this face xs = [for(i=f) verts[i].x], ys = [for(i=f) verts[i].y], // Check X borders on_left_wall = [for(x=xs) if(!is_min(x)) 1] == [], // True if list empty on_right_wall = [for(x=xs) if(!is_max(x)) 1] == [], // Check Y borders on_front_wall = [for(y=ys) if(!is_min(y)) 1] == [], on_back_wall = [for(y=ys) if(!is_max(y)) 1] == [] ) // Keep the face only if it is NOT on any of these walls !(on_left_wall || on_right_wall || on_front_wall || on_back_wall) ) [verts, [for(f=faces) if(keep_face(f)) f]]; function clean_vnf(vnf, e=0.0001) = let( verts = vnf[0], faces = vnf[1], clean_verts = [for (p=verts) [quant(p.x,e), quant(p.y,e), quant(p.z,e)]] ) [clean_verts, faces]; function clean_vnf2(vnf) = let( verts = vnf[0], faces = vnf[1], clean_verts = [for (p=verts) [constrain(p.x,0,1), constrain(p.y,0,1), constrain(p.z,0,1)]] ) [clean_verts, faces]; function boundary_to_3d(boundary_2d, z) = [for (pt = boundary_2d) for(pt2=pt) [pt2[0], pt2[1], z]]; } {//custom vnf textures {function hex_wall(thickness=scaffold_thickness) = let( //idk what theses do, sc is needed to correctly scale the hex so it fits into the 1x1 box for it to be tileable. note that when used you have to mulitply the Y size of texture times the root of 3 hyp=adj_ang_to_hyp(0.5,30), sc = 1/3/hyp, //maxes a hexagon and squishes it hex_poly = move([0,sc-1],yscale(sc, regular_ngon(n=6,id=1-thickness,spin=90,anchor=CENTER),1)), centers = [ [-.5,-.5], [.5,-.5],[-.5,.5],[0,0], [.5,.5] ], //places hexagons on the centers raw_hexes = [for (c=centers) move(c+[0,0], hex_poly)], //booleans are possible in 2D but not as vnf so doing it now tile_bounds = square([1,1],center=true), //clips the hexes so it fits into 1x1 //"inverts" the hexagons so that the negative of them remains scaffold_region = difference(tile_bounds, raw_hexes), raw_vnf = move([.5,.5,.5],linear_sweep(scaffold_region, h=1) ), clamped_vnf = vnf_triangulate(vnf_clamp_to_unit(raw_vnf)), cleaned_vnf = vnf_drop_unused_points(remove_border_faces(vnf_merge_points(clean_vnf(clamped_vnf)))) ) cleaned_vnf;} function diag_stripes_vnf() =[ [[0,0,1],//1 [.5,0,0],[0,.5,0],//1,2 [0,1,1],[1,0,1],//3,4 [1,.5,0],[.5,1,0],//5,6 [1,1,1]],//7 [[0,2,1],[1,2,3,4],[4,3,6,5],[5,6,7]] ]; {function half_pillars() = vnf_vertex_array( let( arc_numbers=2, single_arc = arc(d=1/arc_numbers, angle=[180,0],cp=[.5/arc_numbers,0], $fn=$fn*texture_scale/16), arc_list = [ for(i = [0 : arc_numbers-1]) move([i * 1/arc_numbers, 0], single_arc) ], final_arc = path_join(arc_list), ) [ for (y = [0 : 1]) [ for (arc = final_arc) [arc.x , y , arc.y*2*arc_numbers] ] ],reverse=true);} function diag_weave_vnf() = [ [[0.2, 0, 0], [0.8, 0, 0], [1, 0.2, 0.5], [1, 0.8, 0.5], [0.7, 0.5, 0.5], [0.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1], [0.7, 0.5, 1], [0.5, 0.3, 0.5], [1, 0.2, 0], [1, 0.8, 0], [0.8, 1, 0.5], [0.2, 1, 0.5], [0.5, 0.7, 0.5], [0.7, 0.5, 0], [0.8, 1, 1], [0.2, 1, 1], [0.5, 0.7, 1], [0.8, 1, 0], [0.2, 1, 0], [0, 0.8, 0.5], [0, 0.2, 0.5], [0.3, 0.5, 0.5], [0.5, 0.7, 0], [0, 0.8, 1], [0, 0.2, 1], [0.3, 0.5, 1], [0, 0.8, 0], [0, 0.2, 0], [0.3, 0.5, 0], [0.2, 0, 1], [0.8, 0, 1], [0.5, 0.3, 1]], [[0, 1, 5], [1, 2, 4, 5], [7, 11, 10, 8], [8, 10, 9], [7, 8, 2, 1], [9, 10, 4, 3], [10, 11, 5, 4], [0, 5, 11, 6], [12, 13, 17], [13, 14, 16, 17], [3, 4, 20, 18], [18, 20, 19], [3, 18, 14, 13], [19, 20, 16, 15], [20, 4, 17, 16], [12, 17, 4, 2], [21, 22, 26], [22, 23, 25, 26], [15, 16, 29, 27], [27, 29, 28], [15, 27, 23, 22], [28, 29, 25, 24], [29, 16, 26, 25], [21, 26, 16, 14], [30, 31, 32], [31, 6, 11, 32], [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7], [35, 25, 32, 11], [30, 32, 25, 23]] ]; {function gyroid(x,y,z, wavelength) = let( p = 360/wavelength * [x,y,z] ) sin(p.x)*cos(p.y)+sin(p.y)*cos(p.z)+sin(p.z)*cos(p.x);} } //back_half(s=1000) // hsv(h=170,s=.05,v=.8) // render() // printable_box(); //render() //pin_body(); // //render() //pin_lid(); //gridfinity_bottom(is_bool=true); //back_half(s=1000,y=outerY/2-dbarrel/2){ //fwd(outerX/2) //up(outerZ-lip_outer_downset) //cube([50,30,200],anchor=LEFT); // //} //% //render() //pin_lid(); //color("offwhite") //pin_body(); //// //// //color("teal") //fwd(outerY/2+latch_thickness) //back(latch_inset) //up(outerZ-lip_outer_downset) //xrot(90) //mirror([0,0,1]) //latch(just_latch=true); //lid_handle(is_bool=true); module lid_handle(is_bool=true){ lid_handle_downset = lid_handle_alignment=="top"? outer_chamfer+lid_handle_offset+lid_handle_thickness/2: lip_outer_downset-lid_handle_offset-lid_handle_thickness/2; base_size = [lid_handle_width_factor*hinge_length,lid_handle_thickness]; cut_knob(); module knob(){ up(outerZ-lid_handle_downset) fwd(outerY/2) fwd(lid_handle_outset) prismoid( size1=base_size+[outerY/2*lid_handle_radian,outerY*lid_handle_radian], size2=base_size, h=outerY/2,orient=FWD,anchor=TOP, chamfer=latch_chamfer); }; module cut_knob(){ difference(){ knob(); up(outerZ) cube([outerX*2,outerY*2,outerZ*2],anchor=BOT); shell_inside(); } } }; module lid_groove(is_bool=true){ //caps it it doesn't dig into the inside true_lid_groove_depth = min(lid_groove_depth,t_wallthickness-nozzle_diameter*2); //so the groove doesn't get too large //it could still become too large and dig into the main body but I don't want it to be too restrictive true_lid_groove_height = lid_groove_height; //so I can use it to scale the chamfer in Z to get the right angle; lid_groove_radian = tan(lid_groove_angle); //if the angle would be so shallow that the depth would decrease it caps it true_lid_groove_radian = min( lid_groove_radian*lid_groove_depth, lid_groove_height/lid_groove_depth*2); //when top then aligned just bellow the outer chamfer //when lip aligned just over the "lip" lid_groove_downset = lid_groove_alignment=="top"? outer_chamfer+lid_groove_offset: lip_outer_downset-true_lid_groove_height-lid_groove_offset; if(is_bool) slot(); module slot(){ up(outerZ-lid_groove_downset) fwd(outerY/2) diff() cuboid([lid_groove_width_factor*hinge_length,true_lid_groove_depth,true_lid_groove_height],anchor=FWD+TOP){ if(true_lid_groove_radian!=0) edge_profile([BOT+BACK]) yscale(true_lid_groove_radian/true_lid_groove_depth) mask2d_chamfer(x=true_lid_groove_depth,inset=0); edge_profile(BACK) mask2d_chamfer(lid_groove_chamfer); tag("keep") edge_profile_asym(FRONT,except=BOT, flip=true, corner_type="sharp") xflip() mask2d_chamfer(lid_groove_chamfer); } } }; module latch(for_bool=false,just_latch=false){ ////lalatch_amount = 1; ////for latch amount>1 //latch_gap = 20; ////[mm] //latch_thickness = 4.0; //latch_width = 20; //latch_length = 20; ////[mm] //latch_inset = 2; //latch_tolerance = 0.2;rance = 0.2; usable_latch = latch_length-latch_thickness*2; latch_slot_depth = min(latch_width/3,usable_latch/2); latch_cone_offset = .3+nozzle_diameter/4; clamp_thickness = nozzle_diameter*2 ; //fwd(outerY/2+latch_thickness) //back(latch_inset) //up(outerZ-lip_outer_downset) //xrot(90) //mirror([0,0,1]) // if(closure_type=="latch"&&lid){ xcopies(spacing=latch_gap+latch_width,n=latch_amount) { if(just_latch) just_latch(); if(!for_bool&&!just_latch) box_ankers(); if(for_bool&&!just_latch) anker_carver(); } } module negative_cone(){ right(latch_width/2) back(latch_slot_depth) back(latch_thickness/2) up(latch_thickness/2) union(){ xcyl(d2=latch_thickness-latch_chamfer*2-latch_cone_offset,d1=0, l=(latch_thickness-latch_chamfer*2-latch_cone_offset)/2, anchor=RIGHT+CENTER); xcyl(d=latch_thickness-latch_chamfer*2-latch_cone_offset*2, l=(latch_thickness), anchor=LEFT+CENTER); } } module positive_cone(){ right(latch_width/2) right (latch_tolerance) back(latch_slot_depth) back(latch_thickness/2) up(latch_thickness/2) xcyl(d2=latch_thickness-latch_chamfer*2-latch_cone_offset,d1=latch_cone_offset*2, l=(latch_thickness-latch_chamfer*2-latch_cone_offset*3)/2, anchor=RIGHT+CENTER); } module just_latch(){ // % // back(latch_thickness+latch_slot_depth) // cuboid([latch_width,latch_length, latch_thickness],anchor=BOT+BACK); latch_body(); module latch_body(){ basic_sketch=[ [0,0], [0,latch_slot_depth], [latch_width/2,latch_slot_depth], [latch_width/2-latch_slot_depth,0], ]; compliant_hole=offset([ [latch_width/2-clamp_thickness*2,latch_slot_depth-clamp_thickness*1], [latch_width/2-latch_slot_depth+clamp_thickness*1,clamp_thickness*2], ],r=clamp_thickness,$fn=resolution/2); bezpath1= path_to_bezpath([ [latch_width/2,latch_slot_depth], [latch_width/2-latch_slot_depth/2+latch_clamp_strength,latch_slot_depth/2-latch_clamp_strength], [latch_width/2-latch_slot_depth,0], ]); offset_bez = bezpath_offset(polar_to_xy(r=clamp_thickness,theta=135),bezpath1); path_bez = bezpath_curve(offset_bez,splinesteps=4); perforated_quadrant = union(path_bez,difference(basic_sketch,compliant_hole)); top_slots = union(perforated_quadrant,xflip(perforated_quadrant)); all_slots = union(top_slots,yflip(top_slots)); extra_bot = latch_length-latch_slot_depth*2-latch_thickness; whole_latch = union( all_slots, fwd(latch_slot_depth,rect([latch_width,extra_bot],anchor=BACK)), back(latch_slot_depth,rect([latch_width,latch_thickness/2+latch_chamfer],anchor=BOT)), ); // color("blue") // stroke(bezpath_curve(offset_bez,splinesteps=4),width=.1,closed=true); // // color("red") // stroke(compliant_hole,width=.1,closed=true); difference(){ union(){ offset_sweep(whole_latch,h=latch_thickness,ends=os_chamfer(width=latch_chamfer),$fn=resolution/6); back(latch_slot_depth+latch_thickness/2) xrot(180) teardrop(d=latch_thickness, h=latch_width,cap_h=latch_thickness/2,anchor=TOP,spin=90,chamfer=latch_chamfer,ang=53); }//union ends, difference starts up(latch_thickness+layer_height*2) fwd(extra_bot+latch_slot_depth) chamfer_edge_mask(l=latch_width,orient=LEFT,chamfer=latch_thickness-latch_chamfer); xflip_copy() union(){ negative_cone(); left(latch_joint_tolerance) chain_hull(){ positive_cone(); down(latch_thickness/2) //fwd(latch_thickness/2) positive_cone(); down(latch_thickness) left(latch_thickness/2) positive_cone(); } } } } } module box_ankers(){ need_wall = latch_inset>t_wallthickness-minimum_back_wall_thickness?true:false; distance_to_back = (need_wall?latch_tolerance:0) + latch_thickness+max(0,t_wallthickness-latch_inset); scale_factor = (1 + distance_to_back/latch_thickness)*1; distance_to_back_wall = distance_to_back + minimum_back_wall_thickness; //minimum_back_wall_thickness if(need_wall)let(){ extra_distance = max(0,latch_inset-t_wallthickness); wall_width = latch_width+minimum_back_wall_thickness*4; wall_length = latch_length+minimum_back_wall_thickness*2 +extra_distance*2 + extra_finger_clearance; wall_thickness = minimum_back_wall_thickness + extra_distance; difference(){ fwd(innerY/2) up(outerZ-lip_outer_downset) down(wall_length/2) up(latch_slot_depth+latch_thickness+extra_distance+minimum_back_wall_thickness) diff() cuboid([wall_width,wall_thickness,wall_length],anchor=FRONT){ edge_profile([BACK],except=["Z"]) mask2d_chamfer(x=wall_thickness, excess=2); edge_profile(["Z"],except=[FWD]) yscale(wall_thickness/minimum_back_wall_thickness) mask2d_roundover(r=minimum_back_wall_thickness, excess=2); }; latch_hole(); } } fwd(outerY/2+latch_thickness) back(latch_inset) up(outerZ-lip_outer_downset) xflip_copy() difference(){ union(){ xrot(90) mirror([0,0,1]) positive_cone(); base_size=[latch_thickness*0.5,latch_thickness]; right(latch_width/2+latch_thickness/4) right(latch_tolerance) up(latch_slot_depth+latch_thickness/2) back(latch_chamfer) union(){ prismoid( size1=base_size*scale_factor*4/3, size2=base_size, shift=[(base_size[0]*-scale_factor)*4/6+base_size[0]*.5,0], h=distance_to_back-latch_chamfer,orient=FWD,anchor=TOP, chamfer=latch_chamfer); prismoid( size1=base_size-[latch_chamfer*2,latch_chamfer*2], size2=base_size, h=latch_chamfer,orient=BACK,anchor=TOP, chamfer=latch_chamfer); } right(latch_width/2) left(latch_slot_depth/2) difference(){ union(){ diff() prismoid( size1=latch_slot_depth*(root2/2)*scale_factor, size2=latch_slot_depth*(root2/2), shift=-latch_slot_depth*(root2/2)*scale_factor*1/2.8, h=distance_to_back,orient=FWD,anchor=TOP,spin=-45, chamfer=latch_chamfer) attach(RIGHT+BACK,"corner",inside=true) polygon_edge_mask(mask2d_chamfer(h=latch_thickness*scale_factor,inset=0,mask_angle=$edge_angle), $edge_length+latch_chamfer, scale=0.0001); ; prismoid( size1=latch_slot_depth*(root2/2)-latch_chamfer*2, size2=latch_slot_depth*(root2/2), h=latch_chamfer,orient=BACK,anchor=TOP,spin=-45, chamfer=latch_chamfer); } fwd(latch_chamfer) left(latch_slot_depth/4) back(latch_thickness/1) cuboid([latch_slot_depth,latch_slot_depth,latch_thickness*2],anchor=RIGHT,chamfer=-latch_chamfer,orient=FWD,edges=TOP); } }//diff starts if(need_wall) right(latch_width/2+latch_tolerance) back(latch_thickness) fwd(max(0,latch_inset-t_wallthickness)) cube([latch_width*2,latch_inset,latch_length*2],anchor=LEFT+FWD); }//diff ends } module latch_hole(){ max_thickness = t_wallthickness+latch_thickness+latch_inset; back_size = [latch_width,latch_length] + [latch_tolerance*2,latch_tolerance*2]+[0,extra_finger_clearance]; front_size = back_size + [0,max_thickness*2]; fwd(outerY/2) back(latch_inset+latch_tolerance) up(outerZ-lip_outer_downset) down(extra_finger_clearance/2) down(latch_length/2-latch_slot_depth-latch_thickness) prismoid( size2=back_size, size1=front_size, h=max_thickness,orient=BACK,anchor=TOP, chamfer=latch_chamfer); } module anker_carver(){ difference(){ latch_hole(); box_ankers(); } } } module gridfinity_stacking_lip(){ if(stacking_lip&&gridfinity_support) up(outerZ) difference(){ //up(4.4) rect_tube(size=[outerX,outerY], wall=t_wallthickness, h=4.4-nozzle_diameter*2,rounding=3.75,anchor=BOT,chamfer2=0); union(){ up(.7+1.8) prismoid(size1=[outerX-1.9*2,outerY-1.9*2], size2=[outerX,outerY], h=1.9,rounding1=3.2/2, rounding2=7.5/2); up(0.7) prismoid(size1=[outerX-1.9*2,outerY-1.9*2], size2=[outerX-1.9*2,outerY-1.9*2], h=1.8,rounding1=3.2/2, rounding2=3.2/2); prismoid(size1=[outerX-(2.6)*2,outerY-(2.6)*2], size2=[outerX-1.9*2,outerY-1.9*2], h=0.7,rounding1=1.6/2, rounding2=3.2/2); } } } module gridfinity_bottom(is_bool=true){ // grid_pitch=42; // height_unit=7; // 2.95 pos_offset=is_bool?0:wallthickness; if(gridfinity_support) grid_copies(n=[ceil(outerX/grid_pitch),ceil(outerY/grid_pitch)],spacing=grid_pitch) bottom_tile(); module bottom_tile(){ if(base_magnets) { final_base_magnet_diameter = base_magnet_diameter+base_magnet_tolerance*2 + (is_bool?0:nozzle_diameter*3); final_base_magnet_height = base_magnet_height+base_magnet_tolerance*2 +(is_bool?0:layer_height*5); magnet_spacing = grid_pitch-(2.15+0.8+4.8)*2; magnet_diagonal_spacing = magnet_spacing/(root2/2); zrot(90) teardrop(h=final_base_magnet_height,d=4,anchor=CENTER,orient=FRONT,ang=1,cap_h=final_base_magnet_diameter/2) ; } if(!(!is_bool&&fill_bottom)) difference(){ cuboid([grid_pitch,grid_pitch,4.75+pos_offset],anchor=BOT); up(pos_offset) scale([grid_pitch/(grid_pitch+pos_offset*2),grid_pitch/(grid_pitch+pos_offset*2),1]){ prismoid(size1=grid_pitch-(.8+2.15+.25)*2, size2=grid_pitch-(2.15+.25)*2, h=.8,rounding1=1.6/2,rounding2=3.2/2); up(.8) prismoid(size1=grid_pitch-(2.15+.25)*2, size2=grid_pitch-(2.15+.25)*2, h=1.8,rounding1=3.2/2,rounding2=3.2/2); up(.8+1.8) prismoid(size1=grid_pitch-(2.15+.25)*2, size2=grid_pitch-(.25)*2, h=2.15,rounding1=3.2/2,rounding2=7.5/2); } } } } module pin_hole(){ hole_length = outer_fillet+barrel_length/2+t_wallthickness; handleX = hole_length*((pin_floppiness*.33)+.666); handleZ = (-hole_length*pin_floppiness)/2; bez = [[0,0,0],[hole_length/3,0,0],[handleX,0,handleZ],[hole_length,0,-hole_length*pin_floppiness*2]]; path = rot([-pin_insert_direction,0,0],p=bezpath_curve(bez)); //the sketch that is being swept sketch = teardrop2d(d=dpin, ang=55,spin=180); //move aligns 0,0,0 to the middle of the back right barrel of the lid difference(){ move([hinge_length/2-barrel_length, outerY/2-t_wallthickness/2+pin_barrel_alignment_offset, outerZ-hinge_height_offset-dbarrel/2]) path_sweep(sketch,path); right(outerX/2) left(t_wallthickness) fwd(dbarrel) cuboid([outerX,outerY,outerZ],anchor=BOT+LEFT); } } module snap_rim(is_lid=false){ // snap_rim_depth = 1; // snap_rim_tolerance local_rim_tolerance=is_lid?snap_rim_tolerance:-snap_rim_tolerance; snap_rim_height= snap_rim_depth*snap_rim_height_factor; center= wallthickness/2-snap_rim_depth/2; raw_sketch = fwd(snap_rim_height,[ [0, 0], [0, snap_rim_height/1.2], [0, snap_rim_height], [center, snap_rim_height], [center+snap_rim_depth-snap_rim_tolerance, snap_rim_height*3.5/5+lid_tolerance_offset/3], [center+snap_rim_depth-snap_rim_tolerance, snap_rim_height*3/5+lid_tolerance_offset/3], [center, snap_rim_height*2/5+lid_tolerance_offset/3], [center, snap_rim_height*1/5], [wallthickness/2, 0], [t_wallthickness+epsilon, 0], [t_wallthickness+epsilon, -snap_rim_height], [0,-snap_rim_height] ]); body_carve_sketch= invert_snap_rim? right(center*2+snap_rim_depth, mirror([1,0],union( difference( union( square([t_wallthickness+.5+lid_tolerance_offset,snap_rim_height*2],anchor=LEFT), right(t_wallthickness+.5+lid_tolerance_offset,mirror([0,1],right_triangle(snap_rim_height*2,anchor=LEFT)))), raw_sketch ), square([t_wallthickness-wallthickness+1,snap_rim_height],anchor=RIGHT+FWD), ) ) ) : difference( union( square([2,snap_rim_height],anchor=BOT), square([t_wallthickness+1,snap_rim_height*2],anchor=LEFT), ), raw_sketch ) ; lid_carve_sketch= invert_snap_rim? right(center*2+snap_rim_depth, mirror([1,0], union( square([2,snap_rim_height],anchor=BOT), right(wallthickness+.5, union( mirror([0,1],right_triangle(snap_rim_height*2,anchor=LEFT)), rect([1,snap_rim_height*2],anchor=RIGHT))), make_region( zrot(180,raw_sketch,cp=[wallthickness/2,-snap_rim_height*2.5/5]) ) ) ) ) : union( right(wallthickness,square([t_wallthickness-wallthickness+1,(snap_rim_height)*2],anchor=LEFT)), square([2,snap_rim_height],anchor=BOT), zrot(180,raw_sketch,cp=[wallthickness/2,-snap_rim_height*2.5/5]) ) ; final_sketch=path_merge_collinear(is_lid?lid_carve_sketch:body_carve_sketch); // color("red") //stroke(raw_sketch, width=0.03, closed=true); // polygon(raw_sketch); // move_copies(raw_sketch)cube(.2,center=true); //stroke(inverted_raw_sketch, width=0.03, closed=true); // color("blue") stroke(body_carve_sketch, width=0.03, closed=true); // color("teal") stroke(lid_carve_sketch, width=0.03, closed=true); if(closure_type=="snap rim") difference(){ path_sweep( final_sketch,method="manual",relaxed=false, final_path,//profiles=true, closed=true,uniform=false); //// stroke(path_YZ_profile,width=1); if(hinge){ extra_factor=3; cut_start=-(innerY/2-inner_fillet)+local_rim_tolerance; cut_end=cut_start+snap_rim_height*extra_factor; cut_extra=cut_end+snap_rim_height; point1 = [cut_start,lookup(-cut_start, yz_lookup_table)]; point2 = [cut_end,lookup(-cut_end, yz_lookup_table)-snap_rim_height*extra_factor]; point3 = [cut_extra,lookup(-cut_extra, yz_lookup_table)-snap_rim_height*extra_factor]; total_path = [ [point1[0],point1[1]], [point2[0],point2[1]], [point3[0],point3[1]], [cut_end,0], [-outerY,0], [-outerY,outerZ], [cut_start,outerZ], ]; //stroke(path_YZ_profile,width=2); rot([0,-90,0]) rot([0,0,-90]) linear_extrude(outerX*2,center=true) polygon(round_corners(total_path,radius=0)); // // up(outerZ-true_hinge_downset-snap_rim_height/2) // back(innerY/2-inner_fillet-local_rim_tolerance) // prismoid( // size1=[outerX*2,outerY], // size2=[outerX*2,outerY], // h=outerZ, // anchor=FWD); } } } module rim(is_lid){ local_rim_tolerance=is_lid?rim_tolerance/2:-rim_tolerance/2; local_rim_height=round_to(rim_height); rim_width=wallthickness/2+local_rim_tolerance+rim_tolerance; sweep_sketch= [ [-local_rim_height*2-local_rim_tolerance+rim_tolerance/2, 0], [-local_rim_tolerance+rim_tolerance/2, local_rim_height*2+local_rim_tolerance], [rim_width-rim_offset, local_rim_height*2+local_rim_tolerance], [rim_width+rim_offset*2, 0],]; if(rim&&closure_type!="snap rim") difference(){ down(local_rim_height) path_sweep( left(rim_tolerance,sweep_sketch),method="manual",relaxed=false, final_path,closed=true); if(hinge) up(outerZ-true_hinge_downset+local_rim_tolerance) back(innerY/2-inner_fillet/3) prismoid( size1=[outerX,outerY-local_rim_height*10], size2=[outerX,outerY], h=local_rim_height*3, anchor=FWD); if(!hinge&&closure_type=="magnets") up(outerZ-true_hinge_downset+local_rim_tolerance-local_rim_height*2) back((innerY+t_wallthickness)/2) prismoid( size1=[lip_length-local_rim_height*4,t_wallthickness], size2=[lip_length+local_rim_height*4,t_wallthickness*2], h=local_rim_height*4, anchor=BOT); if(closure_type=="magnets") up(outerZ-lip_outer_downset+local_rim_tolerance-local_rim_height*2) fwd((innerY+t_wallthickness)/2) prismoid( size1=[lip_length-local_rim_height*2,t_wallthickness], size2=[lip_length+local_rim_height*6,t_wallthickness*2], h=local_rim_height*4, anchor=BOT); } } module printable_box(){ // Rysowanie zatrzasku (klipsa) if (show_only_latch) { // Sam klips wysrodkowany na stole latch(just_latch=true); } else if (!show_only_lid && !show_only_box && !show_only_latch) { // Klips obok pudelka (gdy drukujemy calosc) zrot(outerX>outerY?90:0) fwd(max(outerX,outerY)/2+ latch_length) latch(just_latch=true); } // Rysowanie pudelka i pokrywki (pomijane, gdy chcemy sam klips) if (!show_only_latch) { if(lid) { if(hinge){ if(hinge_type=="print in place") pip_box_assembled(); if(hinge_type=="pin") pin_box_assembled(); if(hinge_type=="snap") snap_box_assembled(); } else { unhinged_box_assembled(); } } else { if (!show_only_lid) { lidless_body(); } } } } module rotary_tolerance_booltool(is_lid=false,is_pin=true){ last_barrel_number=ceil(barrel_count/2)-1; extra_barrel_length = hinge_type!="print in place"?outer_fillet:0; local_barrel_count=!is_lid?ceil(barrel_count/2):floor(barrel_count/2); module neg_barrel(is_lid=false,barrel_number){ true_barrel_length=!is_lid&&barrel_number==0||barrel_number==last_barrel_number?barrel_length+extra_barrel_length:barrel_length; barrel_placement_fix=!is_lid&&barrel_number==0?extra_barrel_length: barrel_number==last_barrel_number?-extra_barrel_length: 0; boolsketch = union( make_region(circle(d=dbarrel+barrel_rotary_tolerance*2)), hinge_type!="print in place"? trapezoid(h=dbarrel,w2=dbarrel+barrel_rotary_tolerance*2,ang=90-extra_clearance,anchor=TOP,spin=180) : undef ); left(barrel_placement_fix/2) yrot(90) offset_sweep(boolsketch, l=true_barrel_length+(hinge_type!="print in place"?barrel_chamfer*2+barrel_tolerance*2:dbarrel),anchor=FWD,ends=os_chamfer(width=(hinge_type!="print in place"?barrel_chamfer:dbarrel/2))); } up((is_lid?outerZ-true_hinge_downset:true_hinge_upset)+(hinge_type!="print in place"?dbarrel/2:0)) back(outerY/2-(hinge_type!="print in place"?dbarrel:(pip_barrel_outset*dbarrel/2)+barrel_rotary_tolerance)) xcopies(n=floor(local_barrel_count), spacing=barrel_length*2) neg_barrel(is_lid=is_lid,barrel_number=$idx); } module pause_reminder(pause_height){ magnet_depth=magnet_type=="cylinder"?cylinder_diameter:box_depth; true_magnet_depth=magnet_depth+magnet_wallthickness*2-t_wallthickness; outset_fix= Y_magnet_alignment=="center"?true_magnet_depth/2: Y_magnet_alignment=="outside"?true_magnet_depth:0; font_size=outerX/10; font_height=0.0005; if(magnet_pause_helper) if(closure_type=="magnets") translate([0,-outerY/2-outset_fix,pause_height+layer_height/PI]){ text3d(text=str("pause here for magnet"),anchor=BACK,h=font_height,size=font_size/2); fwd(font_size) text3d(text=str(pause_height," mm"),anchor=BACK,h=font_height,size=font_size*2); back(font_size) cube([font_height,font_size*3.75,font_height],anchor=BACK); fwd(font_size*0.48) cube([outerX,0.0001,font_height],anchor=BACK); fwd(font_size*2.75) cube([outerX,0.0001,font_height],anchor=BACK); } } module magnet_array(is_lid=false,for_bool=false){ lid_mirror=is_lid?1:0; center_halfer=Y_magnet_alignment=="center"?0.5:1; inner_c_d=cylinder_diameter+magnet_tolerance*2; outer_c_d=inner_c_d+magnet_wallthickness*2; inner_c_h=cylinder_height+magnet_tolerance*2; outer_c_h=inner_c_h+magnet_top_buffer*2; inner_b_h=box_height+magnet_tolerance*2; outer_b_h=inner_b_h+magnet_top_buffer*2; inner_b_d=box_depth+magnet_tolerance*2; outer_b_d=inner_b_d+magnet_wallthickness*2; inner_b_l=box_length+magnet_tolerance*2; outer_b_l=inner_b_l+magnet_wallthickness*2; final_magnet_depth=magnet_type=="cylinder"?outer_c_d:outer_b_d; final_magnet_width=magnet_type=="cylinder"?outer_c_d:outer_b_l; final_magnet_height=magnet_type=="cylinder"?outer_c_h:outer_b_h; magnet_array_width = magnet_array_width_factor*(lip_length-final_magnet_width); magnet_count=ceil((magnet_array_width)/(minimum_magnet_gap+final_magnet_width)); texture_fix=Y_magnet_alignment=="inside"?exterior_type=="textured"?t_wallthickness-abs(tex_depth):0:0; Y_magnet_alignment_offset= Y_magnet_alignment=="center"?0: Y_magnet_alignment=="outside"?final_magnet_depth/2-t_wallthickness/2+epsilon: exterior_type=="textured"?-abs(tex_depth)-final_magnet_depth/2+t_wallthickness/2-epsilon: -final_magnet_depth/2+t_wallthickness/2-epsilon; module magnet_support_tool(){ back(texture_fix) back(Y_magnet_alignment_offset) cuboid([final_magnet_width,0.1, center_halfer*final_magnet_depth+final_magnet_height],anchor=TOP, chamfer=magnet_chamfer,edges="Y"); } module magnet_hole(){ down(magnet_top_buffer*2) cube([.001,final_magnet_depth*1.1,.001],anchor=TOP);//so the hole doesn't fall out down(magnet_top_buffer) if(magnet_type=="cylinder") cylinder(d=inner_c_d,h=inner_c_h,anchor=TOP); else cube([inner_b_l,inner_b_d,inner_b_h],anchor=TOP); } module magnet_shell(){ hull(){ magnet_support_tool(); if(magnet_type=="cylinder") cyl(d=outer_c_d,h=outer_c_h,anchor=TOP,chamfer=magnet_chamfer); else cuboid([outer_b_l+magnet_chamfer*2,outer_b_d,outer_b_h], anchor=TOP,chamfer=magnet_chamfer); } } module assembled(){ up(lid_tolerance_offset*lid_mirror){ fwd(outerY/2-t_wallthickness/2) up(is_lid?lip_outer_upset:lip_outer_upset) fwd(Y_magnet_alignment_offset) if(closure_type=="magnets") mirror([0,0,lid_mirror]){ if(for_bool) xcopies(n=magnet_count,l=magnet_array_width) magnet_hole(); if(!for_bool) if(connect_magnets)hull() xcopies(n=magnet_count,l=magnet_array_width) magnet_shell(); else xcopies(n=magnet_count,l=magnet_array_width) magnet_shell(); } } } assembled(); if(!hinge) mirror([0,1,0]) up(lip_kathete) assembled(); } module pip_box_assembled(){ if (!show_only_lid) { fwd(pip_barrel_alignment_offset) fwd(outerY/2) fwd(pip_body_lid_tolerance/2) union(){ pip_body(); pause_reminder(lip_outer_upset-magnet_top_buffer); } } if (!show_only_box) { back(pip_barrel_alignment_offset) back(pip_body_lid_tolerance/2) back(outerY/2){ up(stacking_fix*2) up(outerZ) xrot(180) pip_lid(); zrot(180) pause_reminder(lip_outer_downset-magnet_top_buffer); } } } module pip_body(){ intersection(){ difference(){ union(){ difference(){ final_shell(); lid_bool_tool(is_lid=false); rotary_tolerance_booltool(is_pin=false); pip_barrel_array(is_lid=false,is_bool=true); } pip_barrel_array(); magnet_array(is_lid=false,for_bool=false); } magnet_array(is_lid=false,for_bool=true); } cube([outerX*3,outerY*3,outerZ],anchor=BOT); } } module pip_lid(){ intersection(){ difference(){ union(){ difference(){ intersection(){ final_shell(); lid_bool_tool(is_lid=true); } rotary_tolerance_booltool(is_pin=false,is_lid=true); pip_barrel_array(is_lid=true,is_bool=true); } magnet_array(is_lid=true,for_bool=false); pip_barrel_array(is_lid=true); } up(epsilon) magnet_array(is_lid=true,for_bool=true); } cube([outerX*3,outerY*3,outerZ*2],anchor=BOT); } } module pip_barrel(is_lid=false,is_bool=false,barrel_number){ pip_cone_offset=nozzle_diameter; local_lid_tolerance_offset=is_lid?lid_tolerance_offset:0; tangent_factor=sqrt(2)/2; bool_mirror=is_bool?1:0; lid_mirror=is_lid?1:0; back(dbarrel/2) back(pip_barrel_alignment_offset) union(){ difference(){ union(){ //creates the barrel without a hole yrot(90) //barrel cyl(l=barrel_length-barrel_tolerance*2,d=dbarrel,chamfer=barrel_chamfer,anchor=CENTER); shape = [ [-local_lid_tolerance_offset,0], [-tangent_factor*dbarrel/2,-tangent_factor*dbarrel/2], [-2*tangent_factor*dbarrel/2-pip_barrel_alignment_offset-t_wallthickness, pip_barrel_alignment_offset+t_wallthickness], [-local_lid_tolerance_offset,t_wallthickness+pip_barrel_alignment_offset] ]; mirror([0,bool_mirror,0]) mirror([0,0,lid_mirror]) left(barrel_length/2-barrel_tolerance) rot([0,-90,180]) offset_sweep(shape, height=barrel_length-barrel_tolerance*2, ends=os_chamfer(width=barrel_chamfer)); } //negative cone slot if(!(barrel_number==0&&is_lid)) left(barrel_length/2-barrel_tolerance+epsilon) cyl(d1=0,d2=dbarrel-barrel_chamfer*2-pip_cone_offset, l=(dbarrel-barrel_chamfer*2-pip_cone_offset)/2, anchor=TOP,orient=LEFT); } //positve cone right(barrel_length/2-barrel_tolerance-epsilon) cyl(d1=pip_cone_offset,d2=dbarrel-barrel_chamfer*2-pip_cone_offset*2, l=(dbarrel-barrel_chamfer*2-pip_cone_offset*3)/2, anchor=TOP,orient=LEFT); } } module pip_barrel_array(is_lid=false,is_bool=false){ fakeable_is_lid=is_bool?!is_lid:is_lid; local_barrel_count=fakeable_is_lid?ceil(barrel_count/2):floor(barrel_count/2); up(true_hinge_upset) //right(hinge_length/2) back(outerY/2-dbarrel/2) xflip_copy() left_half() xcopies(n=floor(local_barrel_count), spacing=barrel_length*2) pip_barrel(is_lid=is_lid,is_bool=is_bool,barrel_number=$idx); } module snap_box_assembled(){ distribute(l=min(outerX,outerY)+8,dir=outerX>outerY?FWD:RIGHT){ if (!show_only_lid) { union(){ snap_body(); pause_reminder(lip_outer_upset-magnet_top_buffer); }; } if (!show_only_box) { union(){ up(stacking_fix*2) up(outerZ) rot([0,180,0]) snap_lid(); pause_reminder(lip_outer_downset-magnet_top_buffer); } } } } module snap_body(){ intersection(){ difference(){ union(){ difference(){ final_shell(); lid_bool_tool(is_lid=false); rotary_tolerance_booltool(is_pin=true); } snap_barrel_array(is_lid=false); magnet_array(is_lid=false,for_bool=false); } magnet_array(is_lid=false,for_bool=true); } cube([outerX*3,outerY*3,outerZ],anchor=BOT); } } module snap_lid(){ intersection(){ difference(){ union(){ difference(){ intersection(){ final_shell(); lid_bool_tool(is_lid=true,is_pin=true); } rotary_tolerance_booltool(is_pin=true,is_lid=true); } magnet_array(is_lid=true,for_bool=false); snap_barrel_array(is_lid=true); } up(epsilon) magnet_array(is_lid=true,for_bool=true); } cube([outerX*3,outerY*3,outerZ+stacking_fix*2],anchor=BOT); } } module snap_barrel(is_lid=false,barrel_number){ snap_cone_offset=.3+nozzle_diameter/4; tangent_factor=sqrt(2)/2; lid_mirror=is_lid?1:0; last_barrel_number=ceil(barrel_count/2)-1; extra_barrel_length = outer_fillet; true_barrel_length=is_lid&&barrel_number==0||barrel_number==last_barrel_number?barrel_length+extra_barrel_length:barrel_length; barrel_placement_fix=is_lid&&barrel_number==0?extra_barrel_length: barrel_number==last_barrel_number?-extra_barrel_length: 0; true_hole_length=is_lid&&barrel_number==0||barrel_number==last_barrel_number?barrel_length/2:barrel_length; hole_placement_fix=is_lid&&barrel_number==0?barrel_length/4: barrel_number==last_barrel_number?-barrel_length/4: 0; function sign2(input) = sign(input)==0?1:sign(input); module positive_cone(){ cyl(d1=snap_cone_offset*3,d2=dbarrel-barrel_chamfer*2-snap_cone_offset*1, l=(dbarrel-barrel_chamfer*2-snap_cone_offset*4)/2, anchor=TOP,orient=LEFT,chamfer1=snap_cone_offset/2,chamfang1=35); cyl(d=dbarrel-barrel_chamfer*2-snap_cone_offset*1, l=barrel_length/3,anchor=TOP,orient=RIGHT); } back(pin_barrel_alignment_offset) difference(){ union(){ hull(){ //creates the barrel without a hole left(barrel_placement_fix/2) xcyl(l=true_barrel_length-barrel_tolerance*2,d=dbarrel,chamfer=barrel_chamfer,anchor=CENTER); if(is_lid==false) //for the main body fwd(pin_barrel_alignment_offset) //thing so it connects nicely cuboid([ barrel_length-barrel_tolerance*2, t_wallthickness,dbarrel/2+barrel_rotary_tolerance+barrel_chamfer], anchor=TOP,chamfer=barrel_chamfer) cuboid([ barrel_length-barrel_tolerance*2, t_wallthickness/2,dbarrel], anchor=TOP+BACK); if(is_lid==true){ //needs some extro logic for offset=outer_chamfer){ local_tex_depth=exterior_type=="basic"?0:abs(tex_depth); shape = hull_region([ [0,dbarrel/2], [0,0], [0,-dbarrel/2], [dbarrel/2+barrel_chamfer,-dbarrel/2], [dbarrel/2+barrel_chamfer+local_tex_depth,-dbarrel/2+local_tex_depth], [dbarrel/2+barrel_rotary_tolerance*3,-max(dbarrel-t_wallthickness,0)/2], [dbarrel/2+max(dbarrel-t_wallthickness,0)/2+barrel_chamfer,-dbarrel/2+min(t_wallthickness,dbarrel)], ]); left(barrel_placement_fix/2) rot([0,-90,180]) offset_sweep(shape, height=true_barrel_length-barrel_tolerance*2, ends=os_chamfer(width=barrel_chamfer),anchor="zcenter"); } else { shape = [ [tangent_factor*dbarrel/2,tangent_factor*dbarrel/2], [0,0], [tangent_factor*dbarrel/2,-tangent_factor*dbarrel/2], [dbarrel/2,-dbarrel/2+outer_chamfer-hinge_height_offset], [hinge_height_offset+dbarrel/2,hinge_height_offset], [hinge_height_offset+dbarrel/2,barrel_chamfer+max(outer_chamfer,dbarrel+barrel_rotary_tolerance)-dbarrel/2], [hinge_height_offset+dbarrel/2-wallthickness,barrel_chamfer+dbarrel/2+barrel_rotary_tolerance], ]; left(barrel_placement_fix/2) rot([0,-90,180]) offset_sweep(hull_region(shape), height=true_barrel_length-barrel_tolerance*2, ends=os_chamfer(width=barrel_chamfer),anchor="zcenter"); } } }//hull ends and union starts //if(!is_lid) xflip_copy(barrel_length/2-barrel_tolerance-epsilon) if(($idx==1&&!is_lid)||($idx==1&&is_lid)) positive_cone(); }//union ends and difference starts //if(is_lid) xflip_copy() //if(!((barrel_number==0&&$idx!=1)||(barrel_number==last_barrel_number&&$idx!=0))) if((is_lid&&$idx==1)||(!is_lid&&$idx==1)) right(-barrel_length/2+barrel_tolerance-epsilon) union(){ cyl(d1=0,d2=dbarrel-barrel_chamfer*2-snap_cone_offset, l=(dbarrel-barrel_chamfer*2-snap_cone_offset)/2, anchor=TOP,orient=LEFT); //hull carves for the kegs to slot in chain_hull(){ right(snap_hinge_tolerance-barrel_tolerance*2) positive_cone(); slot_offset = polar_to_xy([dbarrel/2,is_lid?0:-90]); move([0,slot_offset[0],-slot_offset[1]]) right(snap_hinge_tolerance-(barrel_tolerance*2)) positive_cone(); move([dbarrel/2,slot_offset[0]*2,-slot_offset[1]*2]) right(snap_hinge_tolerance-(barrel_tolerance*2)) positive_cone(); } } //for clean outer barrels on the lid down(outerZ/2-true_hinge_downset+dbarrel/2) fwd(pin_barrel_alignment_offset) back(t_wallthickness/2) if(is_lid){ X_offset=barrel_length/2-(exterior_type!="basic"? min(abs(tex_depth)*2,outer_fillet):0); if(barrel_number==0) left(barrel_placement_fix) left(X_offset) rounding_edge_mask(l=outerZ,excess=dbarrel+abs(tex_depth)*2, r=outer_fillet,spin=-90,chamfer=outer_chamfer) cuboid([outerY,dbarrel,outerZ],chamfer=-outer_chamfer,anchor=BACK) ; if(barrel_number==last_barrel_number) left(barrel_placement_fix) right(X_offset) rounding_edge_mask(l=outerZ,excess=dbarrel+abs(tex_depth)*2, r=outer_fillet,spin=180,chamfer=outer_chamfer) cuboid([dbarrel,outerY,outerZ],chamfer=-outer_chamfer,anchor=RIGHT) ; } } } module snap_barrel_array(is_lid=false){ local_barrel_count=is_lid?ceil(barrel_count/2):floor(barrel_count/2); //orient the first barrel to the back left up(true_hinge_upset+dbarrel/2) //right(-outerX/2+outer_fillet) back(outerY/2-t_wallthickness/2) xflip_copy() left_half() xcopies(n=floor(local_barrel_count), spacing=barrel_length*2) snap_barrel(is_lid=is_lid,barrel_number=$idx); } module pin_box_assembled(){ distribute(l=min(outerX,outerY)+8,dir=outerX>outerY?FWD:RIGHT){ if (!show_only_lid) { union(){ pin_body(); pause_reminder(lip_outer_upset-magnet_top_buffer); }; } if (!show_only_box) { union(){ up(stacking_fix*2) up(outerZ) rot([0,180,0]) pin_lid(); pause_reminder(lip_outer_downset-magnet_top_buffer); } } } } module pin_body(){ intersection(){ difference(){ union(){ difference(){ final_shell(); lid_bool_tool(is_lid=false); rotary_tolerance_booltool(is_pin=true); } pin_barrel_array(is_lid=false); magnet_array(is_lid=false,for_bool=false); } magnet_array(is_lid=false,for_bool=true); } cube([outerX*3,outerY*3,outerZ],anchor=BOT); } } module pin_lid(){ intersection(){ difference(){ union(){ difference(){ intersection(){ final_shell(); lid_bool_tool(is_lid=true,is_pin=true); } rotary_tolerance_booltool(is_pin=true,is_lid=true); } magnet_array(is_lid=true,for_bool=false); pin_barrel_array(is_lid=true); } pin_hole(); up(epsilon) magnet_array(is_lid=true,for_bool=true); } cube([outerX*3,outerY*3,outerZ+stacking_fix*2],anchor=BOT); } } module pin_barrel(is_lid=false,barrel_number){ tangent_factor=sqrt(2)/2; lid_mirror=is_lid?1:0; last_barrel_number=ceil(barrel_count/2)-1; extra_barrel_length = outer_fillet; true_barrel_length=is_lid&&barrel_number==0||barrel_number==last_barrel_number?barrel_length+extra_barrel_length:barrel_length; barrel_placement_fix=is_lid&&barrel_number==0?extra_barrel_length: barrel_number==last_barrel_number?-extra_barrel_length: 0; true_hole_length=is_lid&&barrel_number==0||barrel_number==last_barrel_number?barrel_length/2:barrel_length; hole_placement_fix=is_lid&&barrel_number==0?barrel_length/4: barrel_number==last_barrel_number?-barrel_length/4: 0; function sign2(input) = sign(input)==0?1:sign(input); back(pin_barrel_alignment_offset) difference(){ hull(){ //creates the barrel without a hole left(barrel_placement_fix/2) xcyl(l=true_barrel_length-barrel_tolerance*2,d=dbarrel,chamfer=barrel_chamfer,anchor=CENTER); if(is_lid==false) //for the main body fwd(pin_barrel_alignment_offset) //thing so it connects nicely cuboid([ barrel_length-barrel_tolerance*2, t_wallthickness,dbarrel/2+barrel_rotary_tolerance+barrel_chamfer], anchor=TOP,chamfer=barrel_chamfer) cuboid([ barrel_length-barrel_tolerance*2, t_wallthickness/2,dbarrel], anchor=TOP+BACK); if(is_lid==true){ //needs some extro logic for offsetouter_chamfer){ local_tex_depth=exterior_type=="basic"?0:abs(tex_depth); shape = hull_region([ [0,dbarrel/2], [0,0], [0,-dbarrel/2], [dbarrel/2+barrel_chamfer,-dbarrel/2], [dbarrel/2+barrel_chamfer+local_tex_depth,-dbarrel/2+local_tex_depth], [dbarrel/2+barrel_rotary_tolerance*3,-max(dbarrel-t_wallthickness,0)/2], [dbarrel/2+max(dbarrel-t_wallthickness,0)/2+barrel_chamfer,-dbarrel/2+min(t_wallthickness,dbarrel)], ]); left(barrel_placement_fix/2) rot([0,-90,180]) offset_sweep(shape, height=true_barrel_length-barrel_tolerance*2, ends=os_chamfer(width=barrel_chamfer),anchor="zcenter"); } else { shape = [ [tangent_factor*dbarrel/2,tangent_factor*dbarrel/2], [0,0], [tangent_factor*dbarrel/2,-tangent_factor*dbarrel/2], [dbarrel/2,-dbarrel/2+outer_chamfer-hinge_height_offset], [hinge_height_offset+dbarrel/2,hinge_height_offset], [hinge_height_offset+dbarrel/2,barrel_chamfer+max(outer_chamfer,dbarrel+barrel_rotary_tolerance)-dbarrel/2], [hinge_height_offset+dbarrel/2-wallthickness,barrel_chamfer+dbarrel/2+barrel_rotary_tolerance], ]; left(barrel_placement_fix/2) rot([0,-90,180]) offset_sweep(hull_region(shape), height=true_barrel_length-barrel_tolerance*2, ends=os_chamfer(width=barrel_chamfer),anchor="zcenter"); } } } //chamfered teardrop hole right(hole_placement_fix) yrot(180*lid_mirror) zrot(-90) teardrop(d=dpin, l=true_hole_length-barrel_tolerance*2+epsilon,ang=55, chamfer1=-barrel_chamfer*sign2(barrel_placement_fix), chamfer2=-barrel_chamfer*sign2(-barrel_placement_fix)); down(outerZ/2-true_hinge_downset+dbarrel/2) fwd(pin_barrel_alignment_offset) back(t_wallthickness/2) if(is_lid){ X_offset=barrel_length/2-(exterior_type!="basic"? min(abs(tex_depth)*2,outer_fillet):0); if(barrel_number==0) left(barrel_placement_fix) left(X_offset) rounding_edge_mask(l=outerZ,excess=dbarrel+abs(tex_depth)*2, r=outer_fillet,spin=-90,chamfer=outer_chamfer) cuboid([outerY,dbarrel,outerZ],chamfer=-outer_chamfer,anchor=BACK) ; if(barrel_number==last_barrel_number) left(barrel_placement_fix) right(X_offset) rounding_edge_mask(l=outerZ,excess=dbarrel+abs(tex_depth)*2, r=outer_fillet,spin=180,chamfer=outer_chamfer) cuboid([dbarrel,outerY,outerZ],chamfer=-outer_chamfer,anchor=RIGHT) ; } } } module pin_barrel_array(is_lid=false){ local_barrel_count=is_lid?ceil(barrel_count/2):floor(barrel_count/2); //orient the first barrel to the back left up(true_hinge_upset+dbarrel/2) //right(-outerX/2+outer_fillet) back(outerY/2-t_wallthickness/2) xcopies(n=floor(local_barrel_count), spacing=barrel_length*2) pin_barrel(is_lid=is_lid,barrel_number=$idx); } module lid_bool_tool(is_lid=false,is_pin=false){ //alignment to the back of the local_lid_bool=is_lid?1:0; difference(){ //up(lid_tolerance_offset*local_lid_bool) down(is_lid?0:min_tolerance) union(){ shape = [ [outerZ-lip_outer_downset,innerY/2-innerY*lip_inset], [outerZ-true_hinge_downset,-innerY/2+innerY*hinge_inset], [outerZ-true_hinge_downset,-outerY], [outerZ*2,-outerY], [outerZ*2,outerY], [outerZ-lip_outer_downset,outerY+max(cylinder_diameter+box_depth,0)]]; radii = [true_lip_inset_rounding,true_hinge_inset_rounding,0,0,0,0]; //color("teal") rot([0,-90,180]) linear_extrude(outerX*3,center=true)polygon(round_corners(shape, radius = radii)); snap_rim(is_lid=is_lid); }; rim(is_lid); //this carves out space for the barrel array if(is_lid&&is_pin){ barrel_cutter_length=min(hinge_length-barrel_chamfer*2-barrel_tolerance*2-epsilon,innerX); //stops before carving into the top wall up(outerZ-max(true_hinge_downset-dbarrel+(dividers?divider_chamfer:0),wallthickness)) back(outerY/2-dbarrel) // //back(outerY/2-dbarrel-inner_chamfer*2) // //fwd(inner_chamfer*2) cuboid([barrel_cutter_length,outerY,outerY],//rounding=dbarrel/2, anchor=TOP+FRONT); //this then overtakes and carves with a rounded edge up(outerZ-true_hinge_downset+dbarrel) back(outerY/2-t_wallthickness/2+pin_barrel_alignment_offset-dbarrel/2) fwd(barrel_rotary_tolerance) cuboid([barrel_cutter_length,outerY,outerY], rounding=hinge_height_offset==0?0:dbarrel/2, anchor=TOP+FRONT,edges=TOP+FRONT); //rounding for smooth rotation up(outerZ-true_hinge_downset) back(outerY/2-t_wallthickness/2+dbarrel/2) back(pin_barrel_alignment_offset) xrot(90) yrot(-90) rounding_edge_mask(l=outerX, r=dbarrel/2,excess=2); } } } module unhinged_box_assembled(){ distribute(l=min(outerX,outerY)+8,dir=outerX>outerY?FWD:RIGHT){ if (!show_only_lid) { union(){ unhinged_body(); pause_reminder(lip_outer_upset-magnet_top_buffer); } } if (!show_only_box) { union(){ up(stacking_fix*2) up(outerZ) rot([0,180,0]) unhinged_lid(); pause_reminder(lip_outer_downset-magnet_top_buffer); } } } } module unhinged_body(){ intersection(){ difference(){ union(){ difference(){ final_shell(); lid_bool_tool(is_lid=false); } magnet_array(is_lid=false,for_bool=false); } magnet_array(is_lid=false,for_bool=true); } cube([outerX*3,outerY*3,outerZ],anchor=BOT); } } module unhinged_lid(){ intersection(){ difference(){ union(){ intersection(){ final_shell(); lid_bool_tool(is_lid=true); } magnet_array(is_lid=true,for_bool=false); } magnet_array(is_lid=true,for_bool=true); } cube([outerX*3,outerY*3,true_outerZ],anchor=BOT); } } module lidless_body(){ final_shell(); } module cached_shell() { // Convexity helps OpenSCAD preview not look "glitchy" with complex holes render(convexity=10) final_shell(); } module final_shell(){ // convexity helps OpenSCAD preview (F5) render the inside of hollow objects correctly. // A value of 10-20 is usually safe for complex shells. difference(){ union(){ render(convexity=12) { if(exterior_type=="basic") basic_shell(); if(exterior_type=="textured") textured_shell(); if(exterior_type=="complex") complex_shell(); } latch(for_bool=false); if(lid_handle) lid_handle(); } latch(for_bool=true); } } module shell_inside(){ bottom_fill_fix=fill_bottom&&gridfinity_support? -wallthickness+5+layer_height*3:0; stacking_lip_fix=stacking_lip&&gridfinity_support? .8:0; difference(){ union(){ up(wallthickness+bottom_fill_fix) offset_sweep( rect([innerX,innerY],rounding=inner_fillet), height=(lid?innerZ-stacking_lip_fix:innerZ+wallthickness+epsilon)-bottom_fill_fix, bot=os_chamfer(width=inner_chamfer), top=os_chamfer(width=lid?inner_chamfer: gridfinity_support&&stacking_lip?0:-t_wallthickness/3), anchor="base" ); if(gridfinity_support&&stacking_lip){ up(outerZ) prismoid(size1=[outerX-(3.4)*2,outerY-(3.4)*2], size2=[outerX-(2.6)*2,outerY-(2.6)*2], h=0.8, rounding2=1.6/2,anchor=TOP); if(!lid) up(outerZ-.8) prismoid(size2=[outerX-(3.4)*2,outerY-(3.4)*2], size1=[outerX-(3.4+t_wallthickness)*2,outerY-(3.4+t_wallthickness)*2], h=t_wallthickness,anchor=TOP); } } if(dividers) up(wallthickness+bottom_fill_fix) offset_sweep( dividers(),h=innerZ*divider_Z_height-bottom_fill_fix, bot=os_chamfer(width=-divider_chamfer), top=os_chamfer(width=divider_Z_height==1?-divider_chamfer:divider_thickness/3) ); if(gridfinity_support){gridfinity_bottom(is_bool=false);} } } module watermark(){ smallest= 0.00001; text="made by lorenz's Any Box Generator"; yflip_copy(smallest/2) text3d(text, h=smallest,size = smallest, anchor=CENTER,$fn=12); cube([len(text)*smallest*0.72,smallest*4,smallest/2],anchor=CENTER); } module basic_shell(){ difference(){ union(){ offset_sweep( rect([outerX,outerY],rounding=outer_fillet), height=outerZ, bot=os_chamfer(width=gridfinity_support?0:outer_chamfer), top=os_chamfer(width=gridfinity_support&&stacking_lip? 0: lid?outer_chamfer:t_wallthickness/3), anchor="base" ); gridfinity_stacking_lip(); } if(lid_groove) lid_groove(); shell_inside(); gridfinity_bottom(is_bool=true); up(outerZ/2) zflip_copy(outerZ/2) watermark(); } } //self explanotaory true_outerZ=gridfinity_support&&stacking_lip?outerZ+4.75:outerZ; module textured_shell(){ diff_scaled_textures=["hexagon","cubes","noise"]; diff_scaled_tex_factor=in_list(texture_pattern,diff_scaled_textures)?(rotate_texture?1/root3:root3):1; shell_circumference=path_length(Tsketch,closed=true); //calculates how many tiles are wraped around the shell horizontal_tiles=round(shell_circumference/texture_scale); //how big the tiles actually are real_texture_scale=shell_circumference/horizontal_tiles; function ceil_to_tile(value,multiple=real_texture_scale*diff_scaled_tex_factor)=ceil(value/multiple)*multiple; //calculates the height so that the tiles are correctly scaled ideal_height=ceil_to_tile(true_outerZ); rot_var=rotate_texture?90:0; intersection(){ basic_shell(); //texture presets are configured here if(texture_pattern=="cubes") linear_sweep( Tsketch, tex_rot=rot_var, tex_inset=.5, tex_depth=tex_depth, texture=("cubes"), h=ideal_height, tex_samples=round_to((texture_scale*$fn)/60,1), tex_size=[real_texture_scale,real_texture_scale*diff_scaled_tex_factor], style="quincunx" ) ; if(texture_pattern=="hexagon") linear_sweep( Tsketch, tex_rot=rot_var, tex_inset=.5, tex_depth=tex_depth, texture=("hex_grid"), h=ideal_height, tex_samples=round_to((texture_scale*$fn)/60,1), tex_size=[real_texture_scale,real_texture_scale*diff_scaled_tex_factor], style="concave" ); if(texture_pattern=="trunc diamonds") linear_sweep( Tsketch, tex_inset=.5, tex_depth=tex_depth, texture=rotate_texture?texture("trunc_pyramids_vnf",border=0.15):("trunc_diamonds"), h=ideal_height, tex_samples=round_to((texture_scale*$fn)/40,1), tex_size=[real_texture_scale,real_texture_scale], style="concave" ); if(texture_pattern=="diamonds") linear_sweep( Tsketch, tex_inset=.5, tex_depth=tex_depth, texture=rotate_texture?"pyramids_vnf":texture("diamonds_vnf"), h=ideal_height, tex_samples=2, tex_size=[real_texture_scale,real_texture_scale], style="concave" ); if(texture_pattern=="stripes") linear_sweep( Tsketch, tex_rot=rot_var, tex_inset=.5, tex_depth=abs(tex_depth), texture=diag_stripes_vnf(), tex_samples=round_to((texture_scale*$fn)/40,1), h=ideal_height, tex_size=[real_texture_scale,real_texture_scale], style="alt" ); if(texture_pattern=="ribs") linear_sweep( Tsketch, tex_rot=rot_var, tex_inset=.5, tex_depth=tex_depth, texture=texture("trunc_ribs_vnf", gap=1/3, border=1/6), tex_samples=round_to((texture_scale*$fn)/40,1), h=ideal_height, tex_size=[real_texture_scale,real_texture_scale], style="concave" ); if(texture_pattern=="noise") linear_sweep( Tsketch, tex_inset=.5, tex_depth=tex_depth, texture=texture("rough"), h=ceil_to_tile(true_outerZ,multiple=real_texture_scale*8), tex_size=[real_texture_scale*8,real_texture_scale*8], style="convex" ); if(texture_pattern=="wave") linear_sweep( Tsketch, tex_inset=.5, tex_depth=tex_depth, texture=texture("hills",round_to((texture_scale*$fn)/32,1)), h=ideal_height, tex_size=[real_texture_scale,real_texture_scale], style="default" ); if(texture_pattern=="round ribs") linear_sweep( Tsketch, tex_rot=rot_var, tex_inset=.5, tex_depth=tex_depth, texture=half_pillars(), h=ideal_height, tex_samples=rotate_texture?(max(round(texture_scale*$fn/32),2)):2, tex_size=[real_texture_scale,real_texture_scale], ); } ; } module complex_shell(){ inset_fix = 1-((abs(tex_depth)/2)/t_wallthickness); diff_scaled_textures=["hex_scaffold"]; diff_scaled_tex_factor=in_list(complex_pattern,diff_scaled_textures)? sqrt(3):1;//root3*1.07221 shell_circumference=path_length(Tsketch,closed=true); //calculates how many tiles are wraped around the shell horizontal_tiles=round(shell_circumference/complex_scale); //how big the tiles actually are real_complex_scale=shell_circumference/horizontal_tiles; function ceil_to_tile(value,multiple=real_complex_scale*diff_scaled_tex_factor) =ceil(value/multiple)*multiple; //calculates the height so that the tiles are correctly scaled ideal_height=ceil_to_tile(true_outerZ); intersection(){ if(!add_texture_to_complex_shell) basic_shell(); else textured_shell(); union(){ offset_sweep( offset(rect([innerX,innerY],rounding=inner_fillet),r=-epsilon+t_wallthickness*extra_wall), height=outerZ, anchor="base" ); cuboid([outerX,outerY,wallthickness+inner_chamfer],anchor=BOT); if(lid) up(outerZ) cuboid([outerX,outerY,wallthickness+inner_chamfer],anchor=TOP); if(complex_pattern=="weave") linear_sweep( Tsketch, tex_inset=inset_fix, tex_depth=t_wallthickness, texture=diag_weave_vnf(), h=ideal_height, tex_samples=round_to((complex_scale*$fn)/64,1), tex_size=[real_complex_scale,real_complex_scale] ) ; if(complex_pattern=="hex_scaffold") linear_sweep( Tsketch, tex_inset=inset_fix, tex_depth=t_wallthickness, texture=hex_wall(), h=ideal_height, tex_samples=round_to((complex_scale*$fn)/64,1), tex_size=[real_complex_scale,real_complex_scale*root3], spin=180 ) ; if(complex_pattern=="gyroid"){ v_size=1/complex_resolution; vnf= isosurface(function(x,y,z)gyroid(x,y,z, wavelength=1), [-scaffold_thickness*1.2,scaffold_thickness*1.2], 1, voxel_size=v_size,closed=true); up(outerZ/2) zcopies(complex_scale*1,n=ceil(outerZ/complex_scale)) grid_copies(complex_scale,n=[ceil(outerX/complex_scale),ceil(outerY/complex_scale)]) //rot([0,45,0]) resize([complex_scale,complex_scale,complex_scale*1]) vnf_polyhedron(vnf); } ; } } }; module insert_tray(t_outerZ) { t_outerX = innerX - tray_tolerance * 2; t_outerY = innerY - tray_tolerance * 2; t_outer_fillet = max(inner_fillet - tray_tolerance, 0.1); t_inner_fillet = max(t_outer_fillet - tray_wall_thickness, 0.1); difference() { offset_sweep( rect([t_outerX, t_outerY], rounding=t_outer_fillet), height=t_outerZ, bot=os_chamfer(width=1), top=os_chamfer(width=0), anchor="base" ); up(tray_wall_thickness) offset_sweep( rect([t_outerX - tray_wall_thickness*2, t_outerY - tray_wall_thickness*2], rounding=t_inner_fillet), height=t_outerZ + epsilon, bot=os_chamfer(width=0), top=os_chamfer(width=-tray_wall_thickness/3), anchor="base" ); } } // ============================================== // GLOWNE WYWOLANIE (Pudelko albo wkladki) // ============================================== if (show_trays || show_only_tray_1 || show_only_tray_2) { // Oblicza pozostale miejsce na druga wkladke (pod sam zawias) bottom_internal_height = (outerZ - lip_outer_downset) - wallthickness; auto_depth = max(bottom_internal_height - tray_depth - 0.5, 2); if (show_trays) { // Rysuje obie wkladki obok siebie insert_tray(tray_depth); right(outerX + 15) insert_tray(auto_depth); } else if (show_only_tray_1) { // Rysuje tylko pierwsza wkladke (na srodku) insert_tray(tray_depth); } else if (show_only_tray_2) { // Rysuje tylko druga wkladke (na srodku) insert_tray(auto_depth); } } else { // Rysuje standardowe pudelko hsv(h=170,s=.05,v=.8) render() printable_box(); }