xref: /potrace-1.14/src/trace.c (revision b3fce824)
1 /* Copyright (C) 2001-2017 Peter Selinger.
2    This file is part of Potrace. It is free software and it is covered
3    by the GNU General Public License. See the file COPYING for details. */
4 
5 /* transform jaggy paths into smooth curves */
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <stdio.h>
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "potracelib.h"
17 #include "curve.h"
18 #include "lists.h"
19 #include "auxiliary.h"
20 #include "trace.h"
21 #include "progress.h"
22 
23 #define INFTY 10000000	/* it suffices that this is longer than any
24 			   path; it need not be really infinite */
25 #define COS179 -0.999847695156	 /* the cosine of 179 degrees */
26 
27 /* ---------------------------------------------------------------------- */
28 #define SAFE_CALLOC(var, n, typ) \
29   if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
30 
31 /* ---------------------------------------------------------------------- */
32 /* auxiliary functions */
33 
34 /* return a direction that is 90 degrees counterclockwise from p2-p0,
35    but then restricted to one of the major wind directions (n, nw, w, etc) */
dorth_infty(dpoint_t p0,dpoint_t p2)36 static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
37   point_t r;
38 
39   r.y = sign(p2.x-p0.x);
40   r.x = -sign(p2.y-p0.y);
41 
42   return r;
43 }
44 
45 /* return (p1-p0)x(p2-p0), the area of the parallelogram */
dpara(dpoint_t p0,dpoint_t p1,dpoint_t p2)46 static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
47   double x1, y1, x2, y2;
48 
49   x1 = p1.x-p0.x;
50   y1 = p1.y-p0.y;
51   x2 = p2.x-p0.x;
52   y2 = p2.y-p0.y;
53 
54   return x1*y2 - x2*y1;
55 }
56 
57 /* ddenom/dpara have the property that the square of radius 1 centered
58    at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
ddenom(dpoint_t p0,dpoint_t p2)59 static inline double ddenom(dpoint_t p0, dpoint_t p2) {
60   point_t r = dorth_infty(p0, p2);
61 
62   return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
63 }
64 
65 /* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
cyclic(int a,int b,int c)66 static inline int cyclic(int a, int b, int c) {
67   if (a<=c) {
68     return (a<=b && b<c);
69   } else {
70     return (a<=b || b<c);
71   }
72 }
73 
74 /* determine the center and slope of the line i..j. Assume i<j. Needs
75    "sum" components of p to be set. */
pointslope(privpath_t * pp,int i,int j,dpoint_t * ctr,dpoint_t * dir)76 static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
77   /* assume i<j */
78 
79   int n = pp->len;
80   sums_t *sums = pp->sums;
81 
82   double x, y, x2, xy, y2;
83   double k;
84   double a, b, c, lambda2, l;
85   int r=0; /* rotations from i to j */
86 
87   while (j>=n) {
88     j-=n;
89     r+=1;
90   }
91   while (i>=n) {
92     i-=n;
93     r-=1;
94   }
95   while (j<0) {
96     j+=n;
97     r-=1;
98   }
99   while (i<0) {
100     i+=n;
101     r+=1;
102   }
103 
104   x = sums[j+1].x-sums[i].x+r*sums[n].x;
105   y = sums[j+1].y-sums[i].y+r*sums[n].y;
106   x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
107   xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
108   y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
109   k = j+1-i+r*n;
110 
111   ctr->x = x/k;
112   ctr->y = y/k;
113 
114   a = (x2-(double)x*x/k)/k;
115   b = (xy-(double)x*y/k)/k;
116   c = (y2-(double)y*y/k)/k;
117 
118   lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
119 
120   /* now find e.vector for lambda2 */
121   a -= lambda2;
122   c -= lambda2;
123 
124   if (fabs(a) >= fabs(c)) {
125     l = sqrt(a*a+b*b);
126     if (l!=0) {
127       dir->x = -b/l;
128       dir->y = a/l;
129     }
130   } else {
131     l = sqrt(c*c+b*b);
132     if (l!=0) {
133       dir->x = -c/l;
134       dir->y = b/l;
135     }
136   }
137   if (l==0) {
138     dir->x = dir->y = 0;   /* sometimes this can happen when k=4:
139 			      the two eigenvalues coincide */
140   }
141 }
142 
143 /* the type of (affine) quadratic forms, represented as symmetric 3x3
144    matrices.  The value of the quadratic form at a vector (x,y) is v^t
145    Q v, where v = (x,y,1)^t. */
146 typedef double quadform_t[3][3];
147 
148 /* Apply quadratic form Q to vector w = (w.x,w.y) */
quadform(quadform_t Q,dpoint_t w)149 static inline double quadform(quadform_t Q, dpoint_t w) {
150   double v[3];
151   int i, j;
152   double sum;
153 
154   v[0] = w.x;
155   v[1] = w.y;
156   v[2] = 1;
157   sum = 0.0;
158 
159   for (i=0; i<3; i++) {
160     for (j=0; j<3; j++) {
161       sum += v[i] * Q[i][j] * v[j];
162     }
163   }
164   return sum;
165 }
166 
167 /* calculate p1 x p2 */
xprod(point_t p1,point_t p2)168 static inline int xprod(point_t p1, point_t p2) {
169   return p1.x*p2.y - p1.y*p2.x;
170 }
171 
172 /* calculate (p1-p0)x(p3-p2) */
cprod(dpoint_t p0,dpoint_t p1,dpoint_t p2,dpoint_t p3)173 static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
174   double x1, y1, x2, y2;
175 
176   x1 = p1.x - p0.x;
177   y1 = p1.y - p0.y;
178   x2 = p3.x - p2.x;
179   y2 = p3.y - p2.y;
180 
181   return x1*y2 - x2*y1;
182 }
183 
184 /* calculate (p1-p0)*(p2-p0) */
iprod(dpoint_t p0,dpoint_t p1,dpoint_t p2)185 static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
186   double x1, y1, x2, y2;
187 
188   x1 = p1.x - p0.x;
189   y1 = p1.y - p0.y;
190   x2 = p2.x - p0.x;
191   y2 = p2.y - p0.y;
192 
193   return x1*x2 + y1*y2;
194 }
195 
196 /* calculate (p1-p0)*(p3-p2) */
iprod1(dpoint_t p0,dpoint_t p1,dpoint_t p2,dpoint_t p3)197 static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
198   double x1, y1, x2, y2;
199 
200   x1 = p1.x - p0.x;
201   y1 = p1.y - p0.y;
202   x2 = p3.x - p2.x;
203   y2 = p3.y - p2.y;
204 
205   return x1*x2 + y1*y2;
206 }
207 
208 /* calculate distance between two points */
ddist(dpoint_t p,dpoint_t q)209 static inline double ddist(dpoint_t p, dpoint_t q) {
210   return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
211 }
212 
213 /* calculate point of a bezier curve */
bezier(double t,dpoint_t p0,dpoint_t p1,dpoint_t p2,dpoint_t p3)214 static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
215   double s = 1-t;
216   dpoint_t res;
217 
218   /* Note: a good optimizing compiler (such as gcc-3) reduces the
219      following to 16 multiplications, using common subexpression
220      elimination. */
221 
222   res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
223   res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
224 
225   return res;
226 }
227 
228 /* calculate the point t in [0..1] on the (convex) bezier curve
229    (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
230    solution in [0..1]. */
tangent(dpoint_t p0,dpoint_t p1,dpoint_t p2,dpoint_t p3,dpoint_t q0,dpoint_t q1)231 static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
232   double A, B, C;   /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
233   double a, b, c;   /* a t^2 + b t + c = 0 */
234   double d, s, r1, r2;
235 
236   A = cprod(p0, p1, q0, q1);
237   B = cprod(p1, p2, q0, q1);
238   C = cprod(p2, p3, q0, q1);
239 
240   a = A - 2*B + C;
241   b = -2*A + 2*B;
242   c = A;
243 
244   d = b*b - 4*a*c;
245 
246   if (a==0 || d<0) {
247     return -1.0;
248   }
249 
250   s = sqrt(d);
251 
252   r1 = (-b + s) / (2 * a);
253   r2 = (-b - s) / (2 * a);
254 
255   if (r1 >= 0 && r1 <= 1) {
256     return r1;
257   } else if (r2 >= 0 && r2 <= 1) {
258     return r2;
259   } else {
260     return -1.0;
261   }
262 }
263 
264 /* ---------------------------------------------------------------------- */
265 /* Preparation: fill in the sum* fields of a path (used for later
266    rapid summing). Return 0 on success, 1 with errno set on
267    failure. */
calc_sums(privpath_t * pp)268 static int calc_sums(privpath_t *pp) {
269   int i, x, y;
270   int n = pp->len;
271 
272   SAFE_CALLOC(pp->sums, pp->len+1, sums_t);
273 
274   /* origin */
275   pp->x0 = pp->pt[0].x;
276   pp->y0 = pp->pt[0].y;
277 
278   /* preparatory computation for later fast summing */
279   pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
280   for (i=0; i<n; i++) {
281     x = pp->pt[i].x - pp->x0;
282     y = pp->pt[i].y - pp->y0;
283     pp->sums[i+1].x = pp->sums[i].x + x;
284     pp->sums[i+1].y = pp->sums[i].y + y;
285     pp->sums[i+1].x2 = pp->sums[i].x2 + x*x;
286     pp->sums[i+1].xy = pp->sums[i].xy + x*y;
287     pp->sums[i+1].y2 = pp->sums[i].y2 + y*y;
288   }
289   return 0;
290 
291  calloc_error:
292   return 1;
293 }
294 
295 /* ---------------------------------------------------------------------- */
296 /* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the
297    "lon" component of a path object (based on pt/len).	For each i,
298    lon[i] is the furthest index such that a straight line can be drawn
299    from i to lon[i]. Return 1 on error with errno set, else 0. */
300 
301 /* this algorithm depends on the fact that the existence of straight
302    subpaths is a triplewise property. I.e., there exists a straight
303    line through squares i0,...,in iff there exists a straight line
304    through i,j,k, for all i0<=i<j<k<=in. (Proof?) */
305 
306 /* this implementation of calc_lon is O(n^2). It replaces an older
307    O(n^3) version. A "constraint" means that future points must
308    satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1],
309    cur) <= 0. */
310 
311 /* Remark for Potrace 1.1: the current implementation of calc_lon is
312    more complex than the implementation found in Potrace 1.0, but it
313    is considerably faster. The introduction of the "nc" data structure
314    means that we only have to test the constraints for "corner"
315    points. On a typical input file, this speeds up the calc_lon
316    function by a factor of 31.2, thereby decreasing its time share
317    within the overall Potrace algorithm from 72.6% to 7.82%, and
318    speeding up the overall algorithm by a factor of 3.36. On another
319    input file, calc_lon was sped up by a factor of 6.7, decreasing its
320    time share from 51.4% to 13.61%, and speeding up the overall
321    algorithm by a factor of 1.78. In any case, the savings are
322    substantial. */
323 
324 /* returns 0 on success, 1 on error with errno set */
calc_lon(privpath_t * pp)325 static int calc_lon(privpath_t *pp) {
326   point_t *pt = pp->pt;
327   int n = pp->len;
328   int i, j, k, k1;
329   int ct[4], dir;
330   point_t constraint[2];
331   point_t cur;
332   point_t off;
333   int *pivk = NULL;  /* pivk[n] */
334   int *nc = NULL;    /* nc[n]: next corner */
335   point_t dk;  /* direction of k-k1 */
336   int a, b, c, d;
337 
338   SAFE_CALLOC(pivk, n, int);
339   SAFE_CALLOC(nc, n, int);
340 
341   /* initialize the nc data structure. Point from each point to the
342      furthest future point to which it is connected by a vertical or
343      horizontal segment. We take advantage of the fact that there is
344      always a direction change at 0 (due to the path decomposition
345      algorithm). But even if this were not so, there is no harm, as
346      in practice, correctness does not depend on the word "furthest"
347      above.  */
348   k = 0;
349   for (i=n-1; i>=0; i--) {
350     if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
351       k = i+1;  /* necessarily i<n-1 in this case */
352     }
353     nc[i] = k;
354   }
355 
356   SAFE_CALLOC(pp->lon, n, int);
357 
358   /* determine pivot points: for each i, let pivk[i] be the furthest k
359      such that all j with i<j<k lie on a line connecting i,k. */
360 
361   for (i=n-1; i>=0; i--) {
362     ct[0] = ct[1] = ct[2] = ct[3] = 0;
363 
364     /* keep track of "directions" that have occurred */
365     dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
366     ct[dir]++;
367 
368     constraint[0].x = 0;
369     constraint[0].y = 0;
370     constraint[1].x = 0;
371     constraint[1].y = 0;
372 
373     /* find the next k such that no straight line from i to k */
374     k = nc[i];
375     k1 = i;
376     while (1) {
377 
378       dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
379       ct[dir]++;
380 
381       /* if all four "directions" have occurred, cut this path */
382       if (ct[0] && ct[1] && ct[2] && ct[3]) {
383 	pivk[i] = k1;
384 	goto foundk;
385       }
386 
387       cur.x = pt[k].x - pt[i].x;
388       cur.y = pt[k].y - pt[i].y;
389 
390       /* see if current constraint is violated */
391       if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
392 	goto constraint_viol;
393       }
394 
395       /* else, update constraint */
396       if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
397 	/* no constraint */
398       } else {
399 	off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
400 	off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
401 	if (xprod(constraint[0], off) >= 0) {
402 	  constraint[0] = off;
403 	}
404 	off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
405 	off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
406 	if (xprod(constraint[1], off) <= 0) {
407 	  constraint[1] = off;
408 	}
409       }
410       k1 = k;
411       k = nc[k1];
412       if (!cyclic(k,i,k1)) {
413 	break;
414       }
415     }
416   constraint_viol:
417     /* k1 was the last "corner" satisfying the current constraint, and
418        k is the first one violating it. We now need to find the last
419        point along k1..k which satisfied the constraint. */
420     dk.x = sign(pt[k].x-pt[k1].x);
421     dk.y = sign(pt[k].y-pt[k1].y);
422     cur.x = pt[k1].x - pt[i].x;
423     cur.y = pt[k1].y - pt[i].y;
424     /* find largest integer j such that xprod(constraint[0], cur+j*dk)
425        >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
426        of xprod. */
427     a = xprod(constraint[0], cur);
428     b = xprod(constraint[0], dk);
429     c = xprod(constraint[1], cur);
430     d = xprod(constraint[1], dk);
431     /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
432        can be solved with integer arithmetic. */
433     j = INFTY;
434     if (b<0) {
435       j = floordiv(a,-b);
436     }
437     if (d>0) {
438       j = min(j, floordiv(-c,d));
439     }
440     pivk[i] = mod(k1+j,n);
441   foundk:
442     ;
443   } /* for i */
444 
445   /* clean up: for each i, let lon[i] be the largest k such that for
446      all i' with i<=i'<k, i'<k<=pivk[i']. */
447 
448   j=pivk[n-1];
449   pp->lon[n-1]=j;
450   for (i=n-2; i>=0; i--) {
451     if (cyclic(i+1,pivk[i],j)) {
452       j=pivk[i];
453     }
454     pp->lon[i]=j;
455   }
456 
457   for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
458     pp->lon[i] = j;
459   }
460 
461   free(pivk);
462   free(nc);
463   return 0;
464 
465  calloc_error:
466   free(pivk);
467   free(nc);
468   return 1;
469 }
470 
471 
472 /* ---------------------------------------------------------------------- */
473 /* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
474 
475 /* Auxiliary function: calculate the penalty of an edge from i to j in
476    the given path. This needs the "lon" and "sum*" data. */
477 
penalty3(privpath_t * pp,int i,int j)478 static double penalty3(privpath_t *pp, int i, int j) {
479   int n = pp->len;
480   point_t *pt = pp->pt;
481   sums_t *sums = pp->sums;
482 
483   /* assume 0<=i<j<=n  */
484   double x, y, x2, xy, y2;
485   double k;
486   double a, b, c, s;
487   double px, py, ex, ey;
488 
489   int r = 0; /* rotations from i to j */
490 
491   if (j>=n) {
492     j -= n;
493     r = 1;
494   }
495 
496   /* critical inner loop: the "if" gives a 4.6 percent speedup */
497   if (r == 0) {
498     x = sums[j+1].x - sums[i].x;
499     y = sums[j+1].y - sums[i].y;
500     x2 = sums[j+1].x2 - sums[i].x2;
501     xy = sums[j+1].xy - sums[i].xy;
502     y2 = sums[j+1].y2 - sums[i].y2;
503     k = j+1 - i;
504   } else {
505     x = sums[j+1].x - sums[i].x + sums[n].x;
506     y = sums[j+1].y - sums[i].y + sums[n].y;
507     x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2;
508     xy = sums[j+1].xy - sums[i].xy + sums[n].xy;
509     y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2;
510     k = j+1 - i + n;
511   }
512 
513   px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
514   py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
515   ey = (pt[j].x - pt[i].x);
516   ex = -(pt[j].y - pt[i].y);
517 
518   a = ((x2 - 2*x*px) / k + px*px);
519   b = ((xy - x*py - y*px) / k + px*py);
520   c = ((y2 - 2*y*py) / k + py*py);
521 
522   s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
523 
524   return sqrt(s);
525 }
526 
527 /* find the optimal polygon. Fill in the m and po components. Return 1
528    on failure with errno set, else 0. Non-cyclic version: assumes i=0
529    is in the polygon. Fixme: implement cyclic version. */
bestpolygon(privpath_t * pp)530 static int bestpolygon(privpath_t *pp)
531 {
532   int i, j, m, k;
533   int n = pp->len;
534   double *pen = NULL; /* pen[n+1]: penalty vector */
535   int *prev = NULL;   /* prev[n+1]: best path pointer vector */
536   int *clip0 = NULL;  /* clip0[n]: longest segment pointer, non-cyclic */
537   int *clip1 = NULL;  /* clip1[n+1]: backwards segment pointer, non-cyclic */
538   int *seg0 = NULL;    /* seg0[m+1]: forward segment bounds, m<=n */
539   int *seg1 = NULL;   /* seg1[m+1]: backward segment bounds, m<=n */
540   double thispen;
541   double best;
542   int c;
543 
544   SAFE_CALLOC(pen, n+1, double);
545   SAFE_CALLOC(prev, n+1, int);
546   SAFE_CALLOC(clip0, n, int);
547   SAFE_CALLOC(clip1, n+1, int);
548   SAFE_CALLOC(seg0, n+1, int);
549   SAFE_CALLOC(seg1, n+1, int);
550 
551   /* calculate clipped paths */
552   for (i=0; i<n; i++) {
553     c = mod(pp->lon[mod(i-1,n)]-1,n);
554     if (c == i) {
555       c = mod(i+1,n);
556     }
557     if (c < i) {
558       clip0[i] = n;
559     } else {
560       clip0[i] = c;
561     }
562   }
563 
564   /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
565      clip1[j] <= i, for i,j=0..n. */
566   j = 1;
567   for (i=0; i<n; i++) {
568     while (j <= clip0[i]) {
569       clip1[j] = i;
570       j++;
571     }
572   }
573 
574   /* calculate seg0[j] = longest path from 0 with j segments */
575   i = 0;
576   for (j=0; i<n; j++) {
577     seg0[j] = i;
578     i = clip0[i];
579   }
580   seg0[j] = n;
581   m = j;
582 
583   /* calculate seg1[j] = longest path to n with m-j segments */
584   i = n;
585   for (j=m; j>0; j--) {
586     seg1[j] = i;
587     i = clip1[i];
588   }
589   seg1[0] = 0;
590 
591   /* now find the shortest path with m segments, based on penalty3 */
592   /* note: the outer 2 loops jointly have at most n iterations, thus
593      the worst-case behavior here is quadratic. In practice, it is
594      close to linear since the inner loop tends to be short. */
595   pen[0]=0;
596   for (j=1; j<=m; j++) {
597     for (i=seg1[j]; i<=seg0[j]; i++) {
598       best = -1;
599       for (k=seg0[j-1]; k>=clip1[i]; k--) {
600 	thispen = penalty3(pp, k, i) + pen[k];
601 	if (best < 0 || thispen < best) {
602 	  prev[i] = k;
603 	  best = thispen;
604 	}
605       }
606       pen[i] = best;
607     }
608   }
609 
610   pp->m = m;
611   SAFE_CALLOC(pp->po, m, int);
612 
613   /* read off shortest path */
614   for (i=n, j=m-1; i>0; j--) {
615     i = prev[i];
616     pp->po[j] = i;
617   }
618 
619   free(pen);
620   free(prev);
621   free(clip0);
622   free(clip1);
623   free(seg0);
624   free(seg1);
625   return 0;
626 
627  calloc_error:
628   free(pen);
629   free(prev);
630   free(clip0);
631   free(clip1);
632   free(seg0);
633   free(seg1);
634   return 1;
635 }
636 
637 /* ---------------------------------------------------------------------- */
638 /* Stage 3: vertex adjustment (Sec. 2.3.1). */
639 
640 /* Adjust vertices of optimal polygon: calculate the intersection of
641    the two "optimal" line segments, then move it into the unit square
642    if it lies outside. Return 1 with errno set on error; 0 on
643    success. */
644 
adjust_vertices(privpath_t * pp)645 static int adjust_vertices(privpath_t *pp) {
646   int m = pp->m;
647   int *po = pp->po;
648   int n = pp->len;
649   point_t *pt = pp->pt;
650   int x0 = pp->x0;
651   int y0 = pp->y0;
652 
653   dpoint_t *ctr = NULL;      /* ctr[m] */
654   dpoint_t *dir = NULL;      /* dir[m] */
655   quadform_t *q = NULL;      /* q[m] */
656   double v[3];
657   double d;
658   int i, j, k, l;
659   dpoint_t s;
660   int r;
661 
662   SAFE_CALLOC(ctr, m, dpoint_t);
663   SAFE_CALLOC(dir, m, dpoint_t);
664   SAFE_CALLOC(q, m, quadform_t);
665 
666   r = privcurve_init(&pp->curve, m);
667   if (r) {
668     goto calloc_error;
669   }
670 
671   /* calculate "optimal" point-slope representation for each line
672      segment */
673   for (i=0; i<m; i++) {
674     j = po[mod(i+1,m)];
675     j = mod(j-po[i],n)+po[i];
676     pointslope(pp, po[i], j, &ctr[i], &dir[i]);
677   }
678 
679   /* represent each line segment as a singular quadratic form; the
680      distance of a point (x,y) from the line segment will be
681      (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
682   for (i=0; i<m; i++) {
683     d = sq(dir[i].x) + sq(dir[i].y);
684     if (d == 0.0) {
685       for (j=0; j<3; j++) {
686 	for (k=0; k<3; k++) {
687 	  q[i][j][k] = 0;
688 	}
689       }
690     } else {
691       v[0] = dir[i].y;
692       v[1] = -dir[i].x;
693       v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
694       for (l=0; l<3; l++) {
695 	for (k=0; k<3; k++) {
696 	  q[i][l][k] = v[l] * v[k] / d;
697 	}
698       }
699     }
700   }
701 
702   /* now calculate the "intersections" of consecutive segments.
703      Instead of using the actual intersection, we find the point
704      within a given unit square which minimizes the square distance to
705      the two lines. */
706   for (i=0; i<m; i++) {
707     quadform_t Q;
708     dpoint_t w;
709     double dx, dy;
710     double det;
711     double min, cand; /* minimum and candidate for minimum of quad. form */
712     double xmin, ymin;	/* coordinates of minimum */
713     int z;
714 
715     /* let s be the vertex, in coordinates relative to x0/y0 */
716     s.x = pt[po[i]].x-x0;
717     s.y = pt[po[i]].y-y0;
718 
719     /* intersect segments i-1 and i */
720 
721     j = mod(i-1,m);
722 
723     /* add quadratic forms */
724     for (l=0; l<3; l++) {
725       for (k=0; k<3; k++) {
726 	Q[l][k] = q[j][l][k] + q[i][l][k];
727       }
728     }
729 
730     while(1) {
731       /* minimize the quadratic form Q on the unit square */
732       /* find intersection */
733 
734 #ifdef HAVE_GCC_LOOP_BUG
735       /* work around gcc bug #12243 */
736       free(NULL);
737 #endif
738 
739       det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
740       if (det != 0.0) {
741 	w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
742 	w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
743 	break;
744       }
745 
746       /* matrix is singular - lines are parallel. Add another,
747 	 orthogonal axis, through the center of the unit square */
748       if (Q[0][0]>Q[1][1]) {
749 	v[0] = -Q[0][1];
750 	v[1] = Q[0][0];
751       } else if (Q[1][1]) {
752 	v[0] = -Q[1][1];
753 	v[1] = Q[1][0];
754       } else {
755 	v[0] = 1;
756 	v[1] = 0;
757       }
758       d = sq(v[0]) + sq(v[1]);
759       v[2] = - v[1] * s.y - v[0] * s.x;
760       for (l=0; l<3; l++) {
761 	for (k=0; k<3; k++) {
762 	  Q[l][k] += v[l] * v[k] / d;
763 	}
764       }
765     }
766     dx = fabs(w.x-s.x);
767     dy = fabs(w.y-s.y);
768     if (dx <= .5 && dy <= .5) {
769       pp->curve.vertex[i].x = w.x+x0;
770       pp->curve.vertex[i].y = w.y+y0;
771       continue;
772     }
773 
774     /* the minimum was not in the unit square; now minimize quadratic
775        on boundary of square */
776     min = quadform(Q, s);
777     xmin = s.x;
778     ymin = s.y;
779 
780     if (Q[0][0] == 0.0) {
781       goto fixx;
782     }
783     for (z=0; z<2; z++) {   /* value of the y-coordinate */
784       w.y = s.y-0.5+z;
785       w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
786       dx = fabs(w.x-s.x);
787       cand = quadform(Q, w);
788       if (dx <= .5 && cand < min) {
789 	min = cand;
790 	xmin = w.x;
791 	ymin = w.y;
792       }
793     }
794   fixx:
795     if (Q[1][1] == 0.0) {
796       goto corners;
797     }
798     for (z=0; z<2; z++) {   /* value of the x-coordinate */
799       w.x = s.x-0.5+z;
800       w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
801       dy = fabs(w.y-s.y);
802       cand = quadform(Q, w);
803       if (dy <= .5 && cand < min) {
804 	min = cand;
805 	xmin = w.x;
806 	ymin = w.y;
807       }
808     }
809   corners:
810     /* check four corners */
811     for (l=0; l<2; l++) {
812       for (k=0; k<2; k++) {
813 	w.x = s.x-0.5+l;
814 	w.y = s.y-0.5+k;
815 	cand = quadform(Q, w);
816 	if (cand < min) {
817 	  min = cand;
818 	  xmin = w.x;
819 	  ymin = w.y;
820 	}
821       }
822     }
823 
824     pp->curve.vertex[i].x = xmin + x0;
825     pp->curve.vertex[i].y = ymin + y0;
826     continue;
827   }
828 
829   free(ctr);
830   free(dir);
831   free(q);
832   return 0;
833 
834  calloc_error:
835   free(ctr);
836   free(dir);
837   free(q);
838   return 1;
839 }
840 
841 /* ---------------------------------------------------------------------- */
842 /* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
843 
844 /* reverse orientation of a path */
reverse(privcurve_t * curve)845 static void reverse(privcurve_t *curve) {
846   int m = curve->n;
847   int i, j;
848   dpoint_t tmp;
849 
850   for (i=0, j=m-1; i<j; i++, j--) {
851     tmp = curve->vertex[i];
852     curve->vertex[i] = curve->vertex[j];
853     curve->vertex[j] = tmp;
854   }
855 }
856 
857 /* Always succeeds */
smooth(privcurve_t * curve,double alphamax)858 static void smooth(privcurve_t *curve, double alphamax) {
859   int m = curve->n;
860 
861   int i, j, k;
862   double dd, denom, alpha;
863   dpoint_t p2, p3, p4;
864 
865   /* examine each vertex and find its best fit */
866   for (i=0; i<m; i++) {
867     j = mod(i+1, m);
868     k = mod(i+2, m);
869     p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
870 
871     denom = ddenom(curve->vertex[i], curve->vertex[k]);
872     if (denom != 0.0) {
873       dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
874       dd = fabs(dd);
875       alpha = dd>1 ? (1 - 1.0/dd) : 0;
876       alpha = alpha / 0.75;
877     } else {
878       alpha = 4/3.0;
879     }
880     curve->alpha0[j] = alpha;	 /* remember "original" value of alpha */
881 
882     if (alpha >= alphamax) {  /* pointed corner */
883       curve->tag[j] = POTRACE_CORNER;
884       curve->c[j][1] = curve->vertex[j];
885       curve->c[j][2] = p4;
886     } else {
887       if (alpha < 0.55) {
888 	alpha = 0.55;
889       } else if (alpha > 1) {
890 	alpha = 1;
891       }
892       p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
893       p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
894       curve->tag[j] = POTRACE_CURVETO;
895       curve->c[j][0] = p2;
896       curve->c[j][1] = p3;
897       curve->c[j][2] = p4;
898     }
899     curve->alpha[j] = alpha;	/* store the "cropped" value of alpha */
900     curve->beta[j] = 0.5;
901   }
902   curve->alphacurve = 1;
903 
904   return;
905 }
906 
907 /* ---------------------------------------------------------------------- */
908 /* Stage 5: Curve optimization (Sec. 2.4) */
909 
910 /* a private type for the result of opti_penalty */
911 struct opti_s {
912   double pen;	   /* penalty */
913   dpoint_t c[2];   /* curve parameters */
914   double t, s;	   /* curve parameters */
915   double alpha;	   /* curve parameter */
916 };
917 typedef struct opti_s opti_t;
918 
919 /* calculate best fit from i+.5 to j+.5.  Assume i<j (cyclically).
920    Return 0 and set badness and parameters (alpha, beta), if
921    possible. Return 1 if impossible. */
opti_penalty(privpath_t * pp,int i,int j,opti_t * res,double opttolerance,int * convc,double * areac)922 static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
923   int m = pp->curve.n;
924   int k, k1, k2, conv, i1;
925   double area, alpha, d, d1, d2;
926   dpoint_t p0, p1, p2, p3, pt;
927   double A, R, A1, A2, A3, A4;
928   double s, t;
929 
930   /* check convexity, corner-freeness, and maximum bend < 179 degrees */
931 
932   if (i==j) {  /* sanity - a full loop can never be an opticurve */
933     return 1;
934   }
935 
936   k = i;
937   i1 = mod(i+1, m);
938   k1 = mod(k+1, m);
939   conv = convc[k1];
940   if (conv == 0) {
941     return 1;
942   }
943   d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
944   for (k=k1; k!=j; k=k1) {
945     k1 = mod(k+1, m);
946     k2 = mod(k+2, m);
947     if (convc[k1] != conv) {
948       return 1;
949     }
950     if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
951       return 1;
952     }
953     if (iprod1(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) {
954       return 1;
955     }
956   }
957 
958   /* the curve we're working in: */
959   p0 = pp->curve.c[mod(i,m)][2];
960   p1 = pp->curve.vertex[mod(i+1,m)];
961   p2 = pp->curve.vertex[mod(j,m)];
962   p3 = pp->curve.c[mod(j,m)][2];
963 
964   /* determine its area */
965   area = areac[j] - areac[i];
966   area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
967   if (i>=j) {
968     area += areac[m];
969   }
970 
971   /* find intersection o of p0p1 and p2p3. Let t,s such that o =
972      interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
973      triangle (p0,o,p3). */
974 
975   A1 = dpara(p0, p1, p2);
976   A2 = dpara(p0, p1, p3);
977   A3 = dpara(p0, p2, p3);
978   /* A4 = dpara(p1, p2, p3); */
979   A4 = A1+A3-A2;
980 
981   if (A2 == A1) {  /* this should never happen */
982     return 1;
983   }
984 
985   t = A3/(A3-A4);
986   s = A2/(A2-A1);
987   A = A2 * t / 2.0;
988 
989   if (A == 0.0) {  /* this should never happen */
990     return 1;
991   }
992 
993   R = area / A;	 /* relative area */
994   alpha = 2 - sqrt(4 - R / 0.3);  /* overall alpha for p0-o-p3 curve */
995 
996   res->c[0] = interval(t * alpha, p0, p1);
997   res->c[1] = interval(s * alpha, p3, p2);
998   res->alpha = alpha;
999   res->t = t;
1000   res->s = s;
1001 
1002   p1 = res->c[0];
1003   p2 = res->c[1];  /* the proposed curve is now (p0,p1,p2,p3) */
1004 
1005   res->pen = 0;
1006 
1007   /* calculate penalty */
1008   /* check tangency with edges */
1009   for (k=mod(i+1,m); k!=j; k=k1) {
1010     k1 = mod(k+1,m);
1011     t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
1012     if (t<-.5) {
1013       return 1;
1014     }
1015     pt = bezier(t, p0, p1, p2, p3);
1016     d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
1017     if (d == 0.0) {  /* this should never happen */
1018       return 1;
1019     }
1020     d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
1021     if (fabs(d1) > opttolerance) {
1022       return 1;
1023     }
1024     if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
1025       return 1;
1026     }
1027     res->pen += sq(d1);
1028   }
1029 
1030   /* check corners */
1031   for (k=i; k!=j; k=k1) {
1032     k1 = mod(k+1,m);
1033     t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
1034     if (t<-.5) {
1035       return 1;
1036     }
1037     pt = bezier(t, p0, p1, p2, p3);
1038     d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
1039     if (d == 0.0) {  /* this should never happen */
1040       return 1;
1041     }
1042     d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
1043     d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
1044     d2 *= 0.75 * pp->curve.alpha[k1];
1045     if (d2 < 0) {
1046       d1 = -d1;
1047       d2 = -d2;
1048     }
1049     if (d1 < d2 - opttolerance) {
1050       return 1;
1051     }
1052     if (d1 < d2) {
1053       res->pen += sq(d1 - d2);
1054     }
1055   }
1056 
1057   return 0;
1058 }
1059 
1060 /* optimize the path p, replacing sequences of Bezier segments by a
1061    single segment when possible. Return 0 on success, 1 with errno set
1062    on failure. */
opticurve(privpath_t * pp,double opttolerance)1063 static int opticurve(privpath_t *pp, double opttolerance) {
1064   int m = pp->curve.n;
1065   int *pt = NULL;     /* pt[m+1] */
1066   double *pen = NULL; /* pen[m+1] */
1067   int *len = NULL;    /* len[m+1] */
1068   opti_t *opt = NULL; /* opt[m+1] */
1069   int om;
1070   int i,j,r;
1071   opti_t o;
1072   dpoint_t p0;
1073   int i1;
1074   double area;
1075   double alpha;
1076   double *s = NULL;
1077   double *t = NULL;
1078 
1079   int *convc = NULL; /* conv[m]: pre-computed convexities */
1080   double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
1081 
1082   SAFE_CALLOC(pt, m+1, int);
1083   SAFE_CALLOC(pen, m+1, double);
1084   SAFE_CALLOC(len, m+1, int);
1085   SAFE_CALLOC(opt, m+1, opti_t);
1086   SAFE_CALLOC(convc, m, int);
1087   SAFE_CALLOC(areac, m+1, double);
1088 
1089   /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
1090   for (i=0; i<m; i++) {
1091     if (pp->curve.tag[i] == POTRACE_CURVETO) {
1092       convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
1093     } else {
1094       convc[i] = 0;
1095     }
1096   }
1097 
1098   /* pre-calculate areas */
1099   area = 0.0;
1100   areac[0] = 0.0;
1101   p0 = pp->curve.vertex[0];
1102   for (i=0; i<m; i++) {
1103     i1 = mod(i+1, m);
1104     if (pp->curve.tag[i1] == POTRACE_CURVETO) {
1105       alpha = pp->curve.alpha[i1];
1106       area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
1107       area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
1108     }
1109     areac[i+1] = area;
1110   }
1111 
1112   pt[0] = -1;
1113   pen[0] = 0;
1114   len[0] = 0;
1115 
1116   /* Fixme: we always start from a fixed point -- should find the best
1117      curve cyclically */
1118 
1119   for (j=1; j<=m; j++) {
1120     /* calculate best path from 0 to j */
1121     pt[j] = j-1;
1122     pen[j] = pen[j-1];
1123     len[j] = len[j-1]+1;
1124 
1125     for (i=j-2; i>=0; i--) {
1126       r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
1127       if (r) {
1128 	break;
1129       }
1130       if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
1131 	pt[j] = i;
1132 	pen[j] = pen[i] + o.pen;
1133 	len[j] = len[i] + 1;
1134 	opt[j] = o;
1135       }
1136     }
1137   }
1138   om = len[m];
1139   r = privcurve_init(&pp->ocurve, om);
1140   if (r) {
1141     goto calloc_error;
1142   }
1143   SAFE_CALLOC(s, om, double);
1144   SAFE_CALLOC(t, om, double);
1145 
1146   j = m;
1147   for (i=om-1; i>=0; i--) {
1148     if (pt[j]==j-1) {
1149       pp->ocurve.tag[i]     = pp->curve.tag[mod(j,m)];
1150       pp->ocurve.c[i][0]    = pp->curve.c[mod(j,m)][0];
1151       pp->ocurve.c[i][1]    = pp->curve.c[mod(j,m)][1];
1152       pp->ocurve.c[i][2]    = pp->curve.c[mod(j,m)][2];
1153       pp->ocurve.vertex[i]  = pp->curve.vertex[mod(j,m)];
1154       pp->ocurve.alpha[i]   = pp->curve.alpha[mod(j,m)];
1155       pp->ocurve.alpha0[i]  = pp->curve.alpha0[mod(j,m)];
1156       pp->ocurve.beta[i]    = pp->curve.beta[mod(j,m)];
1157       s[i] = t[i] = 1.0;
1158     } else {
1159       pp->ocurve.tag[i] = POTRACE_CURVETO;
1160       pp->ocurve.c[i][0] = opt[j].c[0];
1161       pp->ocurve.c[i][1] = opt[j].c[1];
1162       pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
1163       pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
1164       pp->ocurve.alpha[i] = opt[j].alpha;
1165       pp->ocurve.alpha0[i] = opt[j].alpha;
1166       s[i] = opt[j].s;
1167       t[i] = opt[j].t;
1168     }
1169     j = pt[j];
1170   }
1171 
1172   /* calculate beta parameters */
1173   for (i=0; i<om; i++) {
1174     i1 = mod(i+1,om);
1175     pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
1176   }
1177   pp->ocurve.alphacurve = 1;
1178 
1179   free(pt);
1180   free(pen);
1181   free(len);
1182   free(opt);
1183   free(s);
1184   free(t);
1185   free(convc);
1186   free(areac);
1187   return 0;
1188 
1189  calloc_error:
1190   free(pt);
1191   free(pen);
1192   free(len);
1193   free(opt);
1194   free(s);
1195   free(t);
1196   free(convc);
1197   free(areac);
1198   return 1;
1199 }
1200 
1201 /* ---------------------------------------------------------------------- */
1202 
1203 #define TRY(x) if (x) goto try_error
1204 
1205 /* return 0 on success, 1 on error with errno set. */
process_path(path_t * plist,const potrace_param_t * param,progress_t * progress)1206 int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress) {
1207   path_t *p;
1208   double nn = 0, cn = 0;
1209 
1210   if (progress->callback) {
1211     /* precompute task size for progress estimates */
1212     nn = 0;
1213     list_forall (p, plist) {
1214       nn += p->priv->len;
1215     }
1216     cn = 0;
1217   }
1218 
1219   /* call downstream function with each path */
1220   list_forall (p, plist) {
1221     TRY(calc_sums(p->priv));
1222     TRY(calc_lon(p->priv));
1223     TRY(bestpolygon(p->priv));
1224     TRY(adjust_vertices(p->priv));
1225     if (p->sign == '-') {   /* reverse orientation of negative paths */
1226       reverse(&p->priv->curve);
1227     }
1228     smooth(&p->priv->curve, param->alphamax);
1229     if (param->opticurve) {
1230       TRY(opticurve(p->priv, param->opttolerance));
1231       p->priv->fcurve = &p->priv->ocurve;
1232     } else {
1233       p->priv->fcurve = &p->priv->curve;
1234     }
1235     privcurve_to_curve(p->priv->fcurve, &p->curve);
1236 
1237     if (progress->callback) {
1238       cn += p->priv->len;
1239       progress_update(cn/nn, progress);
1240     }
1241   }
1242 
1243   progress_update(1.0, progress);
1244 
1245   return 0;
1246 
1247  try_error:
1248   return 1;
1249 }
1250