Code in blogpost is:
module polyhole(d,h) { n = max(round(2 * d),3); rotate([0,0,180]) cylinder(h = h, r = (d / 2) / cos (180 / n), $fn = n); }
which works, but is not programmer-friendly. Considering its cylinder replacement, it should really work that way - but cylinder has radius as argument, not diameter. Another thing is, its not tab-completition friendly - you have to remember another name, instead of just pressing tab and see. So my fix is
// make it interchangeable between this and cylinder module cylinder_poly(r, h, center=false){ polyhole(d=r*2, h=h, center=center); }
Now when you have hole and realise that polyhole would fit better the change is as simple as it can be.
Another thing that you learn fast is that sharp coners are bad - they tend not to stick well on heatbed destroying overnight prints and tend to look ugly on high speed prints with quick acceleration, making waves on side that is extruded from corner. Good way (except slowing down prints, but who would want to do that? ;)) is corner rounding, or "fillet". As there is no direct way of rounding corners in OpenScad, some work is to be done. Basic building block here is
module fillet(radius, height=100, $fn=16) { //this creates negative of fillet, //i.e. thing to be substracted from object translate([-radius, -radius, -height/2-0.01]) difference() { cube([radius*2, radius*2, height+0.02]); cylinder(r=radius, h=height+0.02, $fn=16); } }
Then miracle happens:
module cube_negative_fillet( size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=0 ){ j=[1,0,1,0]; for (i=[0:3]) { if (radius > -1) { rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(radius, size[2], $fn=$fn); } else { rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) fillet(vertical[i], size[2], $fn=$fn); } rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) fillet(top[i], size[1-j[i]], $fn=$fn); rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) fillet(bottom[i], size[1-j[i]], $fn=$fn); } }
and we have object to substract from your creations to round their corners, positioned in the same way as centered cube. By default, it will round vertical corners to 3mm radius. You can round all four vertical edges with parameter radius or, giving 4 member array to vertical, you can control which edge you want to fillet and how much. You can fillet top side with parameter top too, and of course bottom is there too, even tho it probably will not be nicely printable. (You may use support or pass it $fn=4, then it will have 45deg. chamfer). In all cases, it starts in +x, +y quadrant and goes CCW (first top/bottom fillet crosses +x axis).
Of course, I am lazy so I prepared exact cube replacement:
module cube_fillet_inside( size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=0 ){ if (radius == 0) { cube(size, center=true); } else { difference() { cube(size, center=true); cube_negative_fillet(size, radius, vertical, top, bottom, $fn); } } } module cube_fillet( size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], center=false, $fn=0 ){ if (center) { cube_fillet_inside(size, radius, vertical, top, bottom, $fn); } else { translate([size[0]/2, size[1]/2, size[2]/2]) cube_fillet_inside(size, radius, vertical, top, bottom, $fn); } }
Coming soon: Screws and NEMA stepper interface.
Thanks to nophead, vlnofka and josefprusa