/* * 3darc produce an incomplete hollow cylinder * * ray: ray of the cylinder * thick: Thickness of the outside * start_angle: Start of the pie to remove * end_angle: End of the pie to remove */ module 3darc_sub(ray,len,angle){ if (angle > 90){ cube([ray,ray,len]); rotate([0,0,90]) 3darc_sub(ray,len,angle-90); }else{ intersection(){ cube([ray,ray,len]); rotate([0,0,angle-90]) cube([ray,ray,len]); } } } module 3darc(ray,thick,len,start_angle,end_angle,precision){ rotate([0,0,end_angle]){ difference(){ cylinder(r=ray,h=len,$fn=precision); union(){ if (thick0) rotate([-90,0,0]) translate([0,0,0]) cylinder(r=thickr,h=width); } } } // Use a 2D path made of line and arc and extrude it along the Z axis // path=[[x1,y1,r1],[x2,y2,r2],... // width is the length along the Z axis // thick is the thickness. The extrusion will be centered around the path // offy is normally 0. It is applied to offset from the center of the path // for example, if offy=-thick, then the extrusion will be inside the path //cylinder(r=r1,h=width); // thickr is the ray of the small cylinder used to connect the rectangle joining // the points along the path module profile_arc(path,width,thick,offy,thickr,precision){ end=len(path)-2; for (i=[0:end]){ x1=path[i][0]; y1=path[i][1]; r1=path[i][2]; x2=path[i+1][0]; y2=path[i+1][1]; diffx = x2-x1; diffy = y2-y1; angle = atan2(diffy,diffx); len = sqrt(diffx*diffx+diffy*diffy); translate([x1,0,y1]) rotate([0,-angle,0]){ if (r1==0){ translate([0,0,offy-thick/2]) cube([len,width,thick]); }else{ // We find the half of the angle between the arc center and the two points // (The half angle is the angle of a triangle rectangle going between the // first point, the arc center and the middle between the two points. sina=(len/2)/r1; angle2=asin(sina); len2=cos(angle2)*r1; translate([len/2,0,0]){ //sphere(r=1); rotate([0,90,0]) translate([len2,0,0]){ //sphere(r=1); rotate([-90,0,0]) 3darc(r1+thick/2+offy,thick,width,-angle2+180,angle2+180,precision); } } } if (i>0) rotate([-90,0,0]) translate([0,0,0]) cylinder(r=thickr,h=width); } } } // Create a rectangle using 3 points module profile2_plate(x1_1,y1_1,x1_2,y1_2,x2_1,y2_1,width,thick){ diffx1 = x1_2-x1_1; diffy1 = y1_2-y1_1; angle1 = atan2(diffy1,diffx1); len1 = sqrt(diffx1*diffx1+diffy1*diffy1); diffx2 = x2_1-x1_1; angle2 = atan2(width,diffx2); len2 = sqrt(diffx2*diffx2+width*width); diffy3 = y2_1-y1_1; angle3 = atan2(diffy3,width); translate([0,0,len1/2]) rotate([0,-angle1,0]) triangle(len1,len2,thick); } // Normal vector module normal(p1,p2,p3){ diff1_x = p2[0] - p1[0]; diff1_y = p2[1] - p1[1]; diff1_z = p2[2] - p1[2]; diff2_x = p3[0] - p1[0]; diff2_y = p3[1] - p1[1]; diff2_z = p3[2] - p1[2]; a = diff1_y*diff2_z - diff1_z*diff2_y; b = diff1_z*diff2_x - diff1_x*diff2_z; c = diff1_x*diff2_y - diff1_y*diff2_x; echo ("a=",a,"b=",b,"c=",c); } // Create a triangle using 3 3d points and a thickness module profile2_triangle(p1,p2,p3,thick,corra,corrb){ // Compute the length and angle between p2 and p1 diff1_x = p2[0] - p1[0]; diff1_y = p2[1] - p1[1]; diff1_z = p2[2] - p1[2]; angle1_y = atan2(diff1_z,diff1_y); len1 = sqrt(diff1_x*diff1_x+diff1_y*diff1_y+diff1_z*diff1_z); angle1_z = atan2(diff1_x,diff1_y); echo ("p2-p1: diff1_x",diff1_x,"diff1_y",diff1_y,"diff1_z",diff1_z,"angle1_y=",angle1_y," angle1_z=",angle1_z); // Now do the same between p3 and p1 diff2_x = p3[0] - p1[0]; diff2_y = p3[1] - p1[1]; diff2_z = p3[2] - p1[2]; angle2_y = atan2(diff2_x,diff2_z); len2 = sqrt(diff2_x*diff2_x+diff2_y*diff2_y+diff2_z*diff2_z); angle2_z = atan2(diff2_y,diff2_z); // Then p3 and p2 diff3_x = p3[0] - p2[0]; diff3_y = p3[1] - p2[1]; diff3_z = p3[2] - p2[2]; len3 = sqrt(diff3_x*diff3_x+diff3_y*diff3_y+diff3_z*diff3_z); cosa = (len3*len3-len1*len1-len2*len2)/(-2*len1*len2); angle = acos(cosa); offx = cosa*len2; offy = sin(angle)*len2; echo ("len1=",len1,"len2=",len2,"len3=",len3,"offx=",offx,"offy=",offy); echo ("p3-p1: diff2_x",diff2_x,"diff2_y",diff2_y,"diff2_z",diff2_z,"angle2_y=",angle2_y," angle2_z=",angle2_z); translate([p1[0],p1[1],p1[2]]){ rotate([-90+angle1_y,0,corrb-angle1_z]){ cylinder(r=1,h=len1); } rotate([90+corra,-angle1_y,90+corrb-angle1_z]){ rotate([angle2_y,0,0]){ *rotate([-90,0,0]) cylinder(r=1,h=offy); translate([0,0,-0.5]) linear_extrude(1){ polygon([[0,0],[len1,0],[offx,offy],[0,0]]); } } } } } module profile2_sphere(p){ translate([p[0],p[1],p[2]]) sphere (r=1); } // Use 2 2D path and extrude from one to the other module profile2(path1,path2,width,thick,offy,thickr){ normal ([1,2,3],[4,6,9],[12,11,9]); end=len(path1)-2; pt=1; for (i=[0:end]){ //for (i=[0:end]){ p1=[path1[i][0],0,path1[i][1]]; p2=[path2[i][0],width,path2[i][1]]; p3=[path2[i+1][0],width,path2[i+1][1]]; p4=[path1[i+1][0],0,path1[i+1][1]]; profile2_triangle (p1,p2,p4,thick,0,0); //profile2_triangle (p2,p4,p3,thick,90,180); profile2_sphere (p1); profile2_sphere (p2); profile2_sphere (p3); profile2_sphere (p4); } } // Draw an hexagonal screw nut // The size is the distance between two opposite parallel side // The depth is the thickness of the nut // flat is a boolean. The nut is drawn either with a peak at the top of flat line module nut(size,depth,flat){ rotate([0,0,flat ? 30 : 0]){ linear_extrude(depth){ basex=size/2; s2=basex/cos(30); x=sin(30)*s2; polygon([[-basex,0],[-basex,-x],[0,-s2],[basex,-x], [basex,x],[0,s2],[-basex,x],[-basex,0]]); } } } module donut(ray,thick,precision){ rotate_extrude($fn=precision){ translate([ray,0,0]) circle(r=thick/2); } }