include ; $fn = $preview ? 32 : 128; band_arc_radius = 65; thickness = 3; height = 10; band_arc = 240; leg_length = 27; edge_radius = 0.5; punch_angles = [-95, -70, -45, 0, 45, 70, 95]; tooth_width=2; tooth_height=2.5; teeth_max_angle = 110; teeth_spacing = 2.5; punch_clearance = 5; module tooth() { cyl( d1=tooth_width, d2=edge_radius*2, h=tooth_height, rounding2=edge_radius, anchor=BOT, orient=FWD ); } module punch() { region = right( 1, p=rect( [height/2+1, height/2], rounding=height/4, anchor=LEFT ) ); linear_sweep( [region, xflip(region)], length=thickness+2, center=true, orient=BACK ); } module band() { region = right( band_arc_radius, p=rect( [thickness, height], rounding=edge_radius ) ); rotate_sweep( region, angle=band_arc, spin=-band_arc/2+90 ); } module leg() { rotate(-band_arc/2+90) right(band_arc_radius) cuboid( [thickness, leg_length, height], rounding=edge_radius, edges="Y", anchor=BACK ) attach(FWD) xcyl( thickness, d=height, rounding=edge_radius ); } difference() { union() { band(); leg(); xflip() leg(); } for(a=punch_angles) { zrot(a) back(band_arc_radius) punch(); } } for(a=[-teeth_max_angle:teeth_spacing:teeth_max_angle]) { if(all([ for (b=punch_angles) abs(b - a) > punch_clearance ])) { zrot(a) back(band_arc_radius-thickness/2+0.1) { up(height/4) tooth(); down(height/4) tooth(); }; } }