diff --git a/cameo/Makefile b/cameo/Makefile index d1b4b86..549e649 100644 --- a/cameo/Makefile +++ b/cameo/Makefile @@ -15,7 +15,8 @@ PREFIX ?= /usr/local SHELL=/bin/bash MAIN=cameo -OBJS=cameo.o excellon.o gerber.o gnuplot.o ops.o path.o lex.yy.o y.tab.o +OBJS=cameo.o excellon.o gerber.o gnuplot.o ops.o path.o shape.o \ + lex.yy.o y.tab.o CFLAGS_WARN=-Wall -Wshadow -Wmissing-prototypes \ -Wmissing-declarations -Wno-format-zero-length diff --git a/cameo/README b/cameo/README index e6b1de1..6e3216b 100644 --- a/cameo/README +++ b/cameo/README @@ -136,3 +136,11 @@ Concave corners on an outside path are normally cut such that the corner is round, leaving material at and near the corner point. The option "dog" changes this to cutting a "dogbone" hole such that material is also removed up to the corner point. + + +Drill/mill substitution: + + drill + mill + remainder + empty diff --git a/cameo/lang.l b/cameo/lang.l index 9356334..4e1bd72 100644 --- a/cameo/lang.l +++ b/cameo/lang.l @@ -42,8 +42,12 @@ NUM -?[0-9]+\.?[0-9]* return TOK_ALIGN; } array return TOK_ARRAY; clear return TOK_CLEAR; -reset return TOK_RESET; +drill return TOK_DRILL; +empty return TOK_EMPTY; +mill return TOK_MILL; offset return TOK_OFFSET; +remainder return TOK_REMAINDER; +reset return TOK_RESET; translate return TOK_TRANSLATE; z return TOK_Z; diff --git a/cameo/lang.y b/cameo/lang.y index f382736..a960996 100644 --- a/cameo/lang.y +++ b/cameo/lang.y @@ -25,6 +25,7 @@ static double xo = 0, yo = 0, zo = 0; static struct path *paths = NULL; +static struct path *remain = NULL; #define MIL2MM(mil) ((mil)/1000*25.4) @@ -108,6 +109,33 @@ static void align(int ref, double x, double y) } +static void clear_paths(void) +{ + struct path *next; + + while (paths) { + next = paths->next; + path_free(paths); + paths = next; + } +} + + +static struct path **classify(struct path **anchor, struct path *path) +{ + struct path **walk, *next; + + if (!path) + return &(*anchor)->next; + for (walk = &paths; *walk; walk = &(*walk)->next); + *walk = path; + next = (*anchor)->next; + path_free(*anchor); + *anchor = next; + return anchor; +} + + %} @@ -121,7 +149,8 @@ static void align(int ref, double x, double y) }; -%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_RESET TOK_OFFSET +%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_DRILL TOK_EMPTY +%token TOK_MILL TOK_OFFSET TOK_REMAINDER TOK_RESET %token TOK_TRANSLATE TOK_Z %token TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE %token TOK_DOG TOK_INSIDE @@ -166,13 +195,7 @@ command: } | TOK_CLEAR { - struct path *next; - - while (paths) { - next = paths->next; - path_free(paths); - paths = next; - } + clear_paths(); } | TOK_RESET { @@ -218,6 +241,38 @@ command: gnuplot_write($2, paths); translate(0, 0, -zo); } + | TOK_DRILL dimen dimen + { + struct path **walk; + + remain = paths; + paths = NULL; + walk = &paths; + while (*walk) + walk = + classify(walk, try_drill(*walk, $2, $3)); + } + | TOK_MILL dimen dimen + { + struct path **walk; + + remain = paths; + paths = NULL; + walk = &paths; + while (*walk) + walk = classify(walk, try_mill(*walk, $2, $3)); + } + | TOK_REMAINDER + { + clear_paths(); + paths = remain; + remain = NULL; + } + | TOK_EMPTY + { + if (paths) + yyerror("path list is not empty"); + } ; opt_filename: diff --git a/cameo/ops.c b/cameo/ops.c index 74c4cfa..f73f396 100644 --- a/cameo/ops.c +++ b/cameo/ops.c @@ -11,7 +11,10 @@ */ +#include + #include "path.h" +#include "shape.h" #include "ops.h" @@ -54,3 +57,34 @@ void tool_comp_paths(struct path *paths, int dog_bone, int all_inside) tool_comp_1(path, 0, dog_bone); tool_comp_1(leftmost, !all_inside, dog_bone); } + + +struct path *try_drill(struct path *path, double d_min, double d_max) +{ + struct path *new; + + if (path->r_tool*2 < d_min || path->r_tool*2 > d_max) + return NULL; + if (!path->first || path->first != path->last) + return NULL; + new = path_new((d_min+d_max)/2); /* @@@ fishy */ + path_add(new, path->first->x, path->first->y, path->first->z); + return new; +} + + +struct path *try_mill(struct path *path, double diam, double step) +{ + if (path->r_tool*2 < diam) + return NULL; + if (!path->first) + return NULL; + if (path->first == path->last) + return circle(path->first->x, path->first->y, path->first->z, + path->r_tool, diam/2, step); + if (path->first->next == path->last) + return slot(path->first->x, path->first->y, + path->first->next->x, path->first->next->y, + path->first->z, path->r_tool, diam/2, step); + return NULL; +} diff --git a/cameo/ops.h b/cameo/ops.h index a40fcf9..ad20b1e 100644 --- a/cameo/ops.h +++ b/cameo/ops.h @@ -14,10 +14,11 @@ #ifndef OPS_H #define OPS_H - #include "path.h" void tool_comp_paths(struct path *paths, int dog_bone, int all_inside); +struct path *try_drill(struct path *path, double d_min, double d_max); +struct path *try_mill(struct path *path, double diam, double step); #endif /* !OPS_H */ diff --git a/cameo/shape.c b/cameo/shape.c new file mode 100644 index 0000000..e8c1819 --- /dev/null +++ b/cameo/shape.c @@ -0,0 +1,83 @@ +/* + * shape.c - Toolpaths for basic shapes + * + * Written 2010 by Werner Almesberger + * Copyright 2010 Werner Almesberger + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include + +#include "path.h" +#include "shape.h" + + +static struct path *path; + + +static double arc2angle(double arc, double r) +{ + return acos(1-arc*arc/(r*r)/2); +} + + +static void half_circle(double cx, double cy, double rx, double ry, double z, + double s) +{ + double m[4]; + double x = rx, y = ry, tmp; + double a; + + m[0] = cos(s); + m[1] = -sin(s); + m[2] = -m[1]; + m[3] = m[0]; + + for (a = 0; a < M_PI; a += s) { + path_add(path, cx+x, cy+x, z); + tmp = x*m[0]+y*m[1]; + y = x*m[2]+y*m[3]; + x = tmp; + } + path_add(path, cx-rx, cy-ry, z); +} + + +struct path *slot(double xa, double ya, double xb, double yb, double z, + double sr, double tr, double step) +{ + double dx = xb-xa; + double dy = yb-ya; + double s = arc2angle(step, sr); + double nx, ny; + double f; + + f = (sr-tr)/hypot(dx, dy); + nx = -dy*f; + ny = dx*f; + + path = path_new(tr); + half_circle(xa, ya, nx, ny, z, s); + half_circle(xb, yb, -nx, -ny, z, s); + path_add(path, xa+nx, ya+ny, z); + return path; +} + + +struct path *circle(double cx, double cy, double cz, double cr, double tr, + double step) +{ + double s = arc2angle(step, cr); + double a; + + path = path_new(tr); + for (a = 0; a < 2*M_PI; a += s) + path_add(path, cx+(cr-tr)*cos(a), cy+(cr-tr)*sin(a), cz); + path_add(path, cx+(cr-tr), cy, cz); + return path; +} diff --git a/cameo/shape.h b/cameo/shape.h new file mode 100644 index 0000000..98e280f --- /dev/null +++ b/cameo/shape.h @@ -0,0 +1,25 @@ +/* + * shape.h - Toolpaths for basic shapes + * + * Written 2010 by Werner Almesberger + * Copyright 2010 Werner Almesberger + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef SHAPE_H +#define SHAPE_H + +#include "path.h" + + +struct path *slot(double xa, double ya, double xb, double yb, double z, + double sr, double tr, double step); +struct path *circle(double cx, double cy, double cz, double cr, double tr, + double step); + +#endif /* !SHAPE_H */