//--------------------------------------------------------------- //-- Openscad Bevel library //-- Bevel the edges or add buttress to your parts! //--------------------------------------------------------------- //-- This is a component of the obiscad opescad tools by Obijuan //-- (C) Juan Gonzalez-Gomez (Obijuan) //-- Sep-2012 //--------------------------------------------------------------- //-- Released under the GPL license //--------------------------------------------------------------- use use //----------------------------------------------------------------- //- Rotate a vector an angle teta around the axis given by the //-- unit vector k //----------------------------------------------------------------- function Rot_axis_ang(p,k,teta) = p*cos(teta) + cross(k,p*sin(teta)) + k*dot(k,p)*(1-cos(teta)); //-- Transformation defined by rotating vfrom vector to vto //-- It is applied to vector v //-- It returns the transformed vector function Tovector(vfrom, vto, v) = Rot_axis_ang(v, unitv(cross(vfrom,vto)), anglev(vfrom,vto)); //-- Auxiliary function for extending a vector of 3 components to 4 function ev(v,c=0) = [v[0], v[1], v[2], c]; //-- Calculate the determinant of a matrix given by 3 row vectors function det(a,b,c) = a[0]*(b[1]*c[2]-b[2]*c[1]) - a[1]*(b[0]*c[2]-b[2]*c[0]) + a[2]*(b[0]*c[1]-b[1]*c[0]); //-- Sign function. It only returns 2 values: -1 when x is negative, //-- or 1 when x=0 or x>0 function sign2(x) = sign(x)+1 - abs(sign(x)); //-------------------------------------------------------------------- //-- Beveled concave corner //-- NOT AN INTERFACE MODULE (The user should call bconcave_corner instead) //-- //-- Parameters: //-- * cr: Corner radius //-- * cres: Corner resolution //-- * l: Length //- * th: Thickness //-------------------------------------------------------------------- module bconcave_corner_aux(cr,cres,l,th) { //-- vector for translating the main cube //-- so that the top rigth corner is on the origin v1 = -[(cr+th)/2, (cr+th)/2, 0]; //-- The part frame of reference is on the //-- internal corner v2 = [cr,cr,0]; //-- Locate the frame of ref. in the internal //-- corner translate(v2) difference() { //-- Main cube for doing the corner translate(v1) //color("yellow",0.5) cube([cr+th, cr+th, l],center=true); //-- Cylinder used for beveling... cylinder(r=cr, h=l+1, center=true, $fn=4*(cres+1)); } } //----------------------------------------------------------------------------- //-- API MODULE //-- //-- Beveled concave corner //-- //-- Parameters: //-- * cr: Corner radius //-- * cres: Corner resolution //-- * l: Length //- * th: Thickness //-- * ext_corner: Where the origin is locate. By default it is located //-- in the internal corner (concave zone). If true, //-- it will be in the external corner (convex zone) //---------------------------------------------------------------------------- module bconcave_corner(cr=1,cres=4,th=1,l=10,ext_corner=false) { //-- Locate the origin in the exterior edge if (ext_corner==true) translate([th,th,0]) bconcave_corner_aux(cr,cres,l,th); else //-- Locate the origin in the interior edge translate([0.01, 0.01,0]) bconcave_corner_aux(cr,cres,l,th); } //---------------------------------------------------------------------- //-- Auxiliary module (NOT FOR THE USER!) //-- It is and standar "attach", particularized for placing concave //-- corners //---------------------------------------------------------------------- module bconcave_corner_attach_final( cfrom, //-- Origin connector cto, //-- Target connector cr, cres, l, th, ext_corner) { //-- This block represent an attach operation //-- It is equivalent to: attach(cto,cfrom) translate(cto[0]) rotate(a=cto[2], v=cto[1]) rotate(a=anglev(cfrom[1],cto[1]), v=cross(cfrom[1],cto[1]) ) translate(-cfrom[0]) //-- Place the concave corner (along with some debug information) union() { //color("Blue") //connector(cfrom); //connector([cfrom[0],cnormal_v,0]); bconcave_corner(cr=cr, cres=cres, l=l, th=th, ext_corner=ext_corner); } } //------------------------------------------------------------------------- //-- Auxiliary module (NOT FOR THE USER!) //-- It is the general module for performing the bconcave corner attach //-- All the parameters should be passed to it //-- //-- External connectors are where de concave corner will be placed. They //-- are provided by the user //-- //-- Internal connectors refers to the connectors of the concave corner //-- //-- Then an attach between the internal and external connectors is done //------------------------------------------------------------------------- module bconcave_corner_attach_aux( //-- External connectors edge_c, normal_c, //-- Internal connectors iedge_c, inormal_c, //-- Other params cr, cres, th, l, ext_corner) { //-- Get the Corner vectors from the internal connectors cedge_v = iedge_c[1]; //-- Corner edge vector cnormal_v = inormal_c[1]; //-- Corner normal vector //-- Get the vector paralell and normal to the edge //-- From the external connectors edge_v = edge_c[1]; //-- Edge verctor enormal_v = normal_c[1]; //-- Edge normal vector //--------------------------------------------------------------- //-- For doing a correct attach, first the roll angle for the //-- external connector should be calculated. It determines the //-- orientation of the concave corner around the edge vector //-- //-- This orientation is calculated using the edge normal vectors //-- that bisec the corner //-- //-- There are 2 different cases: depending on the relative angle //-- between the internal and external edges. They can be parallel //-- or not //----------------------------------------------------------------- //-- The roll angle has two components: the value and the sign //-- Calculate the sign of the rotation (the sign of roll) s=sign2(det(cnormal_v,enormal_v,edge_v)); //-- Calculate the roll when the edges are paralell rollp = s*anglev(cnormal_v, enormal_v); //-- Calculate the roll in the general case Tcnormal_v = Tovector(cedge_v, edge_v, cnormal_v); rollg=s*anglev(Tcnormal_v, enormal_v); //-- For the paralell case... use rollp if (mod(cross(cedge_v,edge_v))==0) { //echo("Paralell"); //-- Place the concave bevel corner! bconcave_corner_attach_final( cfrom = [[0,0,0], cedge_v, 0], cto = [edge_c[0], edge_c[1], rollp], cr = cr, cres = cres, l = l, th = th, ext_corner = ext_corner); } //-- For the general case, use rollg else { //echo("not paralell"); //-- Place the concave bevel corner! bconcave_corner_attach_final( cfrom = [[0,0,0], cedge_v, 0], cto = [edge_c[0], edge_c[1], rollg], cr = cr, cres = cres, l = l, th = th, ext_corner = ext_corner); } } //--------------------------------------------------------------------------- //-- API MODULE //-- //-- Bevel an edge. A concave corner is located so that the calling //-- module can easily perform a difference() operation //-- //-- Two connectors are needed: //-- * edge_c : Connector located on the edge, paralell to the edge //-- * normal_c : Connector located on the same point than edge_c //-- pointing to the internal corner part, in the direction //-- of the corner bisector //-- * cr : Corner radius //-- * cres : Corner resolution //-- * l : Corner length //-------------------------------------------------------------------------- module bevel( edge_c, normal_c, cr=3, cres=3, l=5) { //-- Call the general module with the correct internal connectors bconcave_corner_attach_aux( //-- External connectors edge_c = edge_c, normal_c = normal_c, //-- Internal connectors iedge_c = [[0,0,0], unitv([0,0,1]), 0], inormal_c = [[0,0,0], [-1,-1,0] , 0], //-- The other params cr=cr, cres=cres, l=l, th=1, ext_corner=false); } //--------------------------------------------------------------------------- //-- API MODULE //-- //-- Attach a Beveled concave corner //-- Two connectors are needed: //-- * edge_c : Connector located on the edge, paralell to the edge //-- * normal_c : Connector located on the same point than edge_c //-- pointing to the internal corner part, in the direction //-- of the corner bisector //-- * cr : Corner radius //-- * cres : Corner resolution //-- * l : Corner length //-- * th : Corner thickness (not visible when ext_corner=false) //-- * ext_corner: If the exterior corner is used as a reference //-------------------------------------------------------------------------- module bconcave_corner_attach( edge_c, normal_c, cr=3, cres=3, l=5, th=1, ext_corner=false) { //-- Call the general module with the correct internal connectors bconcave_corner_attach_aux( //-- External connectors edge_c = edge_c, normal_c = normal_c, //-- Internal connectors iedge_c = [[0,0,0], unitv([0,0,1]), 0], inormal_c = [[0,0,0], [1,1,0] , 0], //-- The other params cr=cr, cres=cres, l=l, th=th, ext_corner=ext_corner); } //----------------------------------------------------------- //--- TEST MODULES //----------------------------------------------------------- //----------------------------------------------------------------- //-- Testing the Bevel operator... All the 12 edges of a cube //-- are beveled. All the cases are covered, so it is a good //-- test for finding bugs! //---------------------------------------------------------------- module Test1_beveled_cube() { //-------- Main object size=[30,30,30]; //-- Define all the edges connectors ec1 = [[size[0]/2, 0,size[2]/2], [0,1,0], 0]; en1 = [ec1[0], [1,0,1], 0]; ec2 = [[-size[0]/2, 0,size[2]/2], [0,1,0], 0]; en2 = [ec2[0], [-1,0,1], 0]; ec3 = [[-size[0]/2, 0,-size[2]/2], [0,1,0], 0]; en3 = [ec3[0], [-1,0,-1], 0]; ec4 = [[size[0]/2, 0,-size[2]/2], [0,1,0], 0]; en4 = [ec4[0], [1,0,-1], 0]; ec5 = [[0, size[0]/2,size[2]/2], [1,0,0], 0]; en5 = [ec5[0], [0,1,1], 0]; ec6 = [[0, -size[0]/2,size[2]/2], [1,0,0], 0]; en6 = [ec6[0], [0,-1,1], 0]; ec7 = [[0, -size[0]/2,-size[2]/2], [1,0,0], 0]; en7 = [ec7[0], [0,-1,-1], 0]; ec8 = [[0, size[0]/2,-size[2]/2], [1,0,0], 0]; en8 = [ec8[0], [0,1,-1], 0]; ec9 = [[size[2]/2, size[0]/2,0 ], [0,0,1], 0]; en9 = [ec9[0], [1,1,0], 0]; ec10 = [[size[2]/2, -size[0]/2,0 ], [0,0,1], 0]; en10 = [ec10[0], [1,-1,0], 0]; ec11 = [[-size[2]/2, -size[0]/2,0 ], [0,0,1], 0]; en11 = [ec11[0], [-1,-1,0], 0]; ec12 = [[-size[2]/2, size[0]/2,0 ], [0,0,1], 0]; en12 = [ec12[0], [-1,1,0], 0]; //-- for Debuging... Show a specefic connector *connector(ec12); *connector(en12); //-- Parameters for all the beveled edges //-- It can be changed for testing cr=2; cres=0; //-- Remove from the main cube the concave corner parts difference() { //-- Draw the main cube cube(size,center=true); //-- Attach the concave corners for beveling! bevel(ec1,en1,cr=cr,cres=0, l=size[1]+2); bevel(ec2,en2,cr=cr,cres=0, l=size[1]+2); bevel(ec3,en3,cr=cr,cres=0, l=size[1]+2); bevel(ec4,en4,cr=cr,cres=0, l=size[1]+2); bevel(ec5,en5,cr=cr,cres=0, l=size[0]+2); bevel(ec6,en6,cr=cr,cres=0, l=size[0]+2); bevel(ec7,en7,cr=cr,cres=0, l=size[0]+2); bevel(ec8,en8,cr=cr,cres=0, l=size[0]+2); bevel(ec9,en9,cr=cr,cres=0, l=size[0]+2); bevel(ec10,en10,cr=cr,cres=0, l=size[0]+2); bevel(ec11,en11,cr=cr,cres=0, l=size[0]+2); bevel(ec12,en12,cr=cr,cres=0, l=size[0]+2); } } //---------------------------------------------------------------- //-- Testing the bconcave_corner_attach operator //-- It is used for adding buttress between two ortogonal parts //---------------------------------------------------------------- module Test2_buttress() { size=[30,30,30]; th=3; l=2; cr = 6; //-- A cross. It divides the space in 4 quadrants difference() { cube(size,center=true); translate([size[0]/4 + th/2, 0, size[0]/4 + th/2]) cube([size[0]/2, size[1]+2, size[2]/2],center=true); translate([-size[0]/4 - th/2, 0, size[0]/4 + th/2]) cube([size[0]/2, size[1]+2, size[2]/2],center=true); translate([-size[0]/4 - th/2, 0, -size[0]/4 - th/2]) cube([size[0]/2, size[1]+2, size[2]/2],center=true); translate([size[0]/4 + th/2, 0, -size[0]/4 - th/2]) cube([size[0]/2, size[1]+2, size[2]/2],center=true); } ec1 = [[th/2, size[1]/2-l/2, th/2], [0,1,0], 0]; en1 = [ec1[0],[1,0,1],0]; ec2 = [[th/2, -size[1]/2+l/2, th/2], [0,1,0], 0]; en2 = [ec2[0],[1,0,1],0]; ec3 = [[-th/2, 0, th/2], [0,1,0], 0]; en3 = [ec3[0],[-1,0,1],0]; ec4 = [[-th/2, 0, -th/2], [0,1,0], 0]; en4 = [ec4[0],[-1,0,-1],0]; ec5 = [[th/2, 0, -th/2], [0,1,0], 0]; en5 = [ec5[0],[1,0,-1],0]; *connector(ec5); *connector(en5); //-- quadrant 1: two buttress bconcave_corner_attach(ec1,en1,cr, l=l, cres=0); bconcave_corner_attach(ec2,en2,cr, l=l, cres=0); //-- quadrant 2: one bit buttress bconcave_corner_attach(ec3,en3,cr=3, l=size[1], cres=0); //-- quadrant 3: a Rounded buttress bconcave_corner_attach(ec4,en4,cr=8, l=size[1], cres=5); //-- Quadrant 4: A rounded buttress in the middle bconcave_corner_attach(ec5,en5,cr=8, l=size[1]/3, cres=5); } //------------------------------------------------------------------- //-- TESTS //------------------------------------------------------------------- //-- example 1: A beveled concave corner bconcave_corner(cr=15, cres=10, l=10, th=3, ext_corner=true); //-- Example 2: Testing the bevel() operator //Test1_beveled_cube(); //-- Example 3: Testing the bconcave_corner_attach() operator //Test2_buttress();