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;