From 57b4e276e5836abdcd198f571663a743e8acbf86 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 16 Dec 2010 14:19:46 -0300 Subject: [PATCH] cameo: added optimization of movements between tool paths - ops.h, ops.c (optimize_paths): reorder toolpaths to reduce the distance between them - lang.l, lang.y: added command "optimize" - README: documented "optimize" --- cameo/README | 9 +++++++++ cameo/lang.l | 1 + cameo/lang.y | 6 +++++- cameo/ops.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ cameo/ops.h | 1 + 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/cameo/README b/cameo/README index 0529e28..bb4dad0 100644 --- a/cameo/README +++ b/cameo/README @@ -179,3 +179,12 @@ and write the toolpaths to the file "drill.gp". Next, we retrieve the remaining paths, generate toolpaths for a 0.8 mm endmill, and write them to the file "mill.gp". Finally, we check that all paths have been processed. + + +Tool path optimization: + + optimize + +Try to reduce the movements made between paths by reordering the paths. +Note that this disturbs the order generated by "offset" and should thus +not be used on paths that to be executed in a specific sequence. diff --git a/cameo/lang.l b/cameo/lang.l index 9fb0de8..605f41c 100644 --- a/cameo/lang.l +++ b/cameo/lang.l @@ -46,6 +46,7 @@ NUM -?[0-9]+\.?[0-9]* empty return TOK_EMPTY; mill return TOK_MILL; offset return TOK_OFFSET; +optimize return TOK_OPTIMIZE; remainder return TOK_REMAINDER; reset return TOK_RESET; translate return TOK_TRANSLATE; diff --git a/cameo/lang.y b/cameo/lang.y index af69ae7..938115b 100644 --- a/cameo/lang.y +++ b/cameo/lang.y @@ -150,7 +150,7 @@ static struct path **classify(struct path **anchor, struct path *path) %token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_DRILL TOK_EMPTY -%token TOK_MILL TOK_OFFSET TOK_REMAINDER TOK_RESET +%token TOK_MILL TOK_OFFSET TOK_OPTIMIZE TOK_REMAINDER TOK_RESET %token TOK_TRANSLATE TOK_Z %token TOK_APPEND TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE %token TOK_DOG TOK_INSIDE @@ -208,6 +208,10 @@ command: tool_comp_paths(paths, !!($2 & OO_DOG), !!($2 & OO_INSIDE)); } + | TOK_OPTIMIZE + { + paths = optimize_paths(paths); + } | TOK_TRANSLATE dimen dimen { translate(paths, $2, $3, 0); diff --git a/cameo/ops.c b/cameo/ops.c index d5b4ac5..93ba2ea 100644 --- a/cameo/ops.c +++ b/cameo/ops.c @@ -12,6 +12,7 @@ #include +#include #include "path.h" #include "shape.h" @@ -88,3 +89,48 @@ struct path *try_mill(struct path *path, double diam, double step) path->first->z, path->r_tool, diam/2, step); return NULL; } + + +/* + * This isn't a perfect solution for the traveling salesman problem, but it's + * easy to implement and usually produces results that don't look overly + * offensive. + */ + +struct path *optimize_paths(struct path *paths) +{ + struct path **walk, **best = NULL; + struct path *res = NULL, **anchor = &res; + struct path *curr; + struct point *p; + double best_d = 0, d; + + for (walk = &paths; *walk; walk = &(*walk)->next) { + p = (*walk)->first; + if (!p) + continue; + d = hypot(p->x, p->y); + if (!best || d < best_d) { + best = walk; + best_d = d; + } + } + while (best) { + curr = *best; + *anchor = *best; + anchor = &curr->next; + *best = curr->next; + best = NULL; + for (walk = &paths; *walk; walk = &(*walk)->next) { + p = (*walk)->first; + if (!p) + continue; + d = hypot(p->x-curr->last->x, p->y-curr->last->y); + if (!best || d < best_d) { + best = walk; + best_d = d; + } + } + } + return res; +} diff --git a/cameo/ops.h b/cameo/ops.h index ad20b1e..7e3dd16 100644 --- a/cameo/ops.h +++ b/cameo/ops.h @@ -20,5 +20,6 @@ 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); +struct path *optimize_paths(struct path *paths); #endif /* !OPS_H */