Index: Makefile =================================================================== --- Makefile (revision 11249) +++ Makefile (revision 11250) @@ -1,4 +1,4 @@ CFLAGS = -Wall -g -ansi -pedantic -parse.o: parse.c uhpgl_math.h libuhpgl.h +parse.o: parse.c uhpgl_math.h libuhpgl.h arc_iterate.h Index: arc_iterate.h =================================================================== --- arc_iterate.h (nonexistent) +++ arc_iterate.h (revision 11250) @@ -0,0 +1,109 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +/* Arc approximation loops for internal use - not intended to be + included by the library user */ + +#ifndef LIBUHPGL_ARC_ITERATE_H +#define LIBUHPGL_ARC_ITERATE_H + +/* Arc approximation loops */ + +typedef struct uhpgl_arc_it_s { + const uhpgl_arc_t *arc; + double step; /* stepping angle */ + double ang; + uhpgl_point_t pt; + int remain; +} uhpgl_arc_it_t; + +/* Do not call directly. Set up iterator for angle based steps. */ +static uhpgl_point_t *uhpgl_arc_it_first_ang(uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double step) +{ + if (step < 0) + step = -step; + else if (step == 0) + step = 5; + + if (arc->deltaa < 0) + step = -step; + + it->arc = arc; + it->step = step; + it->remain = floor(arc->deltaa / step)+2; + + it->pt = arc->startp; + it->ang = arc->starta; + return &it->pt; +} + +/* Do not call directly. Set up iterator for radius error based steps. */ +static uhpgl_point_t *uhpgl_arc_it_first_err(uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double err) +{ + double step; + + if (err > arc->r / 4) + return uhpgl_arc_it_first_ang(it, arc, 0); + + step = RAD2DEG(acos((arc->r - err) / arc->r) * 2); + if (step < 0) + step = -step; + + if (step < 0.1) + step = 0.1; + else if (step > 15) + step = 15; + + return uhpgl_arc_it_first_ang(it, arc, step); +} + +/* Start an iteration, return the first point */ +static uhpgl_point_t *uhpgl_arc_it_first(uhpgl_ctx_t *ctx, uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double resolution) +{ + if (ctx->state.ct) + return uhpgl_arc_it_first_ang(it, arc, resolution); + return uhpgl_arc_it_first_err(it, arc, resolution); +} + +/* Return the next point or NULL if there are no more points */ +static uhpgl_point_t *uhpgl_arc_it_next(uhpgl_arc_it_t *it) +{ + it->remain--; + switch(it->remain) { + case 0: /* beyond the endpoint */ + return NULL; + case 1: /* at the endpoint */ + /* special case: endpoint reached in the previous iterationm remaining correction path is 0 long */ + if ((it->pt.x == it->arc->endp.x) && (it->pt.y == it->arc->endp.y)) + return NULL; + it->pt = it->arc->endp; + return &it->pt; + default: + it->ang += it->step; + it->pt.x = ROUND((double)it->arc->center.x + it->arc->r * cos(DEG2RAD(it->ang))); + it->pt.y = ROUND((double)it->arc->center.y + it->arc->r * sin(DEG2RAD(it->ang))); + return &it->pt; + } + return NULL; +} + +#endif Index: parse.c =================================================================== --- parse.c (revision 11249) +++ parse.c (revision 11250) @@ -25,28 +25,10 @@ #include "uhpgl_math.h" #include "libuhpgl.h" #include "parse.h" +#include "arc_iterate.h" #define inst2num(s1, s2) ((((int)s1) << 8) | (int)s2) -/* Implementation idea borrowed from an old gcc */ -static double ROUND(double x) -{ - double t; - - if (x >= 0.0) { - t = ceil(x); - if (t - x > 0.5) - t -= 1.0; - return t; - } - - t = ceil(-x); - if ((t + x) > 0.5) - t -= 1.0; - return -t; -} - - typedef enum state_e { ST_IDLE, ST_INST, Index: uhpgl_math.h =================================================================== --- uhpgl_math.h (revision 11249) +++ uhpgl_math.h (revision 11250) @@ -33,4 +33,22 @@ #define DEG2RAD(d) ((d) * CONST_PI / 180.0) #define DDIST(dx, dy) sqrt((double)(dx)*(double)(dx) + (double)(dy)*(double)(dy)) +/* Implementation idea borrowed from an old gcc */ +static double ROUND(double x) +{ + double t; + + if (x >= 0.0) { + t = ceil(x); + if (t - x > 0.5) + t -= 1.0; + return t; + } + + t = ceil(-x); + if ((t + x) > 0.5) + t -= 1.0; + return -t; +} + #endif