mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-23 09:55:32 +02:00
489ca9c24d
Also removed the tool diameter argument. We use the diameter from the path, like "offset" does. In the long run, this convention probably doesn't make sense, though.
466 lines
6.9 KiB
Plaintext
466 lines
6.9 KiB
Plaintext
%{
|
|
/*
|
|
* lang.y - Toolpath adaptation language
|
|
*
|
|
* Written 2010-2012 by Werner Almesberger
|
|
* Copyright 2010-2012 by 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "path.h"
|
|
#include "ops.h"
|
|
#include "area.h"
|
|
#include "gnuplot.h"
|
|
#include "gerber.h"
|
|
#include "excellon.h"
|
|
|
|
#include "y.tab.h"
|
|
|
|
|
|
static double xo = 0, yo = 0, zo = 0; /* origin */
|
|
static double rot = 0;
|
|
static struct path *paths = NULL;
|
|
static struct path *remain = NULL;
|
|
|
|
|
|
#define MIL2MM(mil) ((mil)/1000*25.4)
|
|
|
|
|
|
static void add_paths(struct path *new)
|
|
{
|
|
struct path **anchor = &paths;
|
|
|
|
while (*anchor)
|
|
anchor = &(*anchor)->next;
|
|
*anchor = new;
|
|
}
|
|
|
|
|
|
static void translate(struct path *list, double x, double y, double z)
|
|
{
|
|
struct path *path;
|
|
struct point *p;
|
|
|
|
for (path = list; path; path = path->next)
|
|
for (p = path->first; p; p = p->next) {
|
|
p->x += x;
|
|
p->y += y;
|
|
p->z += z;
|
|
}
|
|
}
|
|
|
|
|
|
static void rotate(struct path *list, double angle)
|
|
{
|
|
double m[2][2], tmp;
|
|
struct point *p;
|
|
|
|
angle = angle/180.0*M_PI;
|
|
m[0][0] = cos(angle);
|
|
m[0][1] = -sin(angle);
|
|
m[1][0] = -m[0][1];
|
|
m[1][1] = m[0][0];
|
|
while (list) {
|
|
for (p = list->first; p; p = p->next) {
|
|
tmp = p->x*m[0][0]+p->y*m[0][1];
|
|
p->y = p->x*m[1][0]+p->y*m[1][1];
|
|
p->x = tmp;
|
|
}
|
|
list = list->next;
|
|
}
|
|
}
|
|
|
|
|
|
static double ref_pick_1(int ref, double a, double b)
|
|
{
|
|
switch (ref) {
|
|
case 0:
|
|
return a;
|
|
case 1:
|
|
return (a+b)/2;
|
|
case 2:
|
|
return b;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
|
|
static void ref_pick_xy(int ref, double xa, double ya, double xb, double yb,
|
|
double *x, double *y)
|
|
{
|
|
*x = ref_pick_1((ref-1) % 3, xa, xb);
|
|
*y = ref_pick_1((ref-1)/3, ya, yb);
|
|
}
|
|
|
|
|
|
static void bbox(const struct path *path,
|
|
double *xa, double *ya, double *xb, double *yb)
|
|
{
|
|
const struct point *p;
|
|
int first = 1;
|
|
|
|
*xa = *ya = *xb = *yb = 0;
|
|
|
|
while (path) {
|
|
for (p = path->first; p; p = p->next) {
|
|
if (first || p->x < *xa)
|
|
*xa = p->x;
|
|
if (first || p->x > *xb)
|
|
*xb = p->x;
|
|
if (first || p->y < *ya)
|
|
*ya = p->y;
|
|
if (first || p->y > *yb)
|
|
*yb = p->y;
|
|
first = 0;
|
|
}
|
|
path = path->next;
|
|
}
|
|
}
|
|
|
|
|
|
static void align(int ref, double x, double y)
|
|
{
|
|
double xa = 0, ya = 0, xb = 0, yb = 0;
|
|
double xr, yr, xd, yd;
|
|
int first = 1;
|
|
|
|
bbox(paths, &xa, &ya, &xb, &yb);
|
|
|
|
ref_pick_xy(ref, xa, ya, xb, yb, &xr, &yr);
|
|
xd = x-xr;
|
|
yd = y-yr;
|
|
|
|
translate(paths, xd, yd, 0);
|
|
xo += xd;
|
|
yo += yd;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
%}
|
|
|
|
|
|
%union {
|
|
double num;
|
|
char *str;
|
|
int flag;
|
|
enum {
|
|
OO_DOG = 1 << 0,
|
|
OO_INSIDE = 1 << 1,
|
|
} oopt;
|
|
};
|
|
|
|
|
|
%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_DRILL TOK_EMPTY TOK_AREA
|
|
%token TOK_MILL TOK_OFFSET TOK_OPTIMIZE TOK_REMAINDER TOK_RESET
|
|
%token TOK_ROTATE TOK_STATS TOK_TRANSLATE TOK_Z
|
|
%token TOK_APPEND TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE
|
|
%token TOK_DOG TOK_INSIDE TOK_ANY
|
|
|
|
%token <num> NUM_EXP_MIL NUM_EXP_MM NUM_IMP_MIL NUM_IMP_MM REF
|
|
%token <str> STRING
|
|
|
|
%type <str> opt_filename
|
|
%type <num> dimen number x_size y_size
|
|
%type <flag> opt_any
|
|
%type <oopt> offset_options offset_option
|
|
|
|
%%
|
|
|
|
all:
|
|
| command all
|
|
;
|
|
|
|
command:
|
|
TOK_ALIGN REF dimen dimen
|
|
{
|
|
align((int) $2, $3, $4);
|
|
}
|
|
| TOK_ALIGN REF dimen dimen dimen dimen
|
|
{
|
|
int ref = $2;
|
|
double x, y;
|
|
|
|
if ($3 > $5)
|
|
yyerror("left edge > right edge");
|
|
if ($4 > $6)
|
|
yyerror("bottom > top");
|
|
|
|
ref_pick_xy(ref, $3, $4, $5, $6, &x, &y);
|
|
align(ref, x, y);
|
|
}
|
|
| TOK_ARRAY x_size y_size number number
|
|
{
|
|
double x = $2*$4;
|
|
double y = $3*$5;
|
|
|
|
translate(paths, x, y, 0);
|
|
xo += x;
|
|
yo += y;
|
|
}
|
|
| TOK_CLEAR
|
|
{
|
|
clear_paths();
|
|
}
|
|
| TOK_RESET
|
|
{
|
|
xo = yo = rot = 0;
|
|
}
|
|
| TOK_OFFSET offset_options
|
|
{
|
|
struct path *new;
|
|
|
|
new = tool_comp_paths(paths,
|
|
!!($2 & OO_DOG), !!($2 & OO_INSIDE));
|
|
clear_paths();
|
|
paths = new;
|
|
}
|
|
| TOK_OPTIMIZE
|
|
{
|
|
paths = optimize_paths(paths);
|
|
}
|
|
| TOK_ROTATE number
|
|
{
|
|
rotate(paths, $2);
|
|
rot += $2;
|
|
}
|
|
| TOK_STATS
|
|
{
|
|
path_stats(paths);
|
|
}
|
|
| TOK_TRANSLATE dimen dimen
|
|
{
|
|
translate(paths, $2, $3, 0);
|
|
xo += $2;
|
|
yo += $3;
|
|
}
|
|
| TOK_Z dimen
|
|
{
|
|
zo += $2;
|
|
}
|
|
| TOK_Z dimen dimen
|
|
{
|
|
zo += $3-$2;
|
|
}
|
|
| TOK_GERBER dimen opt_filename
|
|
{
|
|
struct path *new;
|
|
|
|
new = gerber_read($3, $2/2);
|
|
rotate(new, rot);
|
|
translate(new, xo, yo, 0);
|
|
add_paths(new);
|
|
}
|
|
| TOK_GNUPLOT dimen opt_filename
|
|
{
|
|
struct path *new;
|
|
|
|
new = gnuplot_read($3, $2/2);
|
|
rotate(new, rot);
|
|
translate(new, xo, yo, 0);
|
|
add_paths(new);
|
|
}
|
|
| TOK_EXCELLON opt_filename
|
|
{
|
|
struct path *new;
|
|
|
|
new = excellon_read($2);
|
|
rotate(new, rot);
|
|
translate(new, xo, yo, 0);
|
|
add_paths(new);
|
|
}
|
|
| TOK_WRITE opt_filename
|
|
{
|
|
translate(paths, 0, 0, zo);
|
|
gnuplot_write($2, paths);
|
|
translate(paths, 0, 0, -zo);
|
|
}
|
|
| TOK_APPEND opt_filename
|
|
{
|
|
translate(paths, 0, 0, zo);
|
|
gnuplot_append($2, paths);
|
|
translate(paths, 0, 0, -zo);
|
|
}
|
|
| TOK_DRILL dimen opt_comma dimen
|
|
{
|
|
struct path **walk;
|
|
|
|
remain = paths;
|
|
paths = NULL;
|
|
walk = &remain;
|
|
while (*walk)
|
|
walk =
|
|
classify(walk, try_drill(*walk, $2, $4));
|
|
}
|
|
| TOK_AREA dimen
|
|
{
|
|
struct path *tmp;
|
|
|
|
tmp = area(paths, $2);
|
|
clear_paths();
|
|
paths = tmp;
|
|
}
|
|
| TOK_MILL opt_any dimen dimen
|
|
{
|
|
struct path **walk;
|
|
|
|
remain = paths;
|
|
paths = NULL;
|
|
walk = &remain;
|
|
while (*walk)
|
|
walk = classify(walk,
|
|
try_mill(*walk, $3, $4, $2));
|
|
}
|
|
| TOK_REMAINDER
|
|
{
|
|
clear_paths();
|
|
paths = remain;
|
|
remain = NULL;
|
|
}
|
|
| TOK_EMPTY
|
|
{
|
|
if (paths)
|
|
yyerror("path list is not empty");
|
|
}
|
|
;
|
|
|
|
opt_filename:
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| STRING
|
|
{
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
dimen:
|
|
NUM_EXP_MM
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| NUM_IMP_MM
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| NUM_EXP_MIL
|
|
{
|
|
$$ = MIL2MM($1);
|
|
}
|
|
| NUM_IMP_MIL
|
|
{
|
|
$$ = MIL2MM($1);
|
|
}
|
|
;
|
|
|
|
x_size:
|
|
dimen
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| '+' dimen
|
|
{
|
|
double xa, ya, xb, yb;
|
|
|
|
bbox(paths, &xa, &ya, &xb, &yb);
|
|
$$ = xb-xa+$2;
|
|
}
|
|
;
|
|
|
|
y_size:
|
|
dimen
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| '+' dimen
|
|
{
|
|
double xa, ya, xb, yb;
|
|
|
|
bbox(paths, &xa, &ya, &xb, &yb);
|
|
$$ = yb-ya+$2;
|
|
}
|
|
;
|
|
|
|
number:
|
|
NUM_IMP_MIL
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| NUM_IMP_MM
|
|
{
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
offset_options:
|
|
{
|
|
$$ = 0;
|
|
}
|
|
| offset_option offset_options
|
|
{
|
|
$$ = $1 | $2;
|
|
|
|
}
|
|
;
|
|
|
|
offset_option:
|
|
TOK_DOG
|
|
{
|
|
$$ = OO_DOG;
|
|
}
|
|
| TOK_INSIDE
|
|
{
|
|
$$ = OO_INSIDE;
|
|
}
|
|
;
|
|
|
|
opt_comma:
|
|
| ','
|
|
;
|
|
|
|
opt_any:
|
|
{
|
|
$$ = 0;
|
|
}
|
|
| TOK_ANY
|
|
{
|
|
$$ = 1;
|
|
}
|
|
;
|