pcb 4.1.1
An interactive printed circuit board layout editor.

trace.c

Go to the documentation of this file.
00001 
00021 /* trace.c 147 2007-04-09 00:44:09Z selinger */
00022 
00023 #include <stdio.h>
00024 #include <math.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 
00028 #include "global.h"
00029 #include "potracelib.h"
00030 #include "curve.h"
00031 #include "lists.h"
00032 #include "auxiliary.h"
00033 #include "trace.h"
00034 #include "pcb-printf.h"
00035 //#include "progress.h"
00036 
00040 #define INFTY 10000000
00041 
00044 #define COS179 -0.999847695156
00045 
00046 /* ---------------------------------------------------------------------- */
00047 #define SAFE_MALLOC(var, n, typ) \
00048   if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
00049 
00050 /* ---------------------------------------------------------------------- */
00051 /* auxiliary functions */
00052 
00058 static inline point_t
00059 dorth_infty (dpoint_t p0, dpoint_t p2)
00060 {
00061   point_t r;
00062 
00063   r.y = sign (p2.x - p0.x);
00064   r.x = -sign (p2.y - p0.y);
00065 
00066   return r;
00067 }
00068 
00072 static inline double
00073 dpara (dpoint_t p0, dpoint_t p1, dpoint_t p2)
00074 {
00075   double x1, y1, x2, y2;
00076 
00077   x1 = p1.x - p0.x;
00078   y1 = p1.y - p0.y;
00079   x2 = p2.x - p0.x;
00080   y2 = p2.y - p0.y;
00081 
00082   return x1 * y2 - x2 * y1;
00083 }
00084 
00090 static inline double
00091 ddenom (dpoint_t p0, dpoint_t p2)
00092 {
00093   point_t r = dorth_infty (p0, p2);
00094 
00095   return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y);
00096 }
00097 
00101 static inline int
00102 cyclic (int a, int b, int c)
00103 {
00104   if (a <= c)
00105     {
00106       return (a <= b && b < c);
00107     }
00108   else
00109     {
00110       return (a <= b || b < c);
00111     }
00112 }
00113 
00119 static void
00120 pointslope (privpath_t * pp, int i, int j, dpoint_t * ctr, dpoint_t * dir)
00121 {
00122   /* assume i<j */
00123 
00124   int n = pp->len;
00125   sums_t *sums = pp->sums;
00126 
00127   double x, y, x2, xy, y2;
00128   double k;
00129   double a, b, c, lambda2, l;
00130   int r = 0;                    /* rotations from i to j */
00131 
00132   while (j >= n)
00133     {
00134       j -= n;
00135       r += 1;
00136     }
00137   while (i >= n)
00138     {
00139       i -= n;
00140       r -= 1;
00141     }
00142   while (j < 0)
00143     {
00144       j += n;
00145       r -= 1;
00146     }
00147   while (i < 0)
00148     {
00149       i += n;
00150       r += 1;
00151     }
00152 
00153   x = sums[j + 1].x - sums[i].x + r * sums[n].x;
00154   y = sums[j + 1].y - sums[i].y + r * sums[n].y;
00155   x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2;
00156   xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy;
00157   y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2;
00158   k = j + 1 - i + r * n;
00159 
00160   ctr->x = x / k;
00161   ctr->y = y / k;
00162 
00163   a = (x2 - (double) x * x / k) / k;
00164   b = (xy - (double) x * y / k) / k;
00165   c = (y2 - (double) y * y / k) / k;
00166 
00167   lambda2 = (a + c + hypot (a - c, 2 * b)) / 2; /* larger e.value */
00168 
00169   /* now find e.vector for lambda2 */
00170   a -= lambda2;
00171   c -= lambda2;
00172 
00173   if (fabs (a) >= fabs (c))
00174     {
00175       l = hypot (a, b);
00176       if (l != 0)
00177         {
00178           dir->x = -b / l;
00179           dir->y = a / l;
00180         }
00181     }
00182   else
00183     {
00184       l = hypot (c, b);
00185       if (l != 0)
00186         {
00187           dir->x = -c / l;
00188           dir->y = b / l;
00189         }
00190     }
00191   if (l == 0)
00192     {
00193       dir->x = dir->y = 0;      /* sometimes this can happen when k=4:
00194                                    the two eigenvalues coincide */
00195     }
00196 }
00197 
00205 typedef double quadform_t[3][3];
00206 
00210 static inline double
00211 quadform (quadform_t Q, dpoint_t w)
00212 {
00213   double v[3];
00214   int i, j;
00215   double sum;
00216 
00217   v[0] = w.x;
00218   v[1] = w.y;
00219   v[2] = 1;
00220   sum = 0.0;
00221 
00222   for (i = 0; i < 3; i++)
00223     {
00224       for (j = 0; j < 3; j++)
00225         {
00226           sum += v[i] * Q[i][j] * v[j];
00227         }
00228     }
00229   return sum;
00230 }
00231 
00235 static inline int
00236 xprod (point_t p1, point_t p2)
00237 {
00238   return p1.x * p2.y - p1.y * p2.x;
00239 }
00240 
00244 static inline double
00245 cprod (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
00246 {
00247   double x1, y1, x2, y2;
00248 
00249   x1 = p1.x - p0.x;
00250   y1 = p1.y - p0.y;
00251   x2 = p3.x - p2.x;
00252   y2 = p3.y - p2.y;
00253 
00254   return x1 * y2 - x2 * y1;
00255 }
00256 
00260 static inline double
00261 iprod (dpoint_t p0, dpoint_t p1, dpoint_t p2)
00262 {
00263   double x1, y1, x2, y2;
00264 
00265   x1 = p1.x - p0.x;
00266   y1 = p1.y - p0.y;
00267   x2 = p2.x - p0.x;
00268   y2 = p2.y - p0.y;
00269 
00270   return x1 * x2 + y1 * y2;
00271 }
00272 
00276 static inline double
00277 iprod1 (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
00278 {
00279   double x1, y1, x2, y2;
00280 
00281   x1 = p1.x - p0.x;
00282   y1 = p1.y - p0.y;
00283   x2 = p3.x - p2.x;
00284   y2 = p3.y - p2.y;
00285 
00286   return x1 * x2 + y1 * y2;
00287 }
00288 
00292 static inline double
00293 ddist (dpoint_t p, dpoint_t q)
00294 {
00295   return hypot (p.x - q.x, p.y - q.y);
00296 }
00297 
00301 static inline dpoint_t
00302 bezier (double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3)
00303 {
00304   double s = 1 - t;
00305   dpoint_t res;
00306 
00307   /* Note: a good optimizing compiler (such as gcc-3) reduces the
00308      following to 16 multiplications, using common subexpression
00309      elimination. */
00310 
00311   res.x =
00312     s * s * s * p0.x + 3 * (s * s * t) * p1.x + 3 * (t * t * s) * p2.x +
00313     t * t * t * p3.x;
00314   res.y =
00315     s * s * s * p0.y + 3 * (s * s * t) * p1.y + 3 * (t * t * s) * p2.y +
00316     t * t * t * p3.y;
00317 
00318   return res;
00319 }
00320 
00327 static double
00328 tangent (dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0,
00329          dpoint_t q1)
00330 {
00331   double A, B, C;               /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
00332   double a, b, c;               /* a t^2 + b t + c = 0 */
00333   double d, s, r1, r2;
00334 
00335   A = cprod (p0, p1, q0, q1);
00336   B = cprod (p1, p2, q0, q1);
00337   C = cprod (p2, p3, q0, q1);
00338 
00339   a = A - 2 * B + C;
00340   b = -2 * A + 2 * B;
00341   c = A;
00342 
00343   d = b * b - 4 * a * c;
00344 
00345   if (a == 0 || d < 0)
00346     {
00347       return -1.0;
00348     }
00349 
00350   s = sqrt (d);
00351 
00352   r1 = (-b + s) / (2 * a);
00353   r2 = (-b - s) / (2 * a);
00354 
00355   if (r1 >= 0 && r1 <= 1)
00356     {
00357       return r1;
00358     }
00359   else if (r2 >= 0 && r2 <= 1)
00360     {
00361       return r2;
00362     }
00363   else
00364     {
00365       return -1.0;
00366     }
00367 }
00368 
00375 static int
00376 calc_sums (privpath_t * pp)
00377 {
00378   int i, x, y;
00379   int n = pp->len;
00380 
00381   SAFE_MALLOC (pp->sums, pp->len + 1, sums_t);
00382 
00383   /* origin */
00384   pp->x0 = pp->pt[0].x;
00385   pp->y0 = pp->pt[0].y;
00386 
00387   /* preparatory computation for later fast summing */
00388   pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x =
00389     pp->sums[0].y = 0;
00390   for (i = 0; i < n; i++)
00391     {
00392       x = pp->pt[i].x - pp->x0;
00393       y = pp->pt[i].y - pp->y0;
00394       pp->sums[i + 1].x = pp->sums[i].x + x;
00395       pp->sums[i + 1].y = pp->sums[i].y + y;
00396       pp->sums[i + 1].x2 = pp->sums[i].x2 + x * x;
00397       pp->sums[i + 1].xy = pp->sums[i].xy + x * y;
00398       pp->sums[i + 1].y2 = pp->sums[i].y2 + y * y;
00399     }
00400   return 0;
00401 
00402 malloc_error:
00403   return 1;
00404 }
00405 
00438 static int
00439 calc_lon (privpath_t * pp)
00440 {
00441   point_t *pt = pp->pt;
00442   int n = pp->len;
00443   int i, j, k, k1;
00444   int ct[4], dir;
00445   point_t constraint[2];
00446   point_t cur;
00447   point_t off;
00448   int *pivk = NULL;             /* pivk[n] */
00449   int *nc = NULL;               /* nc[n]: next corner */
00450   point_t dk;                   /* direction of k-k1 */
00451   int a, b, c, d;
00452 
00453   SAFE_MALLOC (pivk, n, int);
00454   SAFE_MALLOC (nc, n, int);
00455 
00456   /* initialize the nc data structure. Point from each point to the
00457      furthest future point to which it is connected by a vertical or
00458      horizontal segment. We take advantage of the fact that there is
00459      always a direction change at 0 (due to the path decomposition
00460      algorithm). But even if this were not so, there is no harm, as
00461      in practice, correctness does not depend on the word "furthest"
00462      above.  */
00463   k = 0;
00464   for (i = n - 1; i >= 0; i--)
00465     {
00466       if (pt[i].x != pt[k].x && pt[i].y != pt[k].y)
00467         {
00468           k = i + 1;            /* necessarily i<n-1 in this case */
00469         }
00470       nc[i] = k;
00471     }
00472 
00473   SAFE_MALLOC (pp->lon, n, int);
00474 
00475   /* determine pivot points: for each i, let pivk[i] be the furthest k
00476      such that all j with i<j<k lie on a line connecting i,k. */
00477 
00478   for (i = n - 1; i >= 0; i--)
00479     {
00480       ct[0] = ct[1] = ct[2] = ct[3] = 0;
00481 
00482       /* keep track of "directions" that have occurred */
00483       dir =
00484         (3 + 3 * (pt[mod (i + 1, n)].x - pt[i].x) +
00485          (pt[mod (i + 1, n)].y - pt[i].y)) / 2;
00486       ct[dir]++;
00487 
00488       constraint[0].x = 0;
00489       constraint[0].y = 0;
00490       constraint[1].x = 0;
00491       constraint[1].y = 0;
00492 
00493       /* find the next k such that no straight line from i to k */
00494       k = nc[i];
00495       k1 = i;
00496       while (1)
00497         {
00498 
00499           dir =
00500             (3 + 3 * sign (pt[k].x - pt[k1].x) +
00501              sign (pt[k].y - pt[k1].y)) / 2;
00502           ct[dir]++;
00503 
00504           /* if all four "directions" have occurred, cut this path */
00505           if (ct[0] && ct[1] && ct[2] && ct[3])
00506             {
00507               pivk[i] = k1;
00508               goto foundk;
00509             }
00510 
00511           cur.x = pt[k].x - pt[i].x;
00512           cur.y = pt[k].y - pt[i].y;
00513 
00514           /* see if current constraint is violated */
00515           if (xprod (constraint[0], cur) < 0
00516               || xprod (constraint[1], cur) > 0)
00517             {
00518               goto constraint_viol;
00519             }
00520 
00521           /* else, update constraint */
00522           if (abs (cur.x) <= 1 && abs (cur.y) <= 1)
00523             {
00524               /* no constraint */
00525             }
00526           else
00527             {
00528               off.x =
00529                 cur.x + ((cur.y >= 0 && (cur.y > 0 || cur.x < 0)) ? 1 : -1);
00530               off.y =
00531                 cur.y + ((cur.x <= 0 && (cur.x < 0 || cur.y < 0)) ? 1 : -1);
00532               if (xprod (constraint[0], off) >= 0)
00533                 {
00534                   constraint[0] = off;
00535                 }
00536               off.x =
00537                 cur.x + ((cur.y <= 0 && (cur.y < 0 || cur.x < 0)) ? 1 : -1);
00538               off.y =
00539                 cur.y + ((cur.x >= 0 && (cur.x > 0 || cur.y < 0)) ? 1 : -1);
00540               if (xprod (constraint[1], off) <= 0)
00541                 {
00542                   constraint[1] = off;
00543                 }
00544             }
00545           k1 = k;
00546           k = nc[k1];
00547           if (!cyclic (k, i, k1))
00548             {
00549               break;
00550             }
00551         }
00552     constraint_viol:
00553       /* k1 was the last "corner" satisfying the current constraint, and
00554          k is the first one violating it. We now need to find the last
00555          point along k1..k which satisfied the constraint. */
00556       dk.x = sign (pt[k].x - pt[k1].x);
00557       dk.y = sign (pt[k].y - pt[k1].y);
00558       cur.x = pt[k1].x - pt[i].x;
00559       cur.y = pt[k1].y - pt[i].y;
00560       /* find largest integer j such that xprod(constraint[0], cur+j*dk)
00561          >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
00562          of xprod. */
00563       a = xprod (constraint[0], cur);
00564       b = xprod (constraint[0], dk);
00565       c = xprod (constraint[1], cur);
00566       d = xprod (constraint[1], dk);
00567       /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
00568          can be solved with integer arithmetic. */
00569       j = INFTY;
00570       if (b < 0)
00571         {
00572           j = floordiv (a, -b);
00573         }
00574       if (d > 0)
00575         {
00576           j = min (j, floordiv (-c, d));
00577         }
00578       pivk[i] = mod (k1 + j, n);
00579     foundk:
00580       ;
00581     }                           /* for i */
00582 
00583   /* clean up: for each i, let lon[i] be the largest k such that for
00584      all i' with i<=i'<k, i'<k<=pivk[i']. */
00585 
00586   j = pivk[n - 1];
00587   pp->lon[n - 1] = j;
00588   for (i = n - 2; i >= 0; i--)
00589     {
00590       if (cyclic (i + 1, pivk[i], j))
00591         {
00592           j = pivk[i];
00593         }
00594       pp->lon[i] = j;
00595     }
00596 
00597   for (i = n - 1; cyclic (mod (i + 1, n), j, pp->lon[i]); i--)
00598     {
00599       pp->lon[i] = j;
00600     }
00601 
00602   free (pivk);
00603   free (nc);
00604   return 0;
00605 
00606 malloc_error:
00607   free (pivk);
00608   free (nc);
00609   return 1;
00610 }
00611 
00612 
00619 static double
00620 penalty3 (privpath_t * pp, int i, int j)
00621 {
00622   int n = pp->len;
00623   point_t *pt = pp->pt;
00624   sums_t *sums = pp->sums;
00625 
00626   /* assume 0<=i<j<=n  */
00627   double x, y, x2, xy, y2;
00628   double k;
00629   double a, b, c, s;
00630   double px, py, ex, ey;
00631 
00632   int r = 0;                    /* rotations from i to j */
00633 
00634   if (j >= n)
00635     {
00636       j -= n;
00637       r += 1;
00638     }
00639 
00640   x = sums[j + 1].x - sums[i].x + r * sums[n].x;
00641   y = sums[j + 1].y - sums[i].y + r * sums[n].y;
00642   x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2;
00643   xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy;
00644   y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2;
00645   k = j + 1 - i + r * n;
00646 
00647   px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
00648   py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
00649   ey = (pt[j].x - pt[i].x);
00650   ex = -(pt[j].y - pt[i].y);
00651 
00652   a = ((x2 - 2 * x * px) / k + px * px);
00653   b = ((xy - x * py - y * px) / k + px * py);
00654   c = ((y2 - 2 * y * py) / k + py * py);
00655 
00656   s = ex * ex * a + 2 * ex * ey * b + ey * ey * c;
00657 
00658   return sqrt (s);
00659 }
00660 
00671 static int
00672 bestpolygon (privpath_t * pp)
00673 {
00674   int i, j, m, k;
00675   int n = pp->len;
00676   double *pen = NULL;           /* pen[n+1]: penalty vector */
00677   int *prev = NULL;             /* prev[n+1]: best path pointer vector */
00678   int *clip0 = NULL;            /* clip0[n]: longest segment pointer, non-cyclic */
00679   int *clip1 = NULL;            /* clip1[n+1]: backwards segment pointer, non-cyclic */
00680   int *seg0 = NULL;             /* seg0[m+1]: forward segment bounds, m<=n */
00681   int *seg1 = NULL;             /* seg1[m+1]: backward segment bounds, m<=n */
00682   double thispen;
00683   double best;
00684   int c;
00685 
00686   SAFE_MALLOC (pen, n + 1, double);
00687   SAFE_MALLOC (prev, n + 1, int);
00688   SAFE_MALLOC (clip0, n, int);
00689   SAFE_MALLOC (clip1, n + 1, int);
00690   SAFE_MALLOC (seg0, n + 1, int);
00691   SAFE_MALLOC (seg1, n + 1, int);
00692 
00693   /* calculate clipped paths */
00694   for (i = 0; i < n; i++)
00695     {
00696       c = mod (pp->lon[mod (i - 1, n)] - 1, n);
00697       if (c == i)
00698         {
00699           c = mod (i + 1, n);
00700         }
00701       if (c < i)
00702         {
00703           clip0[i] = n;
00704         }
00705       else
00706         {
00707           clip0[i] = c;
00708         }
00709     }
00710 
00711   /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
00712      clip1[j] <= i, for i,j=0..n. */
00713   j = 1;
00714   for (i = 0; i < n; i++)
00715     {
00716       while (j <= clip0[i])
00717         {
00718           clip1[j] = i;
00719           j++;
00720         }
00721     }
00722 
00723   /* calculate seg0[j] = longest path from 0 with j segments */
00724   i = 0;
00725   for (j = 0; i < n; j++)
00726     {
00727       seg0[j] = i;
00728       i = clip0[i];
00729     }
00730   seg0[j] = n;
00731   m = j;
00732 
00733   /* calculate seg1[j] = longest path to n with m-j segments */
00734   i = n;
00735   for (j = m; j > 0; j--)
00736     {
00737       seg1[j] = i;
00738       i = clip1[i];
00739     }
00740   seg1[0] = 0;
00741 
00742   /* now find the shortest path with m segments, based on penalty3 */
00743   /* note: the outer 2 loops jointly have at most n interations, thus
00744      the worst-case behavior here is quadratic. In practice, it is
00745      close to linear since the inner loop tends to be short. */
00746   pen[0] = 0;
00747   for (j = 1; j <= m; j++)
00748     {
00749       for (i = seg1[j]; i <= seg0[j]; i++)
00750         {
00751           best = -1;
00752           for (k = seg0[j - 1]; k >= clip1[i]; k--)
00753             {
00754               thispen = penalty3 (pp, k, i) + pen[k];
00755               if (best < 0 || thispen < best)
00756                 {
00757                   prev[i] = k;
00758                   best = thispen;
00759                 }
00760             }
00761           pen[i] = best;
00762         }
00763     }
00764 
00765   pp->m = m;
00766   SAFE_MALLOC (pp->po, m, int);
00767 
00768   /* read off shortest path */
00769   for (i = n, j = m - 1; i > 0; j--)
00770     {
00771       i = prev[i];
00772       pp->po[j] = i;
00773     }
00774 
00775   free (pen);
00776   free (prev);
00777   free (clip0);
00778   free (clip1);
00779   free (seg0);
00780   free (seg1);
00781   return 0;
00782 
00783 malloc_error:
00784   free (pen);
00785   free (prev);
00786   free (clip0);
00787   free (clip1);
00788   free (seg0);
00789   free (seg1);
00790   return 1;
00791 }
00792 
00802 static int
00803 adjust_vertices (privpath_t * pp)
00804 {
00805   int m = pp->m;
00806   int *po = pp->po;
00807   int n = pp->len;
00808   point_t *pt = pp->pt;
00809   int x0 = pp->x0;
00810   int y0 = pp->y0;
00811 
00812   dpoint_t *ctr = NULL;         /* ctr[m] */
00813   dpoint_t *dir = NULL;         /* dir[m] */
00814   quadform_t *q = NULL;         /* q[m] */
00815   double v[3];
00816   double d;
00817   int i, j, k, l;
00818   dpoint_t s;
00819   int r;
00820 
00821   SAFE_MALLOC (ctr, m, dpoint_t);
00822   SAFE_MALLOC (dir, m, dpoint_t);
00823   SAFE_MALLOC (q, m, quadform_t);
00824 
00825   r = privcurve_init (&pp->curve, m);
00826   if (r)
00827     {
00828       goto malloc_error;
00829     }
00830 
00831   /* calculate "optimal" point-slope representation for each line
00832      segment */
00833   for (i = 0; i < m; i++)
00834     {
00835       j = po[mod (i + 1, m)];
00836       j = mod (j - po[i], n) + po[i];
00837       pointslope (pp, po[i], j, &ctr[i], &dir[i]);
00838     }
00839 
00840   /* represent each line segment as a singular quadratic form; the
00841      distance of a point (x,y) from the line segment will be
00842      (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
00843   for (i = 0; i < m; i++)
00844     {
00845       d = sq (dir[i].x) + sq (dir[i].y);
00846       if (d == 0.0)
00847         {
00848           for (j = 0; j < 3; j++)
00849             {
00850               for (k = 0; k < 3; k++)
00851                 {
00852                   q[i][j][k] = 0;
00853                 }
00854             }
00855         }
00856       else
00857         {
00858           v[0] = dir[i].y;
00859           v[1] = -dir[i].x;
00860           v[2] = -v[1] * ctr[i].y - v[0] * ctr[i].x;
00861           for (l = 0; l < 3; l++)
00862             {
00863               for (k = 0; k < 3; k++)
00864                 {
00865                   q[i][l][k] = v[l] * v[k] / d;
00866                 }
00867             }
00868         }
00869     }
00870 
00871   /* now calculate the "intersections" of consecutive segments.
00872      Instead of using the actual intersection, we find the point
00873      within a given unit square which minimizes the square distance to
00874      the two lines. */
00875   for (i = 0; i < m; i++)
00876     {
00877       quadform_t Q;
00878       dpoint_t w;
00879       double dx, dy;
00880       double det;
00881       double min, cand;         /* minimum and candidate for minimum of quad. form */
00882       double xmin, ymin;        /* coordinates of minimum */
00883       int z;
00884 
00885       /* let s be the vertex, in coordinates relative to x0/y0 */
00886       s.x = pt[po[i]].x - x0;
00887       s.y = pt[po[i]].y - y0;
00888 
00889       /* intersect segments i-1 and i */
00890 
00891       j = mod (i - 1, m);
00892 
00893       /* add quadratic forms */
00894       for (l = 0; l < 3; l++)
00895         {
00896           for (k = 0; k < 3; k++)
00897             {
00898               Q[l][k] = q[j][l][k] + q[i][l][k];
00899             }
00900         }
00901 
00902       while (1)
00903         {
00904           /* minimize the quadratic form Q on the unit square */
00905           /* find intersection */
00906 
00907 #ifdef HAVE_GCC_LOOP_BUG
00908           /* work around gcc bug #12243 */
00909           free (NULL);
00910 #endif
00911 
00912           det = Q[0][0] * Q[1][1] - Q[0][1] * Q[1][0];
00913           if (det != 0.0)
00914             {
00915               w.x = (-Q[0][2] * Q[1][1] + Q[1][2] * Q[0][1]) / det;
00916               w.y = (Q[0][2] * Q[1][0] - Q[1][2] * Q[0][0]) / det;
00917               break;
00918             }
00919 
00920           /* matrix is singular - lines are parallel. Add another,
00921              orthogonal axis, through the center of the unit square */
00922           if (Q[0][0] > Q[1][1])
00923             {
00924               v[0] = -Q[0][1];
00925               v[1] = Q[0][0];
00926             }
00927           else if (Q[1][1])
00928             {
00929               v[0] = -Q[1][1];
00930               v[1] = Q[1][0];
00931             }
00932           else
00933             {
00934               v[0] = 1;
00935               v[1] = 0;
00936             }
00937           d = sq (v[0]) + sq (v[1]);
00938           v[2] = -v[1] * s.y - v[0] * s.x;
00939           for (l = 0; l < 3; l++)
00940             {
00941               for (k = 0; k < 3; k++)
00942                 {
00943                   Q[l][k] += v[l] * v[k] / d;
00944                 }
00945             }
00946         }
00947       dx = fabs (w.x - s.x);
00948       dy = fabs (w.y - s.y);
00949       if (dx <= .5 && dy <= .5)
00950         {
00951           pp->curve.vertex[i].x = w.x + x0;
00952           pp->curve.vertex[i].y = w.y + y0;
00953           continue;
00954         }
00955 
00956       /* the minimum was not in the unit square; now minimize quadratic
00957          on boundary of square */
00958       min = quadform (Q, s);
00959       xmin = s.x;
00960       ymin = s.y;
00961 
00962       if (Q[0][0] == 0.0)
00963         {
00964           goto fixx;
00965         }
00966       for (z = 0; z < 2; z++)
00967         {                       /* value of the y-coordinate */
00968           w.y = s.y - 0.5 + z;
00969           w.x = -(Q[0][1] * w.y + Q[0][2]) / Q[0][0];
00970           dx = fabs (w.x - s.x);
00971           cand = quadform (Q, w);
00972           if (dx <= .5 && cand < min)
00973             {
00974               min = cand;
00975               xmin = w.x;
00976               ymin = w.y;
00977             }
00978         }
00979     fixx:
00980       if (Q[1][1] == 0.0)
00981         {
00982           goto corners;
00983         }
00984       for (z = 0; z < 2; z++)
00985         {                       /* value of the x-coordinate */
00986           w.x = s.x - 0.5 + z;
00987           w.y = -(Q[1][0] * w.x + Q[1][2]) / Q[1][1];
00988           dy = fabs (w.y - s.y);
00989           cand = quadform (Q, w);
00990           if (dy <= .5 && cand < min)
00991             {
00992               min = cand;
00993               xmin = w.x;
00994               ymin = w.y;
00995             }
00996         }
00997     corners:
00998       /* check four corners */
00999       for (l = 0; l < 2; l++)
01000         {
01001           for (k = 0; k < 2; k++)
01002             {
01003               w.x = s.x - 0.5 + l;
01004               w.y = s.y - 0.5 + k;
01005               cand = quadform (Q, w);
01006               if (cand < min)
01007                 {
01008                   min = cand;
01009                   xmin = w.x;
01010                   ymin = w.y;
01011                 }
01012             }
01013         }
01014 
01015       pp->curve.vertex[i].x = xmin + x0;
01016       pp->curve.vertex[i].y = ymin + y0;
01017       continue;
01018     }
01019 
01020   free (ctr);
01021   free (dir);
01022   free (q);
01023   return 0;
01024 
01025 malloc_error:
01026   free (ctr);
01027   free (dir);
01028   free (q);
01029   return 1;
01030 }
01031 
01037 static int
01038 ATTRIBUTE_UNUSED smooth (privcurve_t * curve, int sign, double alphamax)
01039 {
01040   int m = curve->n;
01041 
01042   int i, j, k;
01043   double dd, denom, alpha;
01044   dpoint_t p2, p3, p4;
01045 
01046   if (sign == '-')
01047     {
01048       /* reverse orientation of negative paths */
01049       for (i = 0, j = m - 1; i < j; i++, j--)
01050         {
01051           dpoint_t tmp;
01052           tmp = curve->vertex[i];
01053           curve->vertex[i] = curve->vertex[j];
01054           curve->vertex[j] = tmp;
01055         }
01056     }
01057 
01058   /* examine each vertex and find its best fit */
01059   for (i = 0; i < m; i++)
01060     {
01061       j = mod (i + 1, m);
01062       k = mod (i + 2, m);
01063       p4 = interval (1 / 2.0, curve->vertex[k], curve->vertex[j]);
01064 
01065       denom = ddenom (curve->vertex[i], curve->vertex[k]);
01066       if (denom != 0.0)
01067         {
01068           dd =
01069             dpara (curve->vertex[i], curve->vertex[j],
01070                    curve->vertex[k]) / denom;
01071           dd = fabs (dd);
01072           alpha = dd > 1 ? (1 - 1.0 / dd) : 0;
01073           alpha = alpha / 0.75;
01074         }
01075       else
01076         {
01077           alpha = 4 / 3.0;
01078         }
01079       curve->alpha0[j] = alpha; /* remember "original" value of alpha */
01080 
01081       if (alpha > alphamax)
01082         {                       /* pointed corner */
01083           curve->tag[j] = POTRACE_CORNER;
01084           curve->c[j][1] = curve->vertex[j];
01085           curve->c[j][2] = p4;
01086         }
01087       else
01088         {
01089           if (alpha < 0.55)
01090             {
01091               alpha = 0.55;
01092             }
01093           else if (alpha > 1)
01094             {
01095               alpha = 1;
01096             }
01097           p2 = interval (.5 + .5 * alpha, curve->vertex[i], curve->vertex[j]);
01098           p3 = interval (.5 + .5 * alpha, curve->vertex[k], curve->vertex[j]);
01099           curve->tag[j] = POTRACE_CURVETO;
01100           curve->c[j][0] = p2;
01101           curve->c[j][1] = p3;
01102           curve->c[j][2] = p4;
01103         }
01104       curve->alpha[j] = alpha;  /* store the "cropped" value of alpha */
01105       curve->beta[j] = 0.5;
01106     }
01107   curve->alphacurve = 1;
01108 
01109   return 0;
01110 }
01111 
01112 /* ---------------------------------------------------------------------- */
01113 /* Stage 5: Curve optimization (Sec. 2.4) */
01114 
01118 struct opti_s
01119 {
01120   double pen; 
01121   dpoint_t c[2]; 
01122   double t; 
01123   double s; 
01124   double alpha; 
01125 };
01126 typedef struct opti_s opti_t;
01127 
01136 static int
01137 opti_penalty (privpath_t * pp, int i, int j, opti_t * res,
01138               double opttolerance, int *convc, double *areac)
01139 {
01140   int m = pp->curve.n;
01141   int k, k1, k2, conv, i1;
01142   double area, alpha, d, d1, d2;
01143   dpoint_t p0, p1, p2, p3, pt;
01144   double A, R, A1, A2, A3, A4;
01145   double s, t;
01146 
01147   /* check convexity, corner-freeness, and maximum bend < 179 degrees */
01148 
01149   if (i == j)
01150     {                           /* sanity - a full loop can never be an opticurve */
01151       return 1;
01152     }
01153 
01154   k = i;
01155   i1 = mod (i + 1, m);
01156   k1 = mod (k + 1, m);
01157   conv = convc[k1];
01158   if (conv == 0)
01159     {
01160       return 1;
01161     }
01162   d = ddist (pp->curve.vertex[i], pp->curve.vertex[i1]);
01163   for (k = k1; k != j; k = k1)
01164     {
01165       k1 = mod (k + 1, m);
01166       k2 = mod (k + 2, m);
01167       if (convc[k1] != conv)
01168         {
01169           return 1;
01170         }
01171       if (sign
01172           (cprod
01173            (pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
01174             pp->curve.vertex[k2])) != conv)
01175         {
01176           return 1;
01177         }
01178       if (iprod1
01179           (pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1],
01180            pp->curve.vertex[k2]) < d * ddist (pp->curve.vertex[k1],
01181                                               pp->curve.vertex[k2]) * COS179)
01182         {
01183           return 1;
01184         }
01185     }
01186 
01187   /* the curve we're working in: */
01188   p0 = pp->curve.c[mod (i, m)][2];
01189   p1 = pp->curve.vertex[mod (i + 1, m)];
01190   p2 = pp->curve.vertex[mod (j, m)];
01191   p3 = pp->curve.c[mod (j, m)][2];
01192 
01193   /* determine its area */
01194   area = areac[j] - areac[i];
01195   area -=
01196     dpara (pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2]) / 2;
01197   if (i >= j)
01198     {
01199       area += areac[m];
01200     }
01201 
01202   /* find intersection o of p0p1 and p2p3. Let t,s such that o =
01203      interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
01204      triangle (p0,o,p3). */
01205 
01206   A1 = dpara (p0, p1, p2);
01207   A2 = dpara (p0, p1, p3);
01208   A3 = dpara (p0, p2, p3);
01209   /* A4 = dpara(p1, p2, p3); */
01210   A4 = A1 + A3 - A2;
01211 
01212   if (A2 == A1)
01213     {                           /* this should never happen */
01214       return 1;
01215     }
01216 
01217   t = A3 / (A3 - A4);
01218   s = A2 / (A2 - A1);
01219   A = A2 * t / 2.0;
01220 
01221   if (A == 0.0)
01222     {                           /* this should never happen */
01223       return 1;
01224     }
01225 
01226   R = area / A;                 /* relative area */
01227   alpha = 2 - sqrt (4 - R / 0.3);       /* overall alpha for p0-o-p3 curve */
01228 
01229   res->c[0] = interval (t * alpha, p0, p1);
01230   res->c[1] = interval (s * alpha, p3, p2);
01231   res->alpha = alpha;
01232   res->t = t;
01233   res->s = s;
01234 
01235   p1 = res->c[0];
01236   p2 = res->c[1];               /* the proposed curve is now (p0,p1,p2,p3) */
01237 
01238   res->pen = 0;
01239 
01240   /* calculate penalty */
01241   /* check tangency with edges */
01242   for (k = mod (i + 1, m); k != j; k = k1)
01243     {
01244       k1 = mod (k + 1, m);
01245       t = tangent (p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
01246       if (t < -.5)
01247         {
01248           return 1;
01249         }
01250       pt = bezier (t, p0, p1, p2, p3);
01251       d = ddist (pp->curve.vertex[k], pp->curve.vertex[k1]);
01252       if (d == 0.0)
01253         {                       /* this should never happen */
01254           return 1;
01255         }
01256       d1 = dpara (pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
01257       if (fabs (d1) > opttolerance)
01258         {
01259           return 1;
01260         }
01261       if (iprod (pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0
01262           || iprod (pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0)
01263         {
01264           return 1;
01265         }
01266       res->pen += sq (d1);
01267     }
01268 
01269   /* check corners */
01270   for (k = i; k != j; k = k1)
01271     {
01272       k1 = mod (k + 1, m);
01273       t = tangent (p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
01274       if (t < -.5)
01275         {
01276           return 1;
01277         }
01278       pt = bezier (t, p0, p1, p2, p3);
01279       d = ddist (pp->curve.c[k][2], pp->curve.c[k1][2]);
01280       if (d == 0.0)
01281         {                       /* this should never happen */
01282           return 1;
01283         }
01284       d1 = dpara (pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
01285       d2 =
01286         dpara (pp->curve.c[k][2], pp->curve.c[k1][2],
01287                pp->curve.vertex[k1]) / d;
01288       d2 *= 0.75 * pp->curve.alpha[k1];
01289       if (d2 < 0)
01290         {
01291           d1 = -d1;
01292           d2 = -d2;
01293         }
01294       if (d1 < d2 - opttolerance)
01295         {
01296           return 1;
01297         }
01298       if (d1 < d2)
01299         {
01300           res->pen += sq (d1 - d2);
01301         }
01302     }
01303 
01304   return 0;
01305 }
01306 
01313 static int
01314 ATTRIBUTE_UNUSED opticurve (privpath_t * pp, double opttolerance)
01315 {
01316   int m = pp->curve.n;
01317   int *pt = NULL;               /* pt[m+1] */
01318   double *pen = NULL;           /* pen[m+1] */
01319   int *len = NULL;              /* len[m+1] */
01320   opti_t *opt = NULL;           /* opt[m+1] */
01321   int om;
01322   int i, j, r;
01323   opti_t o;
01324   dpoint_t p0;
01325   int i1;
01326   double area;
01327   double alpha;
01328   double *s = NULL;
01329   double *t = NULL;
01330 
01331   int *convc = NULL;            /* conv[m]: pre-computed convexities */
01332   double *areac = NULL;         /* cumarea[m+1]: cache for fast area computation */
01333 
01334   SAFE_MALLOC (pt, m + 1, int);
01335   SAFE_MALLOC (pen, m + 1, double);
01336   SAFE_MALLOC (len, m + 1, int);
01337   SAFE_MALLOC (opt, m + 1, opti_t);
01338   SAFE_MALLOC (convc, m, int);
01339   SAFE_MALLOC (areac, m + 1, double);
01340 
01341   /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
01342   for (i = 0; i < m; i++)
01343     {
01344       if (pp->curve.tag[i] == POTRACE_CURVETO)
01345         {
01346           convc[i] =
01347             sign (dpara
01348                   (pp->curve.vertex[mod (i - 1, m)], pp->curve.vertex[i],
01349                    pp->curve.vertex[mod (i + 1, m)]));
01350         }
01351       else
01352         {
01353           convc[i] = 0;
01354         }
01355     }
01356 
01357   /* pre-calculate areas */
01358   area = 0.0;
01359   areac[0] = 0.0;
01360   p0 = pp->curve.vertex[0];
01361   for (i = 0; i < m; i++)
01362     {
01363       i1 = mod (i + 1, m);
01364       if (pp->curve.tag[i1] == POTRACE_CURVETO)
01365         {
01366           alpha = pp->curve.alpha[i1];
01367           area +=
01368             0.3 * alpha * (4 - alpha) * dpara (pp->curve.c[i][2],
01369                                                pp->curve.vertex[i1],
01370                                                pp->curve.c[i1][2]) / 2;
01371           area += dpara (p0, pp->curve.c[i][2], pp->curve.c[i1][2]) / 2;
01372         }
01373       areac[i + 1] = area;
01374     }
01375 
01376   pt[0] = -1;
01377   pen[0] = 0;
01378   len[0] = 0;
01379 
01380   /* Fixme: we always start from a fixed point -- should find the best
01381      curve cyclically ### */
01382 
01383   for (j = 1; j <= m; j++)
01384     {
01385       /* calculate best path from 0 to j */
01386       pt[j] = j - 1;
01387       pen[j] = pen[j - 1];
01388       len[j] = len[j - 1] + 1;
01389 
01390       for (i = j - 2; i >= 0; i--)
01391         {
01392           r =
01393             opti_penalty (pp, i, mod (j, m), &o, opttolerance, convc, areac);
01394           if (r)
01395             {
01396               break;
01397             }
01398           if (len[j] > len[i] + 1
01399               || (len[j] == len[i] + 1 && pen[j] > pen[i] + o.pen))
01400             {
01401               pt[j] = i;
01402               pen[j] = pen[i] + o.pen;
01403               len[j] = len[i] + 1;
01404               opt[j] = o;
01405             }
01406         }
01407     }
01408   om = len[m];
01409   r = privcurve_init (&pp->ocurve, om);
01410   if (r)
01411     {
01412       goto malloc_error;
01413     }
01414   SAFE_MALLOC (s, om, double);
01415   SAFE_MALLOC (t, om, double);
01416 
01417   j = m;
01418   for (i = om - 1; i >= 0; i--)
01419     {
01420       if (pt[j] == j - 1)
01421         {
01422           pp->ocurve.tag[i] = pp->curve.tag[mod (j, m)];
01423           pp->ocurve.c[i][0] = pp->curve.c[mod (j, m)][0];
01424           pp->ocurve.c[i][1] = pp->curve.c[mod (j, m)][1];
01425           pp->ocurve.c[i][2] = pp->curve.c[mod (j, m)][2];
01426           pp->ocurve.vertex[i] = pp->curve.vertex[mod (j, m)];
01427           pp->ocurve.alpha[i] = pp->curve.alpha[mod (j, m)];
01428           pp->ocurve.alpha0[i] = pp->curve.alpha0[mod (j, m)];
01429           pp->ocurve.beta[i] = pp->curve.beta[mod (j, m)];
01430           s[i] = t[i] = 1.0;
01431         }
01432       else
01433         {
01434           pp->ocurve.tag[i] = POTRACE_CURVETO;
01435           pp->ocurve.c[i][0] = opt[j].c[0];
01436           pp->ocurve.c[i][1] = opt[j].c[1];
01437           pp->ocurve.c[i][2] = pp->curve.c[mod (j, m)][2];
01438           pp->ocurve.vertex[i] =
01439             interval (opt[j].s, pp->curve.c[mod (j, m)][2],
01440                       pp->curve.vertex[mod (j, m)]);
01441           pp->ocurve.alpha[i] = opt[j].alpha;
01442           pp->ocurve.alpha0[i] = opt[j].alpha;
01443           s[i] = opt[j].s;
01444           t[i] = opt[j].t;
01445         }
01446       j = pt[j];
01447     }
01448 
01449   /* calculate beta parameters */
01450   for (i = 0; i < om; i++)
01451     {
01452       i1 = mod (i + 1, om);
01453       pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
01454     }
01455   pp->ocurve.alphacurve = 1;
01456 
01457   free (pt);
01458   free (pen);
01459   free (len);
01460   free (opt);
01461   free (s);
01462   free (t);
01463   free (convc);
01464   free (areac);
01465   return 0;
01466 
01467 malloc_error:
01468   free (pt);
01469   free (pen);
01470   free (len);
01471   free (opt);
01472   free (s);
01473   free (t);
01474   free (convc);
01475   free (areac);
01476   return 1;
01477 }
01478 
01479 /* ---------------------------------------------------------------------- */
01480 double
01481 plotpolygon (privpath_t * pp, FILE * f, double scale,
01482              const char *var_cutdepth, const char *var_safeZ,
01483              const char *var_plunge, const char *var_feedrate)
01484 {
01485   int i;
01486   int m = pp->m;
01487   int *po = pp->po;
01488   point_t *pt = pp->pt;
01489   /* double scale=1.0/dpi; */
01490   double dm = 0;
01491 
01492   if (!m)
01493     return 0;
01494 
01495   po = pp->po;
01496   pt = pp->pt;
01497 
01498   pcb_fprintf (f, "G0 X%`f Y%`f    (start point)\n", pt[po[0]].x * scale,
01499                pt[po[0]].y * scale);
01500   pcb_fprintf (f, "G1 Z%s F%s\n", var_cutdepth, var_plunge);
01501   pcb_fprintf (f, "F%s\n", var_feedrate);
01502   for (i = 1; i < m; i++)
01503     {
01504       pcb_fprintf (f, "G1 X%`f Y%`f\n",
01505                    pt[po[i]].x * scale, pt[po[i]].y * scale);
01506       dm += fabs (scale) * hypot (pt[po[i]].x - pt[po[i - 1]].x, pt[po[i]].y - pt[po[i - 1]].y);
01507     }
01508   pcb_fprintf (f, "G1 X%`f Y%`f\n", pt[po[0]].x * scale, pt[po[0]].y * scale);
01509   pcb_fprintf (f, "G0 Z%s\n", var_safeZ);
01510   dm += fabs (scale) * hypot (pt[po[m - 1]].x - pt[po[0]].x, pt[po[m - 1]].y - pt[po[0]].y);
01511   pcb_fprintf (f, "(polygon end, distance %`.2f)\n", dm);
01512   return dm;
01513 }
01514 
01515 #define TRY(x) if (x) goto try_error
01516 
01522 double
01523 process_path (path_t * plist, const potrace_param_t * param,
01524               const potrace_bitmap_t * bm, FILE * f, double scale,
01525               const char *var_cutdepth, const char *var_safeZ,
01526               const char *var_plunge, const char *var_feedrate)
01527 {
01528   path_t *p;
01529   double dm = 0;
01530   int n = 0;
01531   /* call downstream function with each path */
01532   list_forall (p, plist)
01533   {
01534     TRY (calc_sums (p->priv));
01535     TRY (calc_lon (p->priv));
01536     TRY (bestpolygon (p->priv));
01537     TRY (adjust_vertices (p->priv));
01538     fprintf (f, "(polygon %d)\n", ++n);
01539     dm += plotpolygon (p->priv, f, scale, var_cutdepth, var_safeZ, var_plunge,
01540                        var_feedrate);
01541 /*  No need to extract curves
01542         TRY(smooth(&p->priv->curve, p->sign, param->alphamax));
01543     if (param->opticurve) {
01544       TRY(opticurve(p->priv, param->opttolerance));
01545       p->priv->fcurve = &p->priv->ocurve;
01546     } else {
01547       p->priv->fcurve = &p->priv->curve;
01548     }
01549     privcurve_to_curve(p->priv->fcurve, &p->curve);*/
01550   }
01551 /*      fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm); */
01552   return dm;
01553 
01554 try_error:
01555   return -1;
01556 }