diff --git a/3d_triangle.scad b/3d_triangle.scad new file mode 100644 index 0000000..f313433 --- /dev/null +++ b/3d_triangle.scad @@ -0,0 +1,327 @@ +// Enhancement of OpenSCAD Primitives Solid with Trinagles +// Copyright (C) 2011 Rene BAUMANN, Switzerland +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; If not, see +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// ================================================================ +// +// File providing functions and modules to draw 3D - triangles +// created in the X-Y plane with hight h, using various triangle +// specification methods. +// Standard traingle geometrical definition is used. Vertices are named A,B,C, +// side a is opposite vertex A a.s.o. the angle at vertex A is named alpha, +// B(beta), C(gamma). +// +// This SW is a contribution to the Free Software Community doing a marvelous +// job of giving anyone access to knowledge and tools to educate himselfe. +// +// Author: Rene Baumann +// Date: 11.09.2011 +// Edition: 0.3 11.09.2011 For review by Marius +// Edition: 0.4 11.11.2011 Ref to GPL2.1 added +// +// -------------------------------------------------------------------------------------- +// +// =========================================== +// +// FUNCTION: 3dtri_sides2coord +// DESCRIPTION: +// Enter triangle sides a,b,c and to get the A,B,C - corner +// co-ordinates. The trinagle's c-side lies on the x-axis +// and A-corner in the co-ordinates center [0,0,0]. Geometry rules +// required that a + b is greater then c. The traingle's vertices are +// computed such that it is located in the X-Y plane, side c is on the +// positive x-axis. +// PARAMETER: +// a : real length of side a +// b : real length of side b +// c : real length of side c +// RETURNS: +// vertices : [Acord,Bcord,Ccord] Array of vertices coordinates +// +// COMMENT: +// vertices = 3dtri_sides2coord (3,4,5); +// vertices[0] : Acord vertex A cordinates the like [x,y,z] +// ------------------------------------------------------------------------------------- +// +function 3dtri_sides2coord (a,b,c) = [ + [0,0,0], + [c,0,0], + [(pow(c,2)+pow(a,2)-pow(b,2))/(2*c),sqrt ( pow(a,2) - + pow((pow(c,2)+pow(a,2)-pow(b,2))/(2*c),2)),0]]; +// +// +// =========================================== +// +// FUNCTION: 3dtri_centerOfGravityCoord +// DESCRIPTION: +// Enter triangle A,B,C - corner coordinates to get the +// triangles Center of Gravity coordinates. It is assumed +// the triangle is parallel to the X-Y plane. The function +// returns always zero for the z-coordinate +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// RETURNS: +// CG : [x,y,0] Center of gravity coordinate in X-Y-plane +// +// COMMENT: +// vertices = 3dtri_sides2coord (3,4,5); +// cg = 3dtri_centerOfGravityCoord(vertices[0],vertices[1],vertices[2]); +// ------------------------------------------------------------------------------------- +// +function 3dtri_centerOfGravityCoord (Acord,Bcord,Ccord) = [ + (Acord[0]+Bcord[0]+Ccord[0])/3,(Acord[1]+Bcord[1]+Ccord[1])/3,0]; +// +// +// =========================================== +// +// FUNCTION: 3dtri_centerOfcircumcircle +// DESCRIPTION: +// Enter triangle A,B,C - corner coordinates to get the +// circum circle coordinates. It is assumed +// the triangle is parallel to the X-Y plane. The function +// returns always zero for the z-coordinate +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// RETURNS: +// cc : [x,y,0] Circumcircle center +// +// COMMENT: +// vertices = 3dtri_sides2coord (3,4,5); +// cc = 3dtri_centerOfcircumcircle (vertices[0],vertices[1],vertices[2]); +// ------------------------------------------------------------------------------------- +// +function 3dtri_centerOfcircumcircle (Acord,Bcord,Ccord) = + [0.5*Bcord[0], + 0.5*((pow(Ccord[1],2)+pow(Ccord[0],2)-Bcord[0]*Ccord[0])/Ccord[1]), + 0]; +// +// +// +// =========================================== +// +// FUNCTION: 3dtri_radiusOfcircumcircle +// DESCRIPTION: +// Provides the triangle's radius from circumcircle to the vertices. +// It is assumed the triangle is parallel to the X-Y plane. The function +// returns always zero for the z-coordinate +// PARAMETER: +// Vcord : [x,y,z] Coordinates of a vertex A or B,C +// CCcord : [x,y,z] Coordinates of circumcircle +// r : Radius at vertices if round corner triangle used, +// else enter "0" +// RETURNS: +// cr : Circumcircle radius +// +// COMMENT: Calculate circumcircle radius of trinagle with round vertices having +// radius R = 2 +// vertices = 3dtri_sides2coord (3,4,5); +// cc = 3dtri_centerOfcircumcircle (vertices[0],vertices[1],vertices[2]); +// cr = 3dtri_radiusOfcircumcircle (vertices[0],cc,2); +// ------------------------------------------------------------------------------------- +// +function 3dtri_radiusOfcircumcircle (Vcord,CCcord,R) = + sqrt(pow(CCcord[0]-Vcord[0],2)+pow(CCcord[1]-Vcord[1],2))+ R; +// +// +// +// =========================================== +// +// FUNCTION: 3dtri_radiusOfIn_circle +// DESCRIPTION: +// Enter triangle A,B,C - corner coordinates to get the +// in-circle radius. It is assumed the triangle is parallel to the +// X-Y plane. The function always returns zero for the z-coordinate. +// Formula used for inner circle radius: r = 2A /(a+b+c) +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// +// RETURNS: +// ir : real radius of in-circle +// +// COMMENT: +// vertices = 3dtri_sides2coord (3,4,5); +// ir = 3dtri_radiusOfIn_circle (vertices[0],vertices[1],vertices[2]); +// ------------------------------------------------------------------------------------- +// +function 3dtri_radiusOfIn_circle (Acord,Bcord,Ccord) = + Bcord[0]*Ccord[1]/(Bcord[0]+sqrt(pow(Ccord[0]-Bcord[0],2)+pow(Ccord[1],2))+ + sqrt(pow(Ccord[0],2)+pow(Ccord[1],2))); +// +// +// +// =========================================== +// +// FUNCTION: 3dtri_centerOfIn_circle +// DESCRIPTION: +// Enter triangle A,B,C - corner coordinates to get the +// in-circle coordinates. It is assumed +// the triangle is parallel to the X-Y plane. The function +// returns always zero for the z-coordinate +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// r : real radius of in-circle +// RETURNS: +// ic : [x,y,0] In-circle center co-ordinates +// +// COMMENT: +// vertices = 3dtri_sides2coord (3,4,5); +// ir = 3dtri_radiusOfIn_circle (vertices[0],vertices[1],vertices[2]); +// ic = 3dtri_centerOfIn_circle (vertices[0],vertices[1],vertices[2],ir); +// ------------------------------------------------------------------------------------- +// +function 3dtri_centerOfIn_circle (Acord,Bcord,Ccord,r) = + [(Bcord[0]+sqrt(pow(Ccord[0]-Bcord[0],2)+pow(Ccord[1],2))+ + sqrt(pow(Ccord[0],2)+pow(Ccord[1],2)))/2-sqrt(pow(Ccord[0]-Bcord[0],2)+pow(Ccord[1],2)),r,0]; +// +// +// ============================================ +// +// MODULE: 3dtri_draw +// DESCRIPTION: +// Draw a standard solid triangle with A,B,C - vertices specified by its +// co-ordinates and height "h", as given by the input parameters. +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// h : real Hight of the triangle +// RETURNS: +// none +// +// COMMENT: +// You might use the result from function 3dtri_sides2coord +// to call module 3dtri_draw ( vertices[0],vertices[1],vertices[2], h) +// ------------------------------------------------------------------------------------- +// +module 3dtri_draw ( Acord, Bcord, Ccord, h) { +polyhedron (points=[Acord,Bcord,Ccord, + Acord+[0,0,h],Bcord+[0,0,h],Ccord+[0,0,h]], + triangles=[ [0,1,2],[0,2,3],[3,2,5], + [3,5,4],[1,5,2],[4,5,1], + [4,1,0],[0,3,4]]); + +}; +// +// +// ============================================== +// +// MODULE: 3dtri_rnd_draw +// DESCRIPTION: +// Draw a round corner triangle with A,B,C - vertices specified by its +// co-ordinates, height h and round vertices having radius "r". +// As specified by the input parameters. +// Please note, the tringles side lenght gets extended by "2 * r", +// and the vertices coordinates define the centers of the +// circles with radius "r". +// PARAMETER: +// Acord : [x,y,z] Coordinates of vertex A +// Bcord : [x,y,z] Coordinates of vertex B +// Ccord : [x,y,z] Coordinates of vertex C +// h : real Hight of the triangle +// r : real Radius from vertices coordinates +// RETURNS: +// none +// +// COMMENT: +// You might use the result from function 3dtri_sides2coord +// to call module 3dtri_rnd_draw ( vertices[0],vertices[1],vertices[2], h, r) +// ------------------------------------------------------------------------------------- +// +module 3dtri_rnd_draw ( Acord, Bcord, Ccord, h, r) { +Avect=Ccord-Bcord; // vector pointing from vertex B to vertex C +p0=Acord + [0,-r,0]; +p1=Bcord + [0,-r,0]; +p2=Bcord + [r*Avect[1]/sqrt(pow(Avect[0],2)+pow(Avect[1],2)), + -r*Avect[0]/sqrt(pow(Avect[0],2)+pow(Avect[1],2)) ,0]; +p3=Ccord + [r*Avect[1]/sqrt(pow(Avect[0],2)+pow(Avect[1],2)), + -r*Avect[0]/sqrt(pow(Avect[0],2)+pow(Avect[1],2)) ,0]; +p4=Ccord +[- r*Ccord[1]/sqrt(pow(Ccord[0],2)+pow(Ccord[1],2)), + r*Ccord[0]/sqrt(pow(Ccord[0],2)+pow(Ccord[1],2)) ,0]; +p5=Acord + [- r*Ccord[1]/sqrt(pow(Ccord[0],2)+pow(Ccord[1],2)), + r*Ccord[0]/sqrt(pow(Ccord[0],2)+pow(Ccord[1],2)) ,0]; +bottom_triangles = [[0,1,2],[0,2,3],[0,3,4],[0,4,5]]; +c_side_triangles = [[7,1,0],[0,6,7]]; +a_side_triangles = [[2,8,3],[8,9,3]]; +b_side_triangles = [[4,10,5],[10,11,5]]; +A_edge_triangles = [[0,5,11],[0,11,6]]; +B_edge_triangles = [[1,7,2],[2,7,8]]; +C_edge_triangles = [[3,9,4],[9,10,4]]; +top_triangles = [[11,7,6],[11,8,7],[11,10,8],[8,10,9]]; +union () { + polyhedron (points=[p0,p1,p2,p3,p4,p5, + p0+[0,0,h],p1+[0,0,h],p2+[0,0,h],p3+[0,0,h],p4+[0,0,h],p5+[0,0,h]], + triangles=[ bottom_triangles[0],bottom_triangles[1],bottom_triangles[2],bottom_triangles[3], + A_edge_triangles[0],A_edge_triangles[1], + c_side_triangles[0],c_side_triangles[1], + B_edge_triangles[0],B_edge_triangles[1], + a_side_triangles[0],a_side_triangles[1], + C_edge_triangles[0],C_edge_triangles[1], + b_side_triangles[0],b_side_triangles[1], + top_triangles[0],top_triangles[1],top_triangles[2],top_triangles[3]]); + translate(Acord) cylinder(r1=r,r2=r,h=h,center=false); + translate(Bcord) cylinder(r1=r,r2=r,h=h,center=false); + translate(Ccord) cylinder(r1=r,r2=r,h=h,center=false); +}; +} +// +// ============================================== +// +// Demo Application - copy into new file and uncomment or uncomment here but +// without uncommenting the use <...> statement, then press F6 - Key +// +// use ; +//$fn=50; +// h =4; +// r=2; +// echo ("Draws a right angle triangle with its circumcircle and in-circle"); +// echo ("The calculated co-ordinates and radius are show in this console window"); +// echo ("Geometry rules for a right angle triangle say, that the circumcircle is the"); +// echo ("Thales Circle which center must be in the middle of the triangle's c - side"); +// echo ("==========================================="); +// vertices = 3dtri_sides2coord (30,40,50); +// echo("A = ",vertices[0]," B = ",vertices[1]," C = ",vertices[2]); +// cg = 3dtri_centerOfGravityCoord (vertices[0],vertices[1],vertices[2]); +// echo (" Center of gravity = ",cg); +// cc = 3dtri_centerOfcircumcircle (vertices[0],vertices[1],vertices[2]); +// echo (" Center of circumcircle = ",cc); +// cr = 3dtri_radiusOfcircumcircle (vertices[0],cc,r); +// echo(" Radius of circumcircle ",cr); +// ir = 3dtri_radiusOfIn_circle (vertices[0],vertices[1],vertices[2]); +// echo (" Radius of in-circle = ",ir); +// ic = 3dtri_centerOfIn_circle (vertices[0],vertices[1],vertices[2],ir); +// echo (" Center of in-circle = ",ic); +// translate(cc+[0,0,5*h/2]) difference () { +// cylinder (h=5*h,r1=cr+4,r2=cr+4,center=true); +// cylinder (h=6*h,r1=cr,r2=cr,center=true);} +// difference () { +// union () { +// difference () { +// 3dtri_rnd_draw (vertices[0], vertices[1], vertices[2],5*h,r); +// scale([0.8,0.8,1]) translate([6,2,4*h]) 3dtri_rnd_draw (vertices[0], vertices[1], vertices[2],5*h,r); +// } +// translate (ic+[0,0,5*h]) cylinder(h=10*h,r1=ir+r,r2=ir+r,center=true); +// } +// translate (ic+[0,0,5*h]) cylinder(h=12*h,r1=0.5*ir,r2=0.5*ir,center=true); +// } + diff --git a/README.markdown b/README.markdown index f26c1f4..09aefb5 100644 --- a/README.markdown +++ b/README.markdown @@ -51,6 +51,7 @@ Other tools (alpha and beta quality): * servos.scad: servo outlines * boxes.scad: box with rounded corners * triangles.scad: simple triangles +* 3d_triangle.scad: more advanced triangles Very generally useful functions and constants: diff --git a/TODO b/TODO index 6940f3f..cc2b4f7 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,8 @@ Code that could be integrated: * http://www.thingiverse.com/thing:4656 * http://www.thingiverse.com/thing:4758 * http://www.thingiverse.com/thing:6021 +* Color library: http://www.thingiverse.com/thing:6717 +* http://www.thingiverse.com/thing:6465 Integrate these better: * bitmap diff --git a/fonts.scad b/fonts.scad new file mode 100644 index 0000000..0ce6a77 --- /dev/null +++ b/fonts.scad @@ -0,0 +1,516 @@ +// Font Functions +// Encoding from http://en.wikipedia.org/wiki/ASCII + +module outline_2d(outline,points,paths,width=0.1,resolution=8) { + if(outline && resolution > 4) { + for(j=[0:len(paths)-1]) union() { + for(i=[1:len(paths[j])-1]) hull() { + translate(points[paths[j][i-1]]) circle($fn=resolution,r=width/2); + translate(points[paths[j][i]]) circle($fn=resolution,r=width/2); + } + hull() { + translate(points[paths[j][len(paths[j])-1]]) circle($fn=resolution,r=width/2); + translate(points[paths[j][0]]) circle($fn=resolution,r=width/2); + } + } + } else { + polygon(points=points,paths=paths); + } +} + +module bold_2d(bold,width=0.2,resolution=8) { + for(j=[0:$children-1]) { + if(bold) { + union() { + child(j); + for(i=[0:resolution-1]) assign(dx=width*cos(360*i/resolution),dy=width*sin(360*i/resolution)) + translate([dx,dy]) child(j); + } + } else { + child(j); + } + } +} + +function 8bit_polyfont(dx=0.1,dy=0.1) = [ + [8,8,0,"fixed"],["Decimal Byte","Caret Notation","Character Escape Code","Abbreviation","Name","Bound Box","[points,paths]"] + ,[ + [ 0,"^@","\0","NUL","Null character",[[0,0],[8,8]],[]] + ,[ 1,"^A","", "SOH","Start of Header",[[0,0],[8,8]],[]] + ,[ 2,"^B","", "STX","Start of Text",[[0,0],[8,8]],[]] + ,[ 3,"^C","", "ETX","End of Text",[[0,0],[8,8]],[]] + ,[ 4,"^D","", "EOT","End of Transmission",[[0,0],[8,8]],[]] + ,[ 5,"^E","", "ENQ","Enquiry",[[0,0],[8,8]],[]] + ,[ 6,"^F","", "ACK","Acknowledgment",[[0,0],[8,8]],[]] + ,[ 7,"^G","\a","BEL","Bell",[[0,0],[8,8]],[]] + ,[ 8,"^H","\b","BS", "Backspace",[[0,0],[8,8]],[]] + ,[ 9,"^I","\t","HT", "Horizontal Tab",[[0,0],[8,8]],[]] + ,[ 10,"^J","\n","LF", "Line Feed",[[0,0],[8,8]],[]] + ,[ 11,"^K","\v","VT", "Vertical Tab",[[0,0],[8,8]],[]] + ,[ 12,"^L","\f","FF", "Form feed",[[0,0],[8,8]],[]] + ,[ 13,"^M","\r","CR", "Carriage return",[[0,0],[8,8]],[]] + ,[ 14,"^N","", "SO", "Shift Out",[[0,0],[8,8]],[]] + ,[ 15,"^O","", "SI", "Shift In",[[0,0],[8,8]],[]] + ,[ 16,"^P","", "DLE","Data Link Escape",[[0,0],[8,8]],[]] + ,[ 17,"^Q","", "DC1","Device Control 1",[[0,0],[8,8]],[]] + ,[ 18,"^R","", "DC2","Device Control 2",[[0,0],[8,8]],[]] + ,[ 19,"^S","", "DC3","Device Control 3",[[0,0],[8,8]],[]] + ,[ 20,"^T","", "DC4","Device Control 4",[[0,0],[8,8]],[]] + ,[ 21,"^U","", "NAK","Negative Acknowledgement",[[0,0],[8,8]],[]] + ,[ 22,"^V","", "SYN","Synchronous Idle",[[0,0],[8,8]],[]] + ,[ 23,"^W","", "ETB","End of Transmission Block",[[0,0],[8,8]],[]] + ,[ 24,"^X","", "CAN","Cancel",[[0,0],[8,8]],[]] + ,[ 25,"^Y","", "EM", "End of Medium",[[0,0],[8,8]],[]] + ,[ 26,"^Z","", "SUB","Substitute",[[0,0],[8,8]],[]] + ,[ 27,"^[","\e","ESC","Escape",[[0,0],[8,8]],[]] + ,[ 28,"^\\","", "FS", "File Separator",[[0,0],[8,8]],[]] + ,[ 29,"^]","", "GS", "Group Separator",[[0,0],[8,8]],[]] + ,[ 30,"^^","", "RS", "Record Separator",[[0,0],[8,8]],[]] + ,[ 31,"^_","", "US", "Unit Separator",[[0,0],[8,8]],[]] + ,[ 32," "," ", "", "Space",[[0,0],[2,8]],[]] + ,[ 33,"!","!", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[5,2],[5,1] + ,[3,3],[3,7],[5,7],[5,3]] + ,[[0,1,2,3],[4,5,6,7]] + ]] + ,[ 34,"\"","\"","", "",[[0,0],[8,8]],[ + [[1,4],[1,7],[3,7],[3,4] + ,[5,4],[5,7],[7,7],[7,4]] + ,[[0,1,2,3],[4,5,6,7]] + ]] + ,[ 35,"#","#", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[0,2],[0,3],[1,3],[1,5],[0,5],[0,6],[1,6],[1,7],[3,7],[3,6],[5,6],[5,7],[7,7] + ,[7,6],[8,6],[8,5],[7,5],[7,3],[8,3],[8,2],[7,2],[7,1],[5,1],[5,2],[3,2],[3,1] + ,[3,3],[3,5],[5,5],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],[28,29,30,31]] + ]] + ,[ 36,"$","$", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[1,2],[1,3],[5,3],[5,4],[2,4],[2,5],[1,5],[1,6],[2,6],[2,7],[3,7],[3,8],[5,8],[5,7],[7,7],[7,6] + ,[3,6],[3,5],[6,5],[6,4],[7,4],[7,3],[6,3],[6,2],[5,2],[5,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 37,"%","%", "", "",[[0,0],[8,8]],[ + [[1,1],[1,3],[2,3],[2,5],[1,5],[1,7],[3,7],[3,5],[4,5],[4,6],[5,6],[5,7],[7,7] + ,[7,6],[6,6],[6,5],[5,5],[5,4],[4,4],[4,3],[3,3],[3,2],[2,2],[2,1] + ,[5,1],[5,3],[7,3],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],[24,25,26,27]] + ]] + ,[ 38,"&","&", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,4],[2,4],[2,5],[3,5],[3,6],[2,6],[2,7],[3,7],[3,8],[6,8],[6,7],[7,7],[7,6],[6,6],[6,5],[5,5],[5,4] + ,[8,4],[8,3],[7,3],[7,2],[8,2],[8,1],[6,1],[6,2],[5,2],[5,1] + ,[3,2],[3,4],[4,4],[4,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29],[30,31,32,33]] + ]] + ,[ 39,"'","'", "", "",[[0,0],[8,8]],[ + [[3,4],[3,7],[5,7],[5,4]] + ,[[0,1,2,3]] + ]] + ,[ 40,"(","(", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[2,2],[2,6],[3,6],[3,7],[6,7],[6,6],[5,6],[5,5],[4,5],[4,3],[5,3],[5,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[ 41,")",")", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[3,2],[3,3],[4,3],[4,5],[3,5],[3,6],[2,6],[2,7],[5,7],[5,6],[6,6],[6,2],[5,2],[5,1],[4,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]] + ]] + ,[ 42,"*","*", "", "",[[0,0],[8,8]],[ + [[1,2],[1,3],[2,3],[2,4],[0,4],[0,5],[2,5],[2,6],[1,6],[1,7],[3,7],[3,6],[5,6],[5,7],[7,7],[7,6],[6,6] + ,[6,5],[8,5],[8,4],[6,4],[6,3],[7,3],[7,2],[5,2],[5,3],[3,3],[3,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 43,"+","+", "", "",[[0,0],[8,8]],[ + [[3,1],[3,3],[1,3],[1,5],[3,5],[3,7],[5,7],[5,5],[7,5],[7,3],[5,3],[5,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[ 44,",",",", "", "",[[0,0],[8,8]],[ + [[2,0],[2,1],[3,1],[3,3],[5,3],[5,1],[4,1],[4,0]] + ,[[0,1,2,3,4,5,6,7]] + ]] + ,[ 45,"-","-", "", "",[[0,0],[8,8]],[ + [[1,3],[1,5],[7,5],[7,3]] + ,[[0,1,2,3]] + ]] + ,[ 46,".",".", "", "",[[0,0],[8,8]],[ + [[3,1],[3,3],[5,3],[5,1]] + ,[[0,1,2,3]] + ]] + ,[ 47,"/","/", "", "",[[0,0],[8,8]],[ + [[1,1],[1,3],[2,3],[2,4],[3,4],[3,5],[4,5],[4,6],[5,6],[5,7],[7,7],[7,6],[6,6],[6,5],[5,5],[5,4],[4,4],[4,3],[3,3],[3,2],[2,2],[2,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]] + ]] + ,[ 48,"0","0", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,2],[6,2],[6,1] + ,[3,2],[3,3],[5,3],[5,2] + ,[3,4],[3,6],[5,6],[5,5],[4,5],[4,4]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11],[12,13,14,15],[16,17,18,19,20,21]] + ]] + ,[ 49,"1","1", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[3,2],[3,5],[2,5],[2,6],[3,6],[3,7],[5,7],[5,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[ 50,"2","2", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[2,2],[2,3],[3,3],[3,4],[4,4],[4,5],[5,5],[5,6],[3,6],[3,5],[1,5],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,5],[6,5],[6,4],[5,4],[5,3],[4,3],[4,2],[3,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28]] + ]] + ,[ 51,"3","3", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,3],[3,3],[3,2],[5,2],[5,3],[4,3],[4,4],[3,4],[3,5],[4,5],[4,6],[1,6],[1,7],[7,7],[7,6],[6,6],[6,5],[5,5],[5,4],[6,4],[6,3],[7,3],[7,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 52,"4","4", "", "",[[0,0],[8,8]],[ + [[4,1],[4,2],[1,2],[1,4],[2,4],[2,5],[3,5],[3,6],[4,6],[4,7],[6,7],[6,3],[7,3],[7,2],[6,2],[6,1] + ,[3,3],[3,4],[4,4],[4,3]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19]] + ]] + ,[ 53,"5","5", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,3],[3,3],[3,2],[5,2],[5,4],[1,4],[1,7],[7,7],[7,6],[3,6],[3,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 54,"6","6", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[3,6],[3,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1] + ,[3,2],[3,4],[5,4],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19]] + ]] + ,[ 55,"7","7", "", "",[[0,0],[8,8]],[ + [[2,1],[2,3],[3,3],[3,4],[4,4],[4,5],[5,5],[5,6],[1,6],[1,7],[7,7],[7,5],[6,5],[6,4],[5,4],[5,3],[4,3],[4,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]] + ]] + ,[ 56,"8","8", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,4],[2,4],[2,5],[1,5],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1] + ,[3,2],[3,4],[5,4],[5,2] + ,[3,5],[3,6],[5,6],[5,5]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],[20,21,22,23],[24,25,26,27]] + ]] + ,[ 57,"9","9", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[4,2],[4,3],[5,3],[5,4],[2,4],[2,5],[1,5],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,3],[6,3],[6,2],[5,2],[5,1] + ,[3,5],[3,6],[5,6],[5,5]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],[20,21,22,23]] + ]] + ,[ 58,":",":", "", "",[[0,0],[8,8]],[ + [[3,1],[3,3],[5,3],[5,1] + ,[3,4],[3,6],[5,6],[5,4]] + ,[[0,1,2,3],[4,5,6,7]] + ]] + ,[ 59,";",";", "", "",[[0,0],[8,8]],[ + [[2,0],[2,1],[3,1],[3,3],[5,3],[5,1],[4,1],[4,0] + ,[3,4],[3,6],[5,6],[5,4]] + ,[[0,1,2,3,4,5,6,7],[8,9,10,11]] + ]] + ,[ 60,"<","<", "", "",[[0,0],[8,8]],[ + [[5,1],[5,2],[4,2],[4,3],[3,3],[3,4],[2,4],[2,5],[3,5],[3,6],[4,6],[4,7],[5,7],[5,8],[7,8],[7,7],[6,7],[6,6],[5,6],[5,5],[4,5],[4,4],[5,4],[5,3],[6,3],[6,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 61,"=","=", "", "",[[0,0],[8,8]],[ + [[1,2],[1,3],[7,3],[7,2] + ,[1,5],[1,6],[7,6],[7,5]] + ,[[0,1,2,3],[4,5,6,7]] + ]] + ,[ 62,">",">", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[2,2],[2,3],[3,3],[3,4],[4,4],[4,5],[3,5],[3,6],[2,6],[2,7],[1,7],[1,8],[3,8],[3,7],[4,7],[4,6],[5,6],[5,5],[6,5],[6,4],[5,4],[5,3],[4,3],[4,2],[3,2],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 63,"?","?", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[5,2],[5,1] + ,[3,3],[3,4],[4,4],[4,5],[5,5],[5,6],[3,6],[3,5],[1,5],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,5],[6,5],[6,4],[5,4],[5,3]] + ,[[0,1,2,3],[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]] + ]] + ,[ 64,"@","@", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,3],[4,3],[4,5],[5,5],[5,6],[3,6],[3,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]] + ]] + ,[ 65,"A","A", "", "",[[0,0],[8,8]],[ + [[1,1],[1,5],[2,5],[2,6],[3,6],[3,7],[5,7],[5,6],[6,6],[6,5],[7,5],[7,1],[5,1],[5,2],[3,2],[3,1] + ,[3,3],[3,5],[5,5],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19]] + ]] + ,[ 66,"B","B", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[6,7],[6,6],[7,6],[7,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1] + ,[3,5],[3,6],[5,6],[5,5] + ,[3,2],[3,4],[5,4],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11],[12,13,14,15],[16,17,18,19]] + ]] + ,[ 67,"C","C", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,5],[5,5],[5,6],[3,6],[3,2],[5,2],[5,3],[7,3],[7,2],[6,2],[6,1]] ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 68,"D","D", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[5,7],[5,6],[6,6],[6,5],[7,5],[7,3],[6,3],[6,2],[5,2],[5,1] + ,[3,2],[3,6],[4,6],[4,5],[5,5],[5,3],[4,3],[4,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11],[12,13,14,15,16,17,18,19]] + ]] + ,[ 69,"E","E", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[7,7],[7,6],[3,6],[3,5],[6,5],[6,4],[3,4],[3,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[ 70,"F","F", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[7,7],[7,6],[3,6],[3,5],[6,5],[6,4],[3,4],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9]] + ]] + ,[ 71,"G","G", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[7,7],[7,6],[3,6],[3,2],[5,2],[5,3],[4,3],[4,4],[7,4],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[ 72,"H","H", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,5],[5,5],[5,7],[7,7],[7,1],[5,1],[5,4],[3,4],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[ 73,"I","I", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[3,2],[3,6],[1,6],[1,7],[7,7],[7,6],[5,6],[5,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[ 74,"J","J", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,3],[3,3],[3,2],[5,2],[5,6],[4,6],[4,7],[7,7],[7,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13]] + ]] + ,[ 75,"K","K", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,5],[4,5],[4,6],[5,6],[5,7],[7,7],[7,6],[6,6],[6,5],[5,5],[5,3],[6,3],[6,2],[7,2],[7,1],[5,1],[5,2],[4,2],[4,3],[3,3],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]] + ]] + ,[ 76,"L","L", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5]] + ]] + ,[ 77,"M","M", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,6],[4,6],[4,5],[5,5],[5,6],[6,6],[6,7],[8,7],[8,1],[6,1],[6,4],[5,4],[5,3],[4,3],[4,4],[3,4],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 78,"N","N", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,6],[4,6],[4,5],[5,5],[5,7],[7,7],[7,1],[5,1],[5,2],[4,2],[4,3],[3,3],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[ 79,"O","O", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,2],[6,2],[6,1] + ,[3,2],[3,6],[5,6],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11],[12,13,14,15]] + ]] + ,[ 80,"P","P", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[6,7],[6,6],[7,6],[7,4],[6,4],[6,3],[3,3],[3,1] + ,[3,4],[3,6],[5,6],[5,4]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[ 81,"Q","Q", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[2,6],[2,7],[6,7],[6,6],[7,6],[7,3],[6,3],[6,2],[7,2],[7,1],[5,1],[5,2],[4,2],[4,1] + ,[3,3],[3,6],[5,6],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],[18,19,20,21]] + ]] + ,[ 82,"R","R", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[6,7],[6,6],[7,6],[7,4],[6,4],[6,2],[7,2],[7,1],[5,1],[5,2],[4,2],[4,3],[3,3],[3,1] + ,[3,4],[3,6],[5,6],[5,4]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19]] + ]] + ,[ 83,"S","S", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[5,2],[5,4],[2,4],[2,5],[1,5],[1,6],[2,6],[2,7],[6,7],[6,6],[3,6],[3,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 84,"T","T", "", "",[[0,0],[8,8]],[ + [[3,1],[3,6],[1,6],[1,7],[7,7],[7,6],[5,6],[5,1]] + ,[[0,1,2,3,4,5,6,7]] + ]] + ,[ 85,"U","U", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,2],[5,2],[5,7],[7,7],[7,1]] + ,[[0,1,2,3,4,5,6,7]] + ]] + ,[ 86,"V","V", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[2,2],[2,3],[1,3],[1,7],[3,7],[3,3],[5,3],[5,7],[7,7],[7,3],[6,3],[6,2],[5,2],[5,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[ 87,"W","W", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,4],[4,4],[4,5],[5,5],[5,4],[6,4],[6,7],[8,7],[8,1],[6,1],[6,2],[5,2],[5,3],[4,3],[4,2],[3,2],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 88,"X","X", "", "",[[0,0],[8,8]],[ + [[1,1],[1,3],[2,3],[2,5],[1,5],[1,7],[3,7],[3,5],[5,5],[5,7],[7,7],[7,5],[6,5],[6,3],[7,3],[7,1],[5,1],[5,3],[3,3],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[ 89,"Y","Y", "", "",[[0,0],[8,8]],[ + [[3,1],[3,4],[2,4],[2,5],[1,5],[1,7],[3,7],[3,5],[5,5],[5,7],[7,7],[7,5],[6,5],[6,4],[5,4],[5,1],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]] + ]] + ,[ 90,"Z","Z", "", "",[[0,0],[8,8]],[ + [[1,1],[1,3],[2,3],[2,4],[3,4],[3,5],[4,5],[4,6],[1,6],[1,7],[7,7],[7,6],[6,6],[6,5],[5,5],[5,4],[4,4],[4,3],[3,3],[3,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]] + ]] + ,[ 91,"[","[", "", "",[[0,0],[8,8]],[ // ] ] + [[2,1],[2,7],[6,7],[6,6],[4,6],[4,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7]] + ]] + ,[ 92,"\\","\\","", "",[[0,0],[8,8]],[ + [[6,1],[6,2],[5,2],[5,3],[4,3],[4,4],[3,4],[3,5],[2,5],[2,6],[1,6],[1,7],[3,7],[3,6],[4,6],[4,5],[5,5],[5,4],[6,4],[6,3],[7,3],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]] + ]] + ,[ 93,"]","]", "", "",[[0,0],[8,8]],[ // [ [ + [[2,1],[2,2],[4,2],[4,6],[2,6],[2,7],[6,7],[6,1]] + ,[[0,1,2,3,4,5,6,7]] + ]] + ,[ 94,"^","^", "", "",[[0,0],[8,8]],[ + [[2,4],[2,5] + ,[3-dx,5],[3,5+dy] + ,[3,6] + ,[4-dx,6],[4,6+dy] + ,[4,7],[5,7] + ,[5,6+dy],[5+dx,6] + ,[6,6] + ,[6,5+dy],[6+dx,5] + ,[7,5],[7,4],[6,4] + ,[6,5-dy],[6-dx,5] + ,[5,5] + ,[5,6-dy],[5-dx,6],[4+dx,6],[4,6-dy] + ,[4,5] + ,[3+dx,5],[3,5-dy] + ,[3,4]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[ 95,"_","_", "", "",[[0,0],[8,8]],[ + [[0,0],[0,1],[8,1],[8,0]] + ,[[0,1,2,3]] + ]] + ,[ 96,"`","`", "", "",[[0,0],[8,8]],[ + [[2,6],[2,7],[3,7] + ,[3,6+dy],[3+dx,6] + ,[4,6] + ,[4,5+dy],[4+dx,5] + ,[5,5],[5,4],[4,4] + ,[4,5-dy],[4-dx,5] + ,[3,5] + ,[3,6-dy],[3-dx,6]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[ 97,"a","a", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,3],[2,3],[2,4],[5,4],[5,5],[2,5],[2,6],[6,6],[6,5],[7,5],[7,1] + ,[3,2],[3,3],[5,3],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13],[14,15,16,17]] + ]] + ,[ 98,"b","b", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,5],[6,5],[6,4],[7,4],[7,2],[6,2],[6,1] + ,[3,2],[3,4],[5,4],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[ 99,"c","c", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,5],[2,5],[2,6],[6,6],[6,5],[3,5],[3,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[100,"d","d", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,4],[2,4],[2,5],[5,5],[5,7],[7,7],[7,1] + ,[3,2],[3,4],[5,4],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[101,"e","e", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,5],[2,5],[2,6],[6,6],[6,5],[7,5],[7,3],[3,3],[3,2],[6,2],[6,1] + ,[3,4],[3,5],[5,5],[5,4]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13],[14,15,16,17]] + ]] + ,[102,"f","f", "", "",[[0,0],[8,8]],[ + [[3,1],[3,4],[2,4],[2,5],[3,5],[3,6],[4,6],[4,7],[7,7],[7,6],[5,6],[5,5],[7,5],[7,4],[5,4],[5,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[103,"g","g", "", "",[[0,0],[8,8]],[ + [[1,0],[1,1],[5,1],[5,2],[2,2],[2,3],[1,3],[1,5],[2,5],[2,6],[6,6],[6,5],[7,5],[7,1],[6,1],[6,0] + ,[3,3],[3,5],[5,5],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[16,17,18,19]] + ]] + ,[104,"h","h", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,5],[6,5],[6,4],[7,4],[7,1],[5,1],[5,4],[3,4],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11]] + ]] + ,[105,"i","i", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[3,2],[3,4],[2,4],[2,5],[5,5],[5,2],[6,2],[6,1] + ,[3,6],[3,7],[5,7],[5,6]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[106,"j","j", "", "",[[0,0],[8,8]],[ + [[2,0],[2,1],[5,1],[5,5],[7,5],[7,1],[6,1],[6,0] + ,[5,6],[5,7],[7,7],[7,6]] + ,[[0,1,2,3,4,5,6,7],[8,9,10,11]] + ]] + ,[107,"k","k", "", "",[[0,0],[8,8]],[ + [[1,1],[1,7],[3,7],[3,4],[4,4],[4,5],[6,5],[6,4],[5,4],[5,3],[6,3],[6,2],[7,2],[7,1],[5,1],[5,2],[4,2],[4,3],[3,3],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[108,"l","l", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[3,2],[3,6],[2,6],[2,7],[5,7],[5,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9]] + ]] + ,[109,"m","m", "", "",[[0,0],[8,8]],[ + [[1,1],[1,6],[3,6],[3,5],[5,5],[5,6],[7,6],[7,5],[8,5],[8,1],[6,1],[6,3],[5,3],[5,2],[4,2],[4,3],[3,3],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]] + ]] + ,[110,"n","n", "", "",[[0,0],[8,8]],[ + [[1,1],[1,6],[6,6],[6,5],[7,5],[7,1],[5,1],[5,5],[3,5],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9]] + ]] + ,[111,"o","o", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,5],[2,5],[2,6],[6,6],[6,5],[7,5],[7,2],[6,2],[6,1] + ,[3,2],[3,5],[5,5],[5,2]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11],[12,13,14,15]] + ]] + ,[112,"p","p", "", "",[[0,0],[8,8]],[ + [[1,0],[1,6],[6,6],[6,5],[7,5],[7,3],[6,3],[6,2],[3,2],[3,0] + ,[3,3],[3,5],[5,5],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[113,"q","q", "", "",[[0,0],[8,8]],[ + [[5,0],[5,2],[2,2],[2,3],[1,3],[1,5],[2,5],[2,6],[7,6],[7,0] + ,[3,3],[3,5],[5,5],[5,3]] + ,[[0,1,2,3,4,5,6,7,8,9],[10,11,12,13]] + ]] + ,[114,"r","r", "", "",[[0,0],[8,8]],[ + [[1,1],[1,6],[6,6],[6,5],[7,5],[7,4],[5,4],[5,5],[3,5],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9]] + ]] + ,[115,"s","s", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[5,2],[5,3],[2,3],[2,4],[1,4],[1,5],[2,5],[2,6],[7,6],[7,5],[3,5],[3,4],[6,4],[6,3],[7,3],[7,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[116,"t","t", "", "",[[0,0],[8,8]],[ + [[4,1],[4,2],[3,2],[3,5],[1,5],[1,6],[3,6],[3,7],[5,7],[5,6],[7,6],[7,5],[5,5],[5,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[117,"u","u", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[1,2],[1,6],[3,6],[3,2],[5,2],[5,6],[7,6],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9]] + ]] + ,[118,"v","v", "", "",[[0,0],[8,8]],[ + [[3,1],[3,2],[2,2],[2,3],[1,3],[1,6],[3,6],[3,3],[5,3],[5,6],[7,6],[7,3],[6,3],[6,2],[5,2],[5,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]] + ]] + ,[119,"w","w", "", "",[[0,0],[8,8]],[ + [[2,1],[2,3],[1,3],[1,6],[3,6],[3,4],[4,4],[4,5],[5,5],[5,4],[6,4],[6,6],[8,6],[8,3],[7,3],[7,1],[5,1],[5,2],[4,2],[4,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[120,"x","x", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[2,2],[2,3],[3,3],[3,4],[2,4],[2,5],[1,5],[1,6],[3,6],[3,5],[5,5],[5,6],[7,6],[7,5],[6,5],[6,4],[5,4],[5,3],[6,3],[6,2],[7,2],[7,1],[5,1],[5,2],[3,2],[3,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]] + ]] + ,[121,"y","y", "", "",[[0,0],[8,8]],[ + [[1,0],[1,1],[4,1],[4,2],[2,2],[2,3],[1,3],[1,6],[3,6],[3,3],[5,3],[5,6],[7,6],[7,2],[6,2],[6,1],[5,1],[5,0]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]] + ]] + ,[122,"z","z", "", "",[[0,0],[8,8]],[ + [[1,1],[1,2],[2,2],[2,3],[3,3],[3,4],[4,4],[4,5],[1,5],[1,6],[7,6],[7,5],[6,5],[6,4],[5,4],[5,3],[4,3],[4,2],[7,2],[7,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[123,"{","{", "", "",[[0,0],[8,8]],[ + [[4,1],[4,2],[3,2],[3,4],[2,4],[2,5],[3,5],[3,7],[4,7],[4,8],[6,8],[6,7],[5,7],[5,5],[4,5],[4,4],[5,4],[5,2],[6,2],[6,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[124,"|","|", "", "",[[0,0],[8,8]],[ + [[3,0],[3,8],[5,8],[5,0]] + ,[[0,1,2,3]] + ]] + ,[125,"}","}", "", "",[[0,0],[8,8]],[ + [[2,1],[2,2],[3,2],[3,4],[4,4],[4,5],[3,5],[3,7],[2,7],[2,8],[4,8],[4,7],[5,7],[5,5],[6,5],[6,4],[5,4],[5,2],[4,2],[4,1]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[126,"~","~", "", "",[[0,0],[8,8]],[ + [[2,5],[2,6] + ,[3-dx,6],[3,6+dy] + ,[3,7],[5,7],[5,6] + ,[6-dx,6],[6,6+dy] + ,[6,7],[7,7],[7,6] + ,[6+dx,6],[6,6-dy] + ,[6,5],[4,5],[4,6] + ,[3+dx,6],[3,6-dy] + ,[3,5]] + ,[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]] + ]] + ,[127,"^?","", "DEL","Delete",[[0,0],[8,8]],[]] + ] ]; + diff --git a/involute_gears.scad b/involute_gears.scad index eaf9051..fd80efe 100644 --- a/involute_gears.scad +++ b/involute_gears.scad @@ -286,7 +286,7 @@ module involute_bevel_gear_tooth ( [side2_point2[0],side2_point2[1],0], [side2_point1[0],side2_point1[1],0], [0.1,0,0]], - triangles=[[0,1,2],[0,2,3],[0,3,4],[0,5,1],[1,5,2],[2,5,3],[3,5,4],[0,4,5]]); + triangles=[[0,2,1],[0,3,2],[0,4,3],[0,1,5],[1,2,5],[2,3,5],[3,4,5],[0,5,4]]); } } } diff --git a/lego_compatibility.scad b/lego_compatibility.scad new file mode 100644 index 0000000..d47b567 --- /dev/null +++ b/lego_compatibility.scad @@ -0,0 +1,157 @@ +// This file is placed under the public domain + +// from: http://www.thingiverse.com/thing:9512 + + +// EXAMPLES: +// standard LEGO 2x1 tile has no pin +// block(1,2,1/3,reinforcement=false,flat_top=true); +// standard LEGO 2x1 flat has pin +// block(1,2,1/3,reinforcement=true); +// standard LEGO 2x1 brick has pin +// block(1,2,1,reinforcement=true); +// standard LEGO 2x1 brick without pin +// block(1,2,1,reinforcement=false); +// standard LEGO 2x1x5 brick has no pin and has hollow knobs +// block(1,2,5,reinforcement=false,hollow_knob=true); + + +knob_diameter=4.8; //knobs on top of blocks +knob_height=2; +knob_spacing=8.0; +wall_thickness=1.45; +roof_thickness=1.05; +block_height=9.5; +pin_diameter=3; //pin for bottom blocks with width or length of 1 +post_diameter=6.5; +reinforcing_width=1.5; +axle_spline_width=2.0; +axle_diameter=5; +cylinder_precision=0.5; + +/* EXAMPLES: + +block(2,1,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=true); + +translate([50,-10,0]) + block(1,2,1/3,axle_hole=false,circular_hole=true,reinforcement=false,hollow_knob=true,flat_top=true); + +translate([10,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=true); +translate([30,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=false,flat_top=false); +translate([50,0,0]) + block(2,2,1/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=false); +translate([0,20,0]) + block(3,2,2/3,axle_hole=false,circular_hole=true,reinforcement=true,hollow_knob=true,flat_top=false); +translate([20,20,0]) + block(3,2,1,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=false,flat_top=false); +translate([40,20,0]) + block(3,2,1/3,axle_hole=false,circular_hole=false,reinforcement=false,hollow_knob=false,flat_top=false); +translate([0,-10,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=false,flat_top=false); +translate([0,-20,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=true,flat_top=false); +translate([0,-30,0]) + block(1,5,1/3,axle_hole=true,circular_hole=false,reinforcement=true,hollow_knob=true,flat_top=true); +//*/ + +module block(width,length,height,axle_hole=false,reinforcement=false, hollow_knob=false, flat_top=false, circular_hole=false, solid_bottom=true, center=false) { + overall_length=(length-1)*knob_spacing+knob_diameter+wall_thickness*2; + overall_width=(width-1)*knob_spacing+knob_diameter+wall_thickness*2; + center= center==true ? 1 : 0; + translate(center*[-overall_length/2, -overall_width/2, 0]) + union() { + difference() { + union() { + // body: + cube([overall_length,overall_width,height*block_height]); + // knobs: + if (flat_top != true) + translate([knob_diameter/2+wall_thickness,knob_diameter/2+wall_thickness,0]) + for (ycount=[0:width-1]) + for (xcount=[0:length-1]) { + translate([xcount*knob_spacing,ycount*knob_spacing,0]) + difference() { + cylinder(r=knob_diameter/2,h=block_height*height+knob_height,$fs=cylinder_precision); + if (hollow_knob==true) + translate([0,0,-roof_thickness]) + cylinder(r=pin_diameter/2,h=block_height*height+knob_height+2*roof_thickness,$fs=cylinder_precision); + } + } + } + // hollow bottom: + if (solid_bottom == false) + translate([wall_thickness,wall_thickness,-roof_thickness]) cube([overall_length-wall_thickness*2,overall_width-wall_thickness*2,block_height*height]); + // flat_top -> groove around bottom + if (flat_top == true) { + translate([-wall_thickness/2,-wall_thickness*2/3,-wall_thickness/2]) + cube([overall_length+wall_thickness,wall_thickness,wall_thickness]); + translate([-wall_thickness/2,overall_width-wall_thickness/3,-wall_thickness/2]) + cube([overall_length+wall_thickness,wall_thickness,wall_thickness]); + + translate([-wall_thickness*2/3,-wall_thickness/2,-wall_thickness/2]) + cube([wall_thickness,overall_width+wall_thickness,wall_thickness]); + translate([overall_length-wall_thickness/3,0,-wall_thickness/2]) + cube([wall_thickness,overall_width+wall_thickness,wall_thickness]); + } + if (axle_hole==true) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,roof_thickness]) axle(height); + if (circular_hole==true) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,roof_thickness]) + cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness/4,$fs=cylinder_precision); + } + + if (reinforcement==true && width>1 && length>1) + difference() { + for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,0]) reinforcement(height); + for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,-roof_thickness/2]) cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness, $fs=cylinder_precision); + } + // posts: + if (solid_bottom == false) + if (width>1 && length>1) for (ycount=[1:width-1]) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,ycount*knob_spacing,0]) post(height); + + if (reinforcement == true && width==1 && length!=1) + for (xcount=[1:length-1]) + translate([xcount*knob_spacing,overall_width/2,0]) cylinder(r=pin_diameter/2,h=block_height*height,$fs=cylinder_precision); + + if (reinforcement == true && length==1 && width!=1) + for (ycount=[1:width-1]) + translate([overall_length/2,ycount*knob_spacing,0]) cylinder(r=pin_diameter/2,h=block_height*height,$fs=cylinder_precision); + } +} + +module post(height) { + difference() { + cylinder(r=post_diameter/2, h=height*block_height-roof_thickness/2,$fs=cylinder_precision); + translate([0,0,-roof_thickness/2]) + cylinder(r=knob_diameter/2, h=height*block_height+roof_thickness/4,$fs=cylinder_precision); + } +} + +module reinforcement(height) { + union() { + translate([0,0,height*block_height/2]) union() { + cube([reinforcing_width,knob_spacing+knob_diameter+wall_thickness/2,height*block_height],center=true); + rotate(v=[0,0,1],a=90) cube([reinforcing_width,knob_spacing+knob_diameter+wall_thickness/2,height*block_height], center=true); + } + } +} + +module axle(height) { + translate([0,0,height*block_height/2]) union() { + cube([axle_diameter,axle_spline_width,height*block_height],center=true); + cube([axle_spline_width,axle_diameter,height*block_height],center=true); + } +} + diff --git a/multiply.scad b/multiply.scad new file mode 100644 index 0000000..bca12c3 --- /dev/null +++ b/multiply.scad @@ -0,0 +1,29 @@ +/* + * Multiplication along certain curves + * + * Copyright by Elmo Mäntynen, 2012. + * Licenced under LGPL2 or later + */ + +include + +use + +// TODO check that the axis parameter works as intended +// Duplicate everything $no of times around an $axis, for $angle/360 rounds +module spin(no, angle=360, axis=Z){ + for (i = [1:no]){ + rotate(normalized_axis(axis)*angle*no/i) union(){ + for (i = [0 : $children-1]) child(i); + } + } +} + +//Doesn't work currently +module duplicate(axis=Z) spin(no=2, axis=axis) child(0); + +module linear_multiply(no, separation, axis=Z){ + for (i = [0:no-1]){ + translate(i*separation*axis) child(0); + } +} diff --git a/openscad_testing.py b/openscad_testing.py index 64d96c7..cadbc2f 100644 --- a/openscad_testing.py +++ b/openscad_testing.py @@ -1,5 +1,5 @@ import py - +import os.path from openscad_utils import * @@ -8,12 +8,14 @@ temppath = py.test.ensuretemp('MCAD') def pytest_generate_tests(metafunc): if "modpath" in metafunc.funcargnames: for fpath, modnames in collect_test_modules().items(): + basename = os.path.splitext(os.path.split(str(fpath))[1])[0] #os.system("cp %s %s/" % (fpath, temppath)) if "modname" in metafunc.funcargnames: for modname in modnames: - metafunc.addcall(funcargs=dict(modname=modname, modpath=fpath)) + print modname + metafunc.addcall(id=basename+"/"+modname, funcargs=dict(modname=modname, modpath=fpath)) else: - metafunc.addcall(funcargs=dict(modpath=fpath)) + metafunc.addcall(id=os.path.split(str(fpath))[1], funcargs=dict(modpath=fpath)) def test_module_compile(modname, modpath): diff --git a/openscad_utils.py b/openscad_utils.py index 3f2875e..00d8dd9 100644 --- a/openscad_utils.py +++ b/openscad_utils.py @@ -1,4 +1,4 @@ -import py, re, os, signal, time, commands +import py, re, os, signal, time, commands, sys from subprocess import Popen, PIPE mod_re = (r"\bmodule\s+(", r")\s*\(\s*") @@ -30,7 +30,9 @@ def collect_test_modules(dirpath=None): class Timeout(Exception): pass def call_openscad(path, stlpath, timeout=5): - command = ['openscad', '-s', str(stlpath), str(path)] + if sys.platform == 'darwin': exe = 'OpenSCAD.app/Contents/MacOS/OpenSCAD' + else: exe = 'openscad' + command = [exe, '-s', str(stlpath), str(path)] print command if timeout: try: diff --git a/regular_shapes.scad b/regular_shapes.scad index 67fee52..acba0bc 100644 --- a/regular_shapes.scad +++ b/regular_shapes.scad @@ -1,6 +1,6 @@ /* * OpenSCAD Shapes Library (www.openscad.org) - * Copyright (C) 2010-2011 Giles Bathgate + * Copyright (C) 2010-2011 Giles Bathgate, Elmo Mäntynen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ module triangle(radius) module reg_polygon(sides,radius) { - function dia(r) = sqrt(pow(r*2,2)/2); //sqrt(r*2^2/2) if only we had an exponention op + function dia(r) = sqrt(pow(r*2,2)/2); //sqrt((r*2^2)/2) if only we had an exponention op if(sides<2) square([radius,0]); if(sides==3) triangle(radius); if(sides==4) square([dia(radius),dia(radius)],center=true); @@ -76,13 +76,21 @@ module dodecagon(radius) reg_polygon(12,radius); } +module ring(inside_diameter, thickness){ + difference(){ + circle(r=(inside_diameter+thickness*2)/2); + circle(r=inside_diameter/2); + } +} + module ellipse(width, height) { scale([1, height/width, 1]) circle(r=width/2); } +// The ratio of lenght and width is about 1.39 for a real egg module egg_outline(width, length){ - union(){ - difference(){ + translate([0, width/2, 0]) union(){ + rotate([0, 0, 180]) difference(){ ellipse(width, 2*length-width); translate([-length/2, 0, 0]) square(length); } @@ -92,17 +100,17 @@ module egg_outline(width, length){ //3D regular shapes -module cone(height, radius, center = false) +module cone(height, radius, center = false) { cylinder(height, radius, 0, center); } -module oval_prism(height, rx, ry, center = false) +module oval_prism(height, rx, ry, center = false) { scale([1, rx/ry, 1]) cylinder(h=height, r=ry, center=center); } -module oval_tube(height, rx, ry, wall, center = false) +module oval_tube(height, rx, ry, wall, center = false) { difference() { scale([1, ry/rx, 1]) cylinder(h=height, r=rx, center=center); @@ -110,7 +118,7 @@ module oval_tube(height, rx, ry, wall, center = false) } } -module cylinder_tube(height, radius, wall, center = false) +module cylinder_tube(height, radius, wall, center = false) { tubify(radius,wall) cylinder(h=height, r=radius, center=center); @@ -143,50 +151,76 @@ module pentagon_prism(height,radius) module pentagon_tube(height,radius,wall) { - tubify(radius,wall) pentagon_prism(height,radius); + tubify(radius,wall) pentagon_prism(height,radius); } -module hexagon_prism(height,radius) +module hexagon_prism(height,radius) { linear_extrude(height=height) hexagon(radius); } -module heptagon_prism(height,radius) +module hexagon_tube(height,radius,wall) +{ + tubify(radius,wall) hexagon_prism(height,radius); +} + +module heptagon_prism(height,radius) { linear_extrude(height=height) heptagon(radius); } -module octagon_prism(height,radius) +module heptagon_tube(height,radius,wall) { - linear_extrude(height=height) octagon(radius); + tubify(radius,wall) heptagon_prism(height,radius); +} + +module octagon_prism(height,radius) +{ + linear_extrude(height=height) octagon(radius); +} + +module octagon_tube(height,radius,wall) +{ + tubify(radius,wall) octagon_prism(height,radius); } module nonagon_prism(height,radius) { - linear_extrude(height=height) nonagon(radius); + linear_extrude(height=height) nonagon(radius); } module decagon_prism(height,radius) { - linear_extrude(height=height) decagon(radius); + linear_extrude(height=height) decagon(radius); } module hendecagon_prism(height,radius) { - linear_extrude(height=height) hendecagon(radius); + linear_extrude(height=height) hendecagon(radius); } module dodecagon_prism(height,radius) { - linear_extrude(height=height) dodecagon(radius); + linear_extrude(height=height) dodecagon(radius); } module torus(outerRadius, innerRadius) { r=(outerRadius-innerRadius)/2; - rotate_extrude() translate([innerRadius+r,0,0]) circle(r); + rotate_extrude() translate([innerRadius+r,0,0]) circle(r); } +module torus2(r1, r2) +{ + rotate_extrude() translate([r1,0,0]) circle(r2); +} + +module oval_torus(inner_radius, thickness=[0, 0]) +{ + rotate_extrude() translate([inner_radius+thickness[0]/2,0,0]) ellipse(width=thickness[0], height=thickness[1]); +} + + module triangle_pyramid(radius) { o=radius/2; //equivalent to radius*sin(30) @@ -201,6 +235,14 @@ module square_pyramid(base_x, base_y,height) polyhedron(points=[[-w,-h,0],[-w,h,0],[w,h,0],[w,-h,0],[0,0,height]],triangles=[[0,3,2,1], [0,1,4], [1,2,4], [2,3,4], [3,0,4]]); } +module egg(width, lenght){ + rotate_extrude() + difference(){ + egg_outline(width, lenght); + translate([-lenght, 0, 0]) cube(2*lenght, center=true); + } +} + // Tests: test_square_pyramid(){square_pyramid(10, 20, 30);} diff --git a/teardrop.scad b/teardrop.scad index 7a3b0fe..a1a0708 100644 --- a/teardrop.scad +++ b/teardrop.scad @@ -1,8 +1,22 @@ -// From http://www.thingiverse.com/thing:3457 -// © 2010 whosawhatsis +/* From http://www.thingiverse.com/thing:3457 + © 2010 whosawhatsis + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ /* -This script generates a teardrop shape at the appropriate angle to prevent overhangs greater than 45 degrees. The angle is in degrees, and is a rotation around the Y axis. You can then rotate around Z to point it in any direction. Rotation around Y or Z will cause the angle to be wrong. +This script generates a teardrop shape at the appropriate angle to prevent overhangs greater than 45 degrees. The angle is in degrees, and is a rotation around the Y axis. You can then rotate around Z to point it in any direction. Rotation around X or Y will cause the angle to be wrong. */ module teardrop(radius, length, angle) { diff --git a/test_docs.py b/test_docs.py index 043be9a..cbf9b11 100644 --- a/test_docs.py +++ b/test_docs.py @@ -1,15 +1,16 @@ import py +import os.path dirpath = py.path.local("./") def pytest_generate_tests(metafunc): if "filename" in metafunc.funcargnames: for fpath in dirpath.visit('*.scad'): - metafunc.addcall(funcargs=dict(filename=fpath.basename)) + metafunc.addcall(id=fpath.basename, funcargs=dict(filename=fpath.basename)) for fpath in dirpath.visit('*.py'): name = fpath.basename if not (name.startswith('test_') or name.startswith('_')): - metafunc.addcall(funcargs=dict(filename=fpath.basename)) + metafunc.addcall(id=fpath.basename, funcargs=dict(filename=fpath.basename)) def test_README(filename): README = dirpath.join('README').read() diff --git a/transformations.scad b/transformations.scad new file mode 100644 index 0000000..b180f58 --- /dev/null +++ b/transformations.scad @@ -0,0 +1,3 @@ +module scale(v, reference=[0, 0, 0]) { + translate(-reference) scale(v) translate(reference) child(0); +} diff --git a/triangles.scad b/triangles.scad index 2482d06..357f7d4 100644 --- a/triangles.scad +++ b/triangles.scad @@ -56,7 +56,7 @@ module test_triangles() // Generate a bunch of triangles by angle for (i = [1:85/5]) { - translate([i*7, 20, i*7]) + translate([i*7, 22, i*7]) { a_triangle(i*5, 10, 5); } diff --git a/trochoids.scad b/trochoids.scad new file mode 100644 index 0000000..a0d00bb --- /dev/null +++ b/trochoids.scad @@ -0,0 +1,290 @@ +//=========================================== +// Public Domain Epi- and Hypo- trochoids in OpenSCAD +// version 1.0 +// by Matt Moses, 2011, mmoses152@gmail.com +// http://www.thingiverse.com/thing:8067 +// +// This file is public domain. Use it for any purpose, including commercial +// applications. Attribution would be nice, but is not required. There is +// no warranty of any kind, including its correctness, usefulness, or safety. +// +// An EPITROCHOID is a curve traced by a point +// fixed at a distance "d" +// to the center of a circle of radius "r" +// as the circle rolls +// outside another circle of radius "R". +// +// An HYPOTROCHOID is a curve traced by a point +// fixed at a distance "d" +// to the center of a circle of radius "r" +// as the circle rolls +// inside another circle of radius "R". +// +// An EPICYCLOID is an epitrochoid with d = r. +// +// An HYPOCYCLOID is an hypotrochoid with d = r. +// +// See http://en.wikipedia.org/wiki/Epitrochoid +// and http://en.wikipedia.org/wiki/Hypotrochoid +// +// Beware the polar forms of the equations on Wikipedia... +// They are correct, but theta is measured to the center of the small disk!! +//=========================================== + +// There are several different methods for extruding. The best are probably +// the ones using linear extrude. + + +//=========================================== +// Demo - draws one of each, plus some little wheels and sticks. +// +// Fun stuff to try: +// Animate, try FPS = 5 and Steps = 200 +// R = 2, r = 1, d = 0.2 +// R = 4, r = 1, d = 1 +// R = 2, r = 1, d = 0.5 +// +// What happens when you make d > r ?? +// What happens when d < 0 ?? +// What happens when r < 0 ?? +// +//=========================================== + +$fn = 30; + +thickness = 2; +R = 4; +r = 1; +d = 1; +n = 60; // number of wedge segments + +alpha = 360*$t; + +color([0, 0, 1]) +translate([0, 0, -0.5]) + cylinder(h = 1, r= R, center = true); + +color([0, 1, 0]) +epitrochoid(R,r,d,n,thickness); + +color([1, 0, 0]) +translate([ (R+r)*cos(alpha) , (R+r)*sin(alpha), -0.5]) { + rotate([0, 0, alpha + R/r*alpha]) { + cylinder(h = 1, r = r, center = true); + translate([-d, 0, 1.5]) { + cylinder(h = 2.2, r = 0.1, center = true); + } + } +} + + +translate([2*(abs(R) + abs(r) + abs(d)), 0, 0]){ +color([0, 0, 1]) +translate([0, 0, -0.5]) + difference() { + cylinder(h = 1, r = 1.1*R, center = true); + cylinder(h = 1.1, r= R, center = true); + } + +color([0, 1, 0]) +hypotrochoid(R,r,d,n,thickness); + +color([1, 0, 0]) +translate([ (R-r)*cos(alpha) , (R-r)*sin(alpha), -0.5]) { + rotate([0, 0, alpha - R/r*alpha]) { + cylinder(h = 1, r = r, center = true); + translate([d, 0, 1.5]) { + cylinder(h = 2.2, r = 0.1, center = true); + } + } +} +} + +// This just makes a twisted hypotrochoid +translate([0,14, 0]) +hypotrochoidLinear(4, 1, 1, 40, 40, 10, 30); + +// End of Demo Section +//=========================================== + + +//=========================================== +// Epitrochoid +// +module epitrochoid(R, r, d, n, thickness) { + dth = 360/n; + for ( i = [0:n-1] ) { + polyhedron(points = [[0,0,0], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i), 0], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1)), 0], + [0,0,thickness], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i), thickness], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1)), thickness]], + triangles = [[0, 2, 1], + [0, 1, 3], + [3, 1, 4], + [3, 4, 5], + [0, 3, 2], + [2, 3, 5], + [1, 2, 4], + [2, 5, 4]]); + } +} +//=========================================== + + +//=========================================== +// Hypotrochoid +// +module hypotrochoid(R, r, d, n, thickness) { + dth = 360/n; + for ( i = [0:n-1] ) { + polyhedron(points = [[0,0,0], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i), 0], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1)), 0], + [0,0,thickness], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i), thickness], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1)), thickness]], + triangles = [[0, 2, 1], + [0, 1, 3], + [3, 1, 4], + [3, 4, 5], + [0, 3, 2], + [2, 3, 5], + [1, 2, 4], + [2, 5, 4]]); + } +} +//=========================================== + + +//=========================================== +// Epitrochoid Wedge with Bore +// +module epitrochoidWBore(R, r, d, n, p, thickness, rb) { + dth = 360/n; + union() { + for ( i = [0:p-1] ) { + polyhedron(points = [[rb*cos(dth*i), rb*sin(dth*i),0], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i), 0], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1)), 0], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1)), 0], + [rb*cos(dth*i), rb*sin(dth*i), thickness], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i), thickness], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1)), thickness], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1)), thickness]], + triangles = [[0, 1, 4], [4, 1, 5], + [1, 2, 5], [5, 2, 6], + [2, 3, 7], [7, 6, 2], + [3, 0, 4], [4, 7, 3], + [4, 5, 7], [7, 5, 6], + [0, 3, 1], [1, 3, 2]]); + } + } +} +//=========================================== + + +//=========================================== +// Epitrochoid Wedge with Bore, Linear Extrude +// +module epitrochoidWBoreLinear(R, r, d, n, p, thickness, rb, twist) { + dth = 360/n; + linear_extrude(height = thickness, convexity = 10, twist = twist) { + union() { + for ( i = [0:p-1] ) { + polygon(points = [[rb*cos(dth*i), rb*sin(dth*i)], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i)], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1))], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1))]], + paths = [[0, 1, 2, 3]], convexity = 10); + } + } + } +} +//=========================================== + + +//=========================================== +// Epitrochoid Wedge, Linear Extrude +// +module epitrochoidLinear(R, r, d, n, p, thickness, twist) { + dth = 360/n; + linear_extrude(height = thickness, convexity = 10, twist = twist) { + union() { + for ( i = [0:p-1] ) { + polygon(points = [[0, 0], + [(R+r)*cos(dth*i) - d*cos((R+r)/r*dth*i), (R+r)*sin(dth*i) - d*sin((R+r)/r*dth*i)], + [(R+r)*cos(dth*(i+1)) - d*cos((R+r)/r*dth*(i+1)), (R+r)*sin(dth*(i+1)) - d*sin((R+r)/r*dth*(i+1))]], + paths = [[0, 1, 2]], convexity = 10); + } + } + } +} +//=========================================== + + +//=========================================== +// Hypotrochoid Wedge with Bore +// +module hypotrochoidWBore(R, r, d, n, p, thickness, rb) { + dth = 360/n; + union() { + for ( i = [0:p-1] ) { + polyhedron(points = [[rb*cos(dth*i), rb*sin(dth*i),0], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i), 0], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1)), 0], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1)), 0], + [rb*cos(dth*i), rb*sin(dth*i), thickness], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i), thickness], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1)), thickness], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1)), thickness]], + triangles = [[0, 1, 4], [4, 1, 5], + [1, 2, 5], [5, 2, 6], + [2, 3, 7], [7, 6, 2], + [3, 0, 4], [4, 7, 3], + [4, 5, 7], [7, 5, 6], + [0, 3, 1], [1, 3, 2]]); + } + } +} +//=========================================== + + +//=========================================== +// Hypotrochoid Wedge with Bore, Linear Extrude +// +module hypotrochoidWBoreLinear(R, r, d, n, p, thickness, rb, twist) { + dth = 360/n; + linear_extrude(height = thickness, convexity = 10, twist = twist) { + union() { + for ( i = [0:p-1] ) { + polygon(points = [[rb*cos(dth*i), rb*sin(dth*i)], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i)], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1))], + [rb*cos(dth*(i+1)), rb*sin(dth*(i+1))]], + paths = [[0, 1, 2, 3]], convexity = 10); + } + } + } +} +//=========================================== + + +//=========================================== +// Hypotrochoid Wedge, Linear Extrude +// +module hypotrochoidLinear(R, r, d, n, p, thickness, twist) { + dth = 360/n; + linear_extrude(height = thickness, convexity = 10, twist = twist) { + union() { + for ( i = [0:p-1] ) { + polygon(points = [[0, 0], + [(R-r)*cos(dth*i) + d*cos((R-r)/r*dth*i), (R-r)*sin(dth*i) - d*sin((R-r)/r*dth*i)], + [(R-r)*cos(dth*(i+1)) + d*cos((R-r)/r*dth*(i+1)), (R-r)*sin(dth*(i+1)) - d*sin((R-r)/r*dth*(i+1))]], + paths = [[0, 1, 2]], convexity = 10); + } + } + } +} +//=========================================== diff --git a/units.scad b/units.scad index 62662a9..61d0d7f 100644 --- a/units.scad +++ b/units.scad @@ -10,8 +10,13 @@ mm = 1; cm = 10 * mm; dm = 100 * mm; m = 1000 * mm; + inch = 25.4 * mm; +X = [1, 0, 0]; +Y = [0, 1, 0]; +Z = [0, 0, 1]; + M3 = 3*mm; M4 = 4*mm; M5 = 5*mm; diff --git a/unregular_shapes.scad b/unregular_shapes.scad new file mode 100644 index 0000000..f1d0a64 --- /dev/null +++ b/unregular_shapes.scad @@ -0,0 +1,10 @@ +// Copyright 2011 Elmo Mäntynen +// LGPL 2.1 + +// Give a list of 4+4 points (check order) to form an 8 point polyhedron +module connect_squares(points){ + polyhedron(points=points, + triangles=[[0,1,2], [3,0,2], [7,6,5], [7,5,4], // Given polygons + [0,4,1], [4,5,1], [1,5,2], [2,5,6], // Connecting + [2,6,3], [3,6,7], [3,4,0], [3,7,4]]);// sides +} diff --git a/utilities.scad b/utilities.scad index 6d6468d..01e4511 100644 --- a/utilities.scad +++ b/utilities.scad @@ -15,7 +15,9 @@ function length2(a) = sqrt( a[0]*a[0] + a[1]*a[1] ); function normalized(a) = a / (max(distance([0,0,0], a), 0.00001)); - +function normalized_axis(a) = a == "x" ? [1, 0, 0]: + a == "y" ? [0, 1, 0]: + a == "z" ? [0, 0, 1]: normalized(a); function angleOfNormalizedVector(n) = [0, -atan2(n[2], length2([n[0], n[1]])), atan2(n[1], n[0]) ]; @@ -23,16 +25,6 @@ function angle(v) = angleOfNormalizedVector(normalized(v)); function angleBetweenTwoPoints(a, b) = angle(normalized(b-a)); -// TODO check that the axis parameter works as intended -// Duplicate everything $no of times around an $axis, for $angle/360 rounds -module spin(no, angle=360, axis=[0, 0, 1]){ - for (i = [0:no]){ - rotate(normalized(axis)*angle*i/no) union(){ - for (i = [0 : $children-1]) child(i); - } - } -} - CENTER = 0; LEFT = -0.5;