//This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. //2015 - B.E. Morgan include ; thickness = 3; inner_diameter_1=29; //outer diameter of bottle cap inner_diameter_2=26; //smallest diameter under bottle cap hole_diameter=18; //diameter of hole above the bottle cap ring_height=9; //position of ring that fits below bottle cap overall_height=20; //overall height of the lock chamfer=0.5; //size of chamfers on external corners $fn=60; //hinge parameters hinge_r1=4.5; hinge_r2=20; hinge_theta_0=90; //font should be bold and fixed-width font="Consolas:style=Bold"; font_size=5; //block with hole for the padlock lock_holder_thickness=8; lock_holder_length=12; //parameters to control size and postion of teardrop hole for lock shackle lock_hole_r=3; lock_inner_diameter=9; tol = 0.5; //Text for top and bottom pieces. The font should be a fixed-width font since the characters are placed at equal angles. The ratios control what fraction of each semicircle the text requires. This allows you to squeeze the letters closer together or push them farther apart. A ratio of 1 would allow the text to span all 180 degrees of its semicircle. s1 = ["H","E","L","L","O"]; s1_ratio=0.5; s2 = ["W","O","R","L","D"]; s2_ratio=0.5; epsilon = 0.1; bottle_lock(); module bottle_lock() { difference() { //basic shape union() { hull() { //big cylinder chamfered_cylinder(r=inner_diameter_1/2+thickness,h=overall_height,l=chamfer); //little hinge cylinder translate([inner_diameter_1/2+hinge_r1,0,0]) chamfered_cylinder(r=hinge_r1,h=overall_height,l=chamfer); } //padlock holder block translate([-lock_holder_length-inner_diameter_1/2,-lock_holder_thickness/2,0]) chamfered_cube(x=lock_holder_length,y=lock_holder_thickness,z=overall_height,l=chamfer); } //hinge cut translate([inner_diameter_1/2+hinge_r1,0,0]) rotate(-hinge_theta_0/2+180) vertical_hinge_negative(tol=tol,r1=hinge_r1,r2=hinge_r2,height=overall_height/2,n=2,$fn=60,theta0=hinge_theta_0,theta1=90, theta2=90); //straight cut through the lock that runs from the hinge to the opposite side rotate(180) translate([-12,-tol*sqrt(2)/2,-overall_height/2]) cube(size=[lock_holder_length*2+inner_diameter_1,tol*sqrt(2),overall_height*2]); //interior space cut from the lock. Includes the ring that fits below the bottle cap rotate_extrude() polygon([ [0,-epsilon], [0,overall_height+epsilon], [inner_diameter_1/2+chamfer+epsilon,overall_height+epsilon], [inner_diameter_1/2,overall_height-chamfer], //ring [inner_diameter_1/2,thickness+ring_height+(inner_diameter_1-inner_diameter_2)/2], [inner_diameter_2/2,thickness+ring_height], [inner_diameter_1/2,thickness+ring_height-(inner_diameter_1-inner_diameter_2)/2], [inner_diameter_1/2,thickness], [hole_diameter/2+chamfer,thickness], [hole_diameter/2,thickness-chamfer], [hole_diameter/2,chamfer], [hole_diameter/2+chamfer+epsilon,-epsilon], ]); //teardrop lock shackle hole translate([-inner_diameter_1/2-lock_holder_length/2-thickness/3,0,overall_height-lock_inner_diameter]) rotate([90,0,0]) { cylinder(r=lock_hole_r,h=2*inner_diameter_2,center=true); translate([0,0,-inner_diameter_2]) rotate([0,0,45]) cube(size=[lock_hole_r,lock_hole_r,inner_diameter_2*2]); } //text rotate(90) mirror([0,1,0]) translate([0,0,-epsilon]) linear_extrude(thickness/4+epsilon) top_text(); } } module chamfered_cube(x=10,y=30,z=20,l=0.3,center=false) { if(center) { chamfered_cube_0(x,y,z,l); } else { translate([x/2,y/2,z/2]) chamfered_cube_0(x,y,z,l); } } module chamfered_cube_0(x,y,z,l) { difference() { cube(size=[x,y,z],center=true); for(yy=[-y/2,y/2]) for(zz=[-z/2,z/2]) translate([0,yy,zz]) rotate([45,0,0]) cube(size=[x+l,2*l,2*l],center=true); for(xx=[-x/2,x/2]) for(yy=[-y/2,y/2]) translate([xx,yy,0]) rotate([0,0,45]) cube(size=[2*l,2*l,z+l],center=true); for(xx=[-x/2,x/2]) for(zz=[-z/2,z/2]) translate([xx,0,zz]) rotate([0,45,0]) cube(size=[2*l,y+l,2*l],center=true); } } module chamfered_cylinder(r,h,l,center=false) { rotate_extrude() { if(center==false) polygon([[0,0],[r-l,0],[r,l],[r,h-l],[r-l,h],[0,h]]); else translate([0,-h/2]) polygon([[0,0],[r-l,0],[r,l],[r,h-l],[r-l,h],[0,h]]); } } module top_text() { for(x=[0:len(s1)-1]) { rotate(-(x+0.5)*180*s1_ratio/len(s1)-90*(1-s1_ratio)) translate([0,(hole_diameter+inner_diameter_1+2*thickness)/4]) text(s1[x], font=font,size=font_size,valign="center",halign="center"); } for(x=[0:len(s2)-1]) { rotate((x+0.5)*180*s2_ratio/len(s2)+90*(1-s2_ratio)) translate([0,(hole_diameter+inner_diameter_1)/4+thickness/2]) rotate(180) text(s2[x], font=font,size=font_size,valign="center",halign="center"); } }