//s=0.001; // Very small number for trivial offsets mm_per_inch=25.4; // Scale by this to make imperial things metric function imp(x)=mm_per_inch*x; // i.e. circle(d=imp(3/8)); for a 3/8" circle M_PI=3.1415926535897932384626433832795028841971693993751058209; // when come back bring... GRID_FINE=0.01; /* Semi-canonical function describing how fn/fs/fa affect the fragments of a circle r */ function fragments(r,fn,fs,fa) = (r < GRID_FINE)?3: (fn > 0.0)?(fn >= 3 ? fn : 3): ceil(max(min(360.0 / fa, r*2*M_PI / fs), 5)); //////////////////////////////////////////////////////////////////////////// //////////////// TRANSFORMATION MATRIX FUNCTIONS /////////////////////////// //////////////////////////////////////////////////////////////////////////// /** * skews: These distort a square into a pallelogram along various axes. */ // Push Y, parallel Z module skew_yz(a) { multmatrix(m= [ [ 1, 0, 0, 0], [tan(a), 1, 0, 0], [ 0, 0, 1, 0], [ 0, 0, 0, 1] ]) children(); } module skew_zy(a) { // Push Z, parallel Y multmatrix(m = [ [1, 0, 0, 0], [0, 1, 0, 0], [tan(a), 0, 1, 0], [0, 0, 0, 1] ]) children(); } module skew_xz(a) { // Push X, parallel Z multmatrix(m = [ [1, tan(a), 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) children(); } module skew_zx(a) { // Push Z, parallel X multmatrix(m = [ [1, 0, 0, 0], [0, 1, 0, 0], [0, tan(a), 1, 0], [0, 0, 0, 1] ]) children(); } module skew_xy(a) { // Push X parallel Y multmatrix(m = [ [1, 0, tan(a), 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) children(); } // Push Y, parallel X module skew_yx(a) { multmatrix(m = [ [1, 0, 0, 0], [0, 1, tan(a), 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) children(); } //////////////////////////////////////////////////////////////////////////// ////////////////////////////// SOLIDS ////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /* Torus, specified by major radius and thickness */ module torus(r, t) rotate_extrude(convexity=4) translate([r,0,0]) circle(t); /* Torus specified with an o-ring size, i.e. inner and outer diameters */ module oring(ir, or, s=0) torus((ir+or)/4, ((or-ir)/4) + s); /** * A six-sided shape of d diameter across the flats, * i.e. hex(6) will fit a 6mm hex key */ module hex(d,l=1) { r=d/2; rotate_extrude($fn=6) polygon([ [0,0], [0,l], [r/cos(30),l], [r/cos(30),0] ]); } // A ring with a square cross-section, like a washer, etc module ring(r1, r2, h, center=false) { if(center) translate([0,0,-(h/2)]) rotate_extrude() polygon(points=[ [r1, 0], [r1, h], [r2, h], [r2, 0] ]); else rotate_extrude() polygon(points=[ [r1, 0], [r1, h], [r2, h], [r2, 0] ], center=center); } /** * Works just like cylinder() except it takes a 'bevel' option which cuts * 45-degree bevels on the top and bottom faces, like * /------\ * | | * | | * \______/ * The bigger the number, the bigger the bevel. */ module bcylinder(r=10, h=10, bevel=0, center=false) { if(bevel == 0) cylinder(r=r, h=h, center=center); else translate([0,0,center?0:h/2]) rotate_extrude() assign(a=r, b=r-bevel, t=h/2, y=(h/2)-bevel, u=-(h/2)+bevel, i=-(h/2)) polygon([ [a,y], [a,u], [b,i], [0,i], [0,t], [b,t]]); } /* What it sounds like. The angle is perfect, the border is crude. 2D object. */ module pie(r, a1=0, a2=90, msteps=100) { function a(n)=90-(a1+((a2-a1)*(n/msteps))); polygon(concat([[0,0]], [ for(n=[0:msteps]) r*[sin(a(n)),cos(a(n))] ])); } // A cube with rounded edges. CPU-intensive. module roundcube(v2=[1,1,1], r=0.1) { v=[v2[0]-(2*r), v2[1]-(2*r), v2[2]-(2*r)]; translate([r,r,r]) union() { minkowski() { cube([v[0],v[1],v[2]]); cylinder(r=r, h=s); } minkowski() { cube([v[0],v[1],v[2]]); rotate([90, 0,0]) cylinder(r=r, h=s); } minkowski() { cube([v[0],v[1],v[2]]); rotate([0,90,0]) cylinder(r=r, h=s); } for(q = [ [0,0,0], [0,0,1], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,0], [1,1,1] ]) translate([v[0]*q[0],v[1]*q[1],v[2]*q[2]]) sphere(r=r); } } /** * Lens in the geometry sense -- the intersection of two circles. * r is the radius of the circles, d is the amount of overlap * from 0=none to 1=total. * * Can also do intersections of spheres via 'sphere=true'. */ module lens(r, d, sphere=false) { if(sphere == true) mirrorintersect([1,0,0]) translate(r*[1-d,0,0]) sphere(r=r); else mirrorintersect([1,0,0]) translate(r*[1-d,0,0]) circle(r=r); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////DUPLICATION/////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Try radial(8, [2,0,0]) cube([1,1,1]); to see what this does. module radial(n=8, o=[0,0,0], a=360, ao=0) for(x=[0:n-1]) rotate([0,0,ao+(a*(x/n))]) translate(o) children(); // Try array(10, 2, [2,0,0], [3,0,0]) cube([1,1,1]); to see what this does. module array(n=10, m=1, on=[1,0,0], om=[0,1,0]) { for(y=[0:m-1]) for(x=[0:n-1]) translate((on*x)+(om*y)) children(); } // Like mirror(), except both the original and the mirrored are created. // 'off' lets you move the plane of the mirror. module mirrordup(plane, off=[0,0,0]) { children(); translate(off) mirror(plane) children(); } // Like mirrordup() but hulls the space between module hulldup(plane, off=[0,0,0]) hull() { translate(-off/2) children(); translate(off/2) mirror(plane) children(); } // An extruded trapezoid for dovetail shapes module dovetail(w1, w2, h, l) { linear_extrude(l) polygon([ [w1/2,0], [w2/2,h], [-w2/2, h], [-w1/2,0] ]); } // like dovetail, but rounded module flange(r1, r2, h1, h2, l) { hull() { cylinder(r=r1, h=h1); translate([l-(r1+r2),0,0]) cylinder(r=r2, h=h2); } } // Translate an object along a radius and angle without rotating // the object itself module traj(a=90, r=1) translate([sin(a)*r, cos(a)*r, 0]) children(); // Mirrors objects then takes their intersection. // Try mirrorintersect([1,0,0]) translate([5,0,0]) cylinder(r=10); module mirrorintersect(plane, off=[0,0,0]) intersection() { children(); translate(off) mirror(plane) children(); } //////////////////////////////////////////////////////////////////////////// ///////////////////////////////VECTOR OPS/////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /** * Integrate an array so that [ [0,0], [5,2], [-3,-1] ] becomes [ [0,0], [5,2], [2,1] ] * You can alter what values are kept and which are accumulated via the * ADD and KEEP matrices. * * This is useful for polygon() arrays, as it lets you specify points as offsets * instead of absolutes. */ function integ(A, ADD=[ [1,0], [0,1] ], KEEP=[ [0,0], [0,0] ])=[ for(N=[0:len(A)-1]) integ2(A, N, ADD, KEEP) ]; /* A polygon that takes delta-values instead of absolute values. */ module dpolygon(A, add=[ [1,0], [0,1]], keep=[[0,0],[0,0]]) polygon(integ(A, add, keep)); /** * Flattens / reduces / unwraps one level of array elements, i.e. * [ [ [1,2], [3,4] ], [ [5,6], [7,8] ] ] into [ [1,2],[3,4],[5,6],[7,8] ] * This lets you cram more than one element into a for() and get a legit array out. */ function flat(A,P=0)=((P+1)