mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-23 04:13:20 +02:00
0826d5b35e
- lang.y: allow an optional comma between the parameters of "drill" - README: explain the new syntax of "drill"
440 lines
6.6 KiB
Plaintext
440 lines
6.6 KiB
Plaintext
%{
|
|
/*
|
|
* lang.y - Toolpath adaptation language
|
|
*
|
|
* Written 2010-2011 by Werner Almesberger
|
|
* Copyright 2010-2011 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 "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;
|
|
enum {
|
|
OO_DOG = 1 << 0,
|
|
OO_INSIDE = 1 << 1,
|
|
} oopt;
|
|
};
|
|
|
|
|
|
%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_DRILL TOK_EMPTY
|
|
%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
|
|
|
|
%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 <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
|
|
{
|
|
tool_comp_paths(paths,
|
|
!!($2 & OO_DOG), !!($2 & OO_INSIDE));
|
|
}
|
|
| 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_MILL dimen dimen
|
|
{
|
|
struct path **walk;
|
|
|
|
remain = paths;
|
|
paths = NULL;
|
|
walk = &remain;
|
|
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:
|
|
{
|
|
$$ = 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:
|
|
| ','
|
|
;
|