File indexing completed on 2024-12-22 04:04:15
0001 /* Copyright (C) 2001-2019 Peter Selinger. 0002 This file is part of Potrace. It is free software and it is covered 0003 by the GNU General Public License. See the file COPYING for details. */ 0004 0005 /* transform jaggy paths into smooth curves */ 0006 0007 #ifdef HAVE_CONFIG_H 0008 #include <config.h> 0009 #endif 0010 0011 #include <stdio.h> 0012 #include <math.h> 0013 #include <stdlib.h> 0014 #include <string.h> 0015 0016 #include "potracelib.h" 0017 #include "curve.h" 0018 #include "lists.h" 0019 #include "auxiliary.h" 0020 #include "trace.h" 0021 #include "progress.h" 0022 0023 #define INFTY 10000000 /* it suffices that this is longer than any 0024 path; it need not be really infinite */ 0025 #define COS179 -0.999847695156 /* the cosine of 179 degrees */ 0026 0027 /* ---------------------------------------------------------------------- */ 0028 #define SAFE_CALLOC(var, n, typ) \ 0029 if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error 0030 0031 /* ---------------------------------------------------------------------- */ 0032 /* auxiliary functions */ 0033 0034 /* return a direction that is 90 degrees counterclockwise from p2-p0, 0035 but then restricted to one of the major wind directions (n, nw, w, etc) */ 0036 static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) { 0037 point_t r; 0038 0039 r.y = sign(p2.x-p0.x); 0040 r.x = -sign(p2.y-p0.y); 0041 0042 return r; 0043 } 0044 0045 /* return (p1-p0)x(p2-p0), the area of the parallelogram */ 0046 static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) { 0047 double x1, y1, x2, y2; 0048 0049 x1 = p1.x-p0.x; 0050 y1 = p1.y-p0.y; 0051 x2 = p2.x-p0.x; 0052 y2 = p2.y-p0.y; 0053 0054 return x1*y2 - x2*y1; 0055 } 0056 0057 /* ddenom/dpara have the property that the square of radius 1 centered 0058 at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */ 0059 static inline double ddenom(dpoint_t p0, dpoint_t p2) { 0060 point_t r = dorth_infty(p0, p2); 0061 0062 return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y); 0063 } 0064 0065 /* return 1 if a <= b < c < a, in a cyclic sense (mod n) */ 0066 static inline int cyclic(int a, int b, int c) { 0067 if (a<=c) { 0068 return (a<=b && b<c); 0069 } else { 0070 return (a<=b || b<c); 0071 } 0072 } 0073 0074 /* determine the center and slope of the line i..j. Assume i<j. Needs 0075 "sum" components of p to be set. */ 0076 static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) { 0077 /* assume i<j */ 0078 0079 int n = pp->len; 0080 sums_t *sums = pp->sums; 0081 0082 double x, y, x2, xy, y2; 0083 double k; 0084 double a, b, c, lambda2, l; 0085 int r=0; /* rotations from i to j */ 0086 0087 while (j>=n) { 0088 j-=n; 0089 r+=1; 0090 } 0091 while (i>=n) { 0092 i-=n; 0093 r-=1; 0094 } 0095 while (j<0) { 0096 j+=n; 0097 r-=1; 0098 } 0099 while (i<0) { 0100 i+=n; 0101 r+=1; 0102 } 0103 0104 x = sums[j+1].x-sums[i].x+r*sums[n].x; 0105 y = sums[j+1].y-sums[i].y+r*sums[n].y; 0106 x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2; 0107 xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy; 0108 y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2; 0109 k = j+1-i+r*n; 0110 0111 ctr->x = x/k; 0112 ctr->y = y/k; 0113 0114 a = (x2-(double)x*x/k)/k; 0115 b = (xy-(double)x*y/k)/k; 0116 c = (y2-(double)y*y/k)/k; 0117 0118 lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */ 0119 0120 /* now find e.vector for lambda2 */ 0121 a -= lambda2; 0122 c -= lambda2; 0123 0124 if (fabs(a) >= fabs(c)) { 0125 l = sqrt(a*a+b*b); 0126 if (l!=0) { 0127 dir->x = -b/l; 0128 dir->y = a/l; 0129 } 0130 } else { 0131 l = sqrt(c*c+b*b); 0132 if (l!=0) { 0133 dir->x = -c/l; 0134 dir->y = b/l; 0135 } 0136 } 0137 if (l==0) { 0138 dir->x = dir->y = 0; /* sometimes this can happen when k=4: 0139 the two eigenvalues coincide */ 0140 } 0141 } 0142 0143 /* the type of (affine) quadratic forms, represented as symmetric 3x3 0144 matrices. The value of the quadratic form at a vector (x,y) is v^t 0145 Q v, where v = (x,y,1)^t. */ 0146 typedef double quadform_t[3][3]; 0147 0148 /* Apply quadratic form Q to vector w = (w.x,w.y) */ 0149 static inline double quadform(quadform_t Q, dpoint_t w) { 0150 double v[3]; 0151 int i, j; 0152 double sum; 0153 0154 v[0] = w.x; 0155 v[1] = w.y; 0156 v[2] = 1; 0157 sum = 0.0; 0158 0159 for (i=0; i<3; i++) { 0160 for (j=0; j<3; j++) { 0161 sum += v[i] * Q[i][j] * v[j]; 0162 } 0163 } 0164 return sum; 0165 } 0166 0167 /* calculate p1 x p2 */ 0168 static inline int xprod(point_t p1, point_t p2) { 0169 return p1.x*p2.y - p1.y*p2.x; 0170 } 0171 0172 /* calculate (p1-p0)x(p3-p2) */ 0173 static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { 0174 double x1, y1, x2, y2; 0175 0176 x1 = p1.x - p0.x; 0177 y1 = p1.y - p0.y; 0178 x2 = p3.x - p2.x; 0179 y2 = p3.y - p2.y; 0180 0181 return x1*y2 - x2*y1; 0182 } 0183 0184 /* calculate (p1-p0)*(p2-p0) */ 0185 static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) { 0186 double x1, y1, x2, y2; 0187 0188 x1 = p1.x - p0.x; 0189 y1 = p1.y - p0.y; 0190 x2 = p2.x - p0.x; 0191 y2 = p2.y - p0.y; 0192 0193 return x1*x2 + y1*y2; 0194 } 0195 0196 /* calculate (p1-p0)*(p3-p2) */ 0197 static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { 0198 double x1, y1, x2, y2; 0199 0200 x1 = p1.x - p0.x; 0201 y1 = p1.y - p0.y; 0202 x2 = p3.x - p2.x; 0203 y2 = p3.y - p2.y; 0204 0205 return x1*x2 + y1*y2; 0206 } 0207 0208 /* calculate distance between two points */ 0209 static inline double ddist(dpoint_t p, dpoint_t q) { 0210 return sqrt(sq(p.x-q.x)+sq(p.y-q.y)); 0211 } 0212 0213 /* calculate point of a bezier curve */ 0214 static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) { 0215 double s = 1-t; 0216 dpoint_t res; 0217 0218 /* Note: a good optimizing compiler (such as gcc-3) reduces the 0219 following to 16 multiplications, using common subexpression 0220 elimination. */ 0221 0222 res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x; 0223 res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y; 0224 0225 return res; 0226 } 0227 0228 /* calculate the point t in [0..1] on the (convex) bezier curve 0229 (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no 0230 solution in [0..1]. */ 0231 static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) { 0232 double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */ 0233 double a, b, c; /* a t^2 + b t + c = 0 */ 0234 double d, s, r1, r2; 0235 0236 A = cprod(p0, p1, q0, q1); 0237 B = cprod(p1, p2, q0, q1); 0238 C = cprod(p2, p3, q0, q1); 0239 0240 a = A - 2*B + C; 0241 b = -2*A + 2*B; 0242 c = A; 0243 0244 d = b*b - 4*a*c; 0245 0246 if (a==0 || d<0) { 0247 return -1.0; 0248 } 0249 0250 s = sqrt(d); 0251 0252 r1 = (-b + s) / (2 * a); 0253 r2 = (-b - s) / (2 * a); 0254 0255 if (r1 >= 0 && r1 <= 1) { 0256 return r1; 0257 } else if (r2 >= 0 && r2 <= 1) { 0258 return r2; 0259 } else { 0260 return -1.0; 0261 } 0262 } 0263 0264 /* ---------------------------------------------------------------------- */ 0265 /* Preparation: fill in the sum* fields of a path (used for later 0266 rapid summing). Return 0 on success, 1 with errno set on 0267 failure. */ 0268 static int calc_sums(privpath_t *pp) { 0269 int i, x, y; 0270 int n = pp->len; 0271 0272 SAFE_CALLOC(pp->sums, pp->len+1, sums_t); 0273 0274 /* origin */ 0275 pp->x0 = pp->pt[0].x; 0276 pp->y0 = pp->pt[0].y; 0277 0278 /* preparatory computation for later fast summing */ 0279 pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0; 0280 for (i=0; i<n; i++) { 0281 x = pp->pt[i].x - pp->x0; 0282 y = pp->pt[i].y - pp->y0; 0283 pp->sums[i+1].x = pp->sums[i].x + x; 0284 pp->sums[i+1].y = pp->sums[i].y + y; 0285 pp->sums[i+1].x2 = pp->sums[i].x2 + (double)x*x; 0286 pp->sums[i+1].xy = pp->sums[i].xy + (double)x*y; 0287 pp->sums[i+1].y2 = pp->sums[i].y2 + (double)y*y; 0288 } 0289 return 0; 0290 0291 calloc_error: 0292 return 1; 0293 } 0294 0295 /* ---------------------------------------------------------------------- */ 0296 /* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the 0297 "lon" component of a path object (based on pt/len). For each i, 0298 lon[i] is the furthest index such that a straight line can be drawn 0299 from i to lon[i]. Return 1 on error with errno set, else 0. */ 0300 0301 /* this algorithm depends on the fact that the existence of straight 0302 subpaths is a triplewise property. I.e., there exists a straight 0303 line through squares i0,...,in iff there exists a straight line 0304 through i,j,k, for all i0<=i<j<k<=in. (Proof?) */ 0305 0306 /* this implementation of calc_lon is O(n^2). It replaces an older 0307 O(n^3) version. A "constraint" means that future points must 0308 satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1], 0309 cur) <= 0. */ 0310 0311 /* Remark for Potrace 1.1: the current implementation of calc_lon is 0312 more complex than the implementation found in Potrace 1.0, but it 0313 is considerably faster. The introduction of the "nc" data structure 0314 means that we only have to test the constraints for "corner" 0315 points. On a typical input file, this speeds up the calc_lon 0316 function by a factor of 31.2, thereby decreasing its time share 0317 within the overall Potrace algorithm from 72.6% to 7.82%, and 0318 speeding up the overall algorithm by a factor of 3.36. On another 0319 input file, calc_lon was sped up by a factor of 6.7, decreasing its 0320 time share from 51.4% to 13.61%, and speeding up the overall 0321 algorithm by a factor of 1.78. In any case, the savings are 0322 substantial. */ 0323 0324 /* returns 0 on success, 1 on error with errno set */ 0325 static int calc_lon(privpath_t *pp) { 0326 point_t *pt = pp->pt; 0327 int n = pp->len; 0328 int i, j, k, k1; 0329 int ct[4], dir; 0330 point_t constraint[2]; 0331 point_t cur; 0332 point_t off; 0333 int *pivk = NULL; /* pivk[n] */ 0334 int *nc = NULL; /* nc[n]: next corner */ 0335 point_t dk; /* direction of k-k1 */ 0336 int a, b, c, d; 0337 0338 SAFE_CALLOC(pivk, n, int); 0339 SAFE_CALLOC(nc, n, int); 0340 0341 /* initialize the nc data structure. Point from each point to the 0342 furthest future point to which it is connected by a vertical or 0343 horizontal segment. We take advantage of the fact that there is 0344 always a direction change at 0 (due to the path decomposition 0345 algorithm). But even if this were not so, there is no harm, as 0346 in practice, correctness does not depend on the word "furthest" 0347 above. */ 0348 k = 0; 0349 for (i=n-1; i>=0; i--) { 0350 if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) { 0351 k = i+1; /* necessarily i<n-1 in this case */ 0352 } 0353 nc[i] = k; 0354 } 0355 0356 SAFE_CALLOC(pp->lon, n, int); 0357 0358 /* determine pivot points: for each i, let pivk[i] be the furthest k 0359 such that all j with i<j<k lie on a line connecting i,k. */ 0360 0361 for (i=n-1; i>=0; i--) { 0362 ct[0] = ct[1] = ct[2] = ct[3] = 0; 0363 0364 /* keep track of "directions" that have occurred */ 0365 dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2; 0366 ct[dir]++; 0367 0368 constraint[0].x = 0; 0369 constraint[0].y = 0; 0370 constraint[1].x = 0; 0371 constraint[1].y = 0; 0372 0373 /* find the next k such that no straight line from i to k */ 0374 k = nc[i]; 0375 k1 = i; 0376 while (1) { 0377 0378 dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2; 0379 ct[dir]++; 0380 0381 /* if all four "directions" have occurred, cut this path */ 0382 if (ct[0] && ct[1] && ct[2] && ct[3]) { 0383 pivk[i] = k1; 0384 goto foundk; 0385 } 0386 0387 cur.x = pt[k].x - pt[i].x; 0388 cur.y = pt[k].y - pt[i].y; 0389 0390 /* see if current constraint is violated */ 0391 if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) { 0392 goto constraint_viol; 0393 } 0394 0395 /* else, update constraint */ 0396 if (abs(cur.x) <= 1 && abs(cur.y) <= 1) { 0397 /* no constraint */ 0398 } else { 0399 off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1); 0400 off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1); 0401 if (xprod(constraint[0], off) >= 0) { 0402 constraint[0] = off; 0403 } 0404 off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1); 0405 off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1); 0406 if (xprod(constraint[1], off) <= 0) { 0407 constraint[1] = off; 0408 } 0409 } 0410 k1 = k; 0411 k = nc[k1]; 0412 if (!cyclic(k,i,k1)) { 0413 break; 0414 } 0415 } 0416 constraint_viol: 0417 /* k1 was the last "corner" satisfying the current constraint, and 0418 k is the first one violating it. We now need to find the last 0419 point along k1..k which satisfied the constraint. */ 0420 dk.x = sign(pt[k].x-pt[k1].x); 0421 dk.y = sign(pt[k].y-pt[k1].y); 0422 cur.x = pt[k1].x - pt[i].x; 0423 cur.y = pt[k1].y - pt[i].y; 0424 /* find largest integer j such that xprod(constraint[0], cur+j*dk) 0425 >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity 0426 of xprod. */ 0427 a = xprod(constraint[0], cur); 0428 b = xprod(constraint[0], dk); 0429 c = xprod(constraint[1], cur); 0430 d = xprod(constraint[1], dk); 0431 /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This 0432 can be solved with integer arithmetic. */ 0433 j = INFTY; 0434 if (b<0) { 0435 j = floordiv(a,-b); 0436 } 0437 if (d>0) { 0438 j = min(j, floordiv(-c,d)); 0439 } 0440 pivk[i] = mod(k1+j,n); 0441 foundk: 0442 ; 0443 } /* for i */ 0444 0445 /* clean up: for each i, let lon[i] be the largest k such that for 0446 all i' with i<=i'<k, i'<k<=pivk[i']. */ 0447 0448 j=pivk[n-1]; 0449 pp->lon[n-1]=j; 0450 for (i=n-2; i>=0; i--) { 0451 if (cyclic(i+1,pivk[i],j)) { 0452 j=pivk[i]; 0453 } 0454 pp->lon[i]=j; 0455 } 0456 0457 for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) { 0458 pp->lon[i] = j; 0459 } 0460 0461 free(pivk); 0462 free(nc); 0463 return 0; 0464 0465 calloc_error: 0466 free(pivk); 0467 free(nc); 0468 return 1; 0469 } 0470 0471 0472 /* ---------------------------------------------------------------------- */ 0473 /* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */ 0474 0475 /* Auxiliary function: calculate the penalty of an edge from i to j in 0476 the given path. This needs the "lon" and "sum*" data. */ 0477 0478 static double penalty3(privpath_t *pp, int i, int j) { 0479 int n = pp->len; 0480 point_t *pt = pp->pt; 0481 sums_t *sums = pp->sums; 0482 0483 /* assume 0<=i<j<=n */ 0484 double x, y, x2, xy, y2; 0485 double k; 0486 double a, b, c, s; 0487 double px, py, ex, ey; 0488 0489 int r = 0; /* rotations from i to j */ 0490 0491 if (j>=n) { 0492 j -= n; 0493 r = 1; 0494 } 0495 0496 /* critical inner loop: the "if" gives a 4.6 percent speedup */ 0497 if (r == 0) { 0498 x = sums[j+1].x - sums[i].x; 0499 y = sums[j+1].y - sums[i].y; 0500 x2 = sums[j+1].x2 - sums[i].x2; 0501 xy = sums[j+1].xy - sums[i].xy; 0502 y2 = sums[j+1].y2 - sums[i].y2; 0503 k = j+1 - i; 0504 } else { 0505 x = sums[j+1].x - sums[i].x + sums[n].x; 0506 y = sums[j+1].y - sums[i].y + sums[n].y; 0507 x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2; 0508 xy = sums[j+1].xy - sums[i].xy + sums[n].xy; 0509 y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2; 0510 k = j+1 - i + n; 0511 } 0512 0513 px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x; 0514 py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y; 0515 ey = (pt[j].x - pt[i].x); 0516 ex = -(pt[j].y - pt[i].y); 0517 0518 a = ((x2 - 2*x*px) / k + px*px); 0519 b = ((xy - x*py - y*px) / k + px*py); 0520 c = ((y2 - 2*y*py) / k + py*py); 0521 0522 s = ex*ex*a + 2*ex*ey*b + ey*ey*c; 0523 0524 return sqrt(s); 0525 } 0526 0527 /* find the optimal polygon. Fill in the m and po components. Return 1 0528 on failure with errno set, else 0. Non-cyclic version: assumes i=0 0529 is in the polygon. Fixme: implement cyclic version. */ 0530 static int bestpolygon(privpath_t *pp) 0531 { 0532 int i, j, m, k; 0533 int n = pp->len; 0534 double *pen = NULL; /* pen[n+1]: penalty vector */ 0535 int *prev = NULL; /* prev[n+1]: best path pointer vector */ 0536 int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */ 0537 int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */ 0538 int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */ 0539 int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */ 0540 double thispen; 0541 double best; 0542 int c; 0543 0544 SAFE_CALLOC(pen, n+1, double); 0545 SAFE_CALLOC(prev, n+1, int); 0546 SAFE_CALLOC(clip0, n, int); 0547 SAFE_CALLOC(clip1, n+1, int); 0548 SAFE_CALLOC(seg0, n+1, int); 0549 SAFE_CALLOC(seg1, n+1, int); 0550 0551 /* calculate clipped paths */ 0552 for (i=0; i<n; i++) { 0553 c = mod(pp->lon[mod(i-1,n)]-1,n); 0554 if (c == i) { 0555 c = mod(i+1,n); 0556 } 0557 if (c < i) { 0558 clip0[i] = n; 0559 } else { 0560 clip0[i] = c; 0561 } 0562 } 0563 0564 /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff 0565 clip1[j] <= i, for i,j=0..n. */ 0566 j = 1; 0567 for (i=0; i<n; i++) { 0568 while (j <= clip0[i]) { 0569 clip1[j] = i; 0570 j++; 0571 } 0572 } 0573 0574 /* calculate seg0[j] = longest path from 0 with j segments */ 0575 i = 0; 0576 for (j=0; i<n; j++) { 0577 seg0[j] = i; 0578 i = clip0[i]; 0579 } 0580 seg0[j] = n; 0581 m = j; 0582 0583 /* calculate seg1[j] = longest path to n with m-j segments */ 0584 i = n; 0585 for (j=m; j>0; j--) { 0586 seg1[j] = i; 0587 i = clip1[i]; 0588 } 0589 seg1[0] = 0; 0590 0591 /* now find the shortest path with m segments, based on penalty3 */ 0592 /* note: the outer 2 loops jointly have at most n iterations, thus 0593 the worst-case behavior here is quadratic. In practice, it is 0594 close to linear since the inner loop tends to be short. */ 0595 pen[0]=0; 0596 for (j=1; j<=m; j++) { 0597 for (i=seg1[j]; i<=seg0[j]; i++) { 0598 best = -1; 0599 for (k=seg0[j-1]; k>=clip1[i]; k--) { 0600 thispen = penalty3(pp, k, i) + pen[k]; 0601 if (best < 0 || thispen < best) { 0602 prev[i] = k; 0603 best = thispen; 0604 } 0605 } 0606 pen[i] = best; 0607 } 0608 } 0609 0610 pp->m = m; 0611 SAFE_CALLOC(pp->po, m, int); 0612 0613 /* read off shortest path */ 0614 for (i=n, j=m-1; i>0; j--) { 0615 i = prev[i]; 0616 pp->po[j] = i; 0617 } 0618 0619 free(pen); 0620 free(prev); 0621 free(clip0); 0622 free(clip1); 0623 free(seg0); 0624 free(seg1); 0625 return 0; 0626 0627 calloc_error: 0628 free(pen); 0629 free(prev); 0630 free(clip0); 0631 free(clip1); 0632 free(seg0); 0633 free(seg1); 0634 return 1; 0635 } 0636 0637 /* ---------------------------------------------------------------------- */ 0638 /* Stage 3: vertex adjustment (Sec. 2.3.1). */ 0639 0640 /* Adjust vertices of optimal polygon: calculate the intersection of 0641 the two "optimal" line segments, then move it into the unit square 0642 if it lies outside. Return 1 with errno set on error; 0 on 0643 success. */ 0644 0645 static int adjust_vertices(privpath_t *pp) { 0646 int m = pp->m; 0647 int *po = pp->po; 0648 int n = pp->len; 0649 point_t *pt = pp->pt; 0650 int x0 = pp->x0; 0651 int y0 = pp->y0; 0652 0653 dpoint_t *ctr = NULL; /* ctr[m] */ 0654 dpoint_t *dir = NULL; /* dir[m] */ 0655 quadform_t *q = NULL; /* q[m] */ 0656 double v[3]; 0657 double d; 0658 int i, j, k, l; 0659 dpoint_t s; 0660 int r; 0661 0662 SAFE_CALLOC(ctr, m, dpoint_t); 0663 SAFE_CALLOC(dir, m, dpoint_t); 0664 SAFE_CALLOC(q, m, quadform_t); 0665 0666 r = privcurve_init(&pp->curve, m); 0667 if (r) { 0668 goto calloc_error; 0669 } 0670 0671 /* calculate "optimal" point-slope representation for each line 0672 segment */ 0673 for (i=0; i<m; i++) { 0674 j = po[mod(i+1,m)]; 0675 j = mod(j-po[i],n)+po[i]; 0676 pointslope(pp, po[i], j, &ctr[i], &dir[i]); 0677 } 0678 0679 /* represent each line segment as a singular quadratic form; the 0680 distance of a point (x,y) from the line segment will be 0681 (x,y,1)Q(x,y,1)^t, where Q=q[i]. */ 0682 for (i=0; i<m; i++) { 0683 d = sq(dir[i].x) + sq(dir[i].y); 0684 if (d == 0.0) { 0685 for (j=0; j<3; j++) { 0686 for (k=0; k<3; k++) { 0687 q[i][j][k] = 0; 0688 } 0689 } 0690 } else { 0691 v[0] = dir[i].y; 0692 v[1] = -dir[i].x; 0693 v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x; 0694 for (l=0; l<3; l++) { 0695 for (k=0; k<3; k++) { 0696 q[i][l][k] = v[l] * v[k] / d; 0697 } 0698 } 0699 } 0700 } 0701 0702 /* now calculate the "intersections" of consecutive segments. 0703 Instead of using the actual intersection, we find the point 0704 within a given unit square which minimizes the square distance to 0705 the two lines. */ 0706 for (i=0; i<m; i++) { 0707 quadform_t Q; 0708 dpoint_t w; 0709 double dx, dy; 0710 double det; 0711 double min, cand; /* minimum and candidate for minimum of quad. form */ 0712 double xmin, ymin; /* coordinates of minimum */ 0713 int z; 0714 0715 /* let s be the vertex, in coordinates relative to x0/y0 */ 0716 s.x = pt[po[i]].x-x0; 0717 s.y = pt[po[i]].y-y0; 0718 0719 /* intersect segments i-1 and i */ 0720 0721 j = mod(i-1,m); 0722 0723 /* add quadratic forms */ 0724 for (l=0; l<3; l++) { 0725 for (k=0; k<3; k++) { 0726 Q[l][k] = q[j][l][k] + q[i][l][k]; 0727 } 0728 } 0729 0730 while(1) { 0731 /* minimize the quadratic form Q on the unit square */ 0732 /* find intersection */ 0733 0734 #ifdef HAVE_GCC_LOOP_BUG 0735 /* work around gcc bug #12243 */ 0736 free(NULL); 0737 #endif 0738 0739 det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0]; 0740 if (det != 0.0) { 0741 w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det; 0742 w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det; 0743 break; 0744 } 0745 0746 /* matrix is singular - lines are parallel. Add another, 0747 orthogonal axis, through the center of the unit square */ 0748 if (Q[0][0]>Q[1][1]) { 0749 v[0] = -Q[0][1]; 0750 v[1] = Q[0][0]; 0751 } else if (Q[1][1]) { 0752 v[0] = -Q[1][1]; 0753 v[1] = Q[1][0]; 0754 } else { 0755 v[0] = 1; 0756 v[1] = 0; 0757 } 0758 d = sq(v[0]) + sq(v[1]); 0759 v[2] = - v[1] * s.y - v[0] * s.x; 0760 for (l=0; l<3; l++) { 0761 for (k=0; k<3; k++) { 0762 Q[l][k] += v[l] * v[k] / d; 0763 } 0764 } 0765 } 0766 dx = fabs(w.x-s.x); 0767 dy = fabs(w.y-s.y); 0768 if (dx <= .5 && dy <= .5) { 0769 pp->curve.vertex[i].x = w.x+x0; 0770 pp->curve.vertex[i].y = w.y+y0; 0771 continue; 0772 } 0773 0774 /* the minimum was not in the unit square; now minimize quadratic 0775 on boundary of square */ 0776 min = quadform(Q, s); 0777 xmin = s.x; 0778 ymin = s.y; 0779 0780 if (Q[0][0] == 0.0) { 0781 goto fixx; 0782 } 0783 for (z=0; z<2; z++) { /* value of the y-coordinate */ 0784 w.y = s.y-0.5+z; 0785 w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0]; 0786 dx = fabs(w.x-s.x); 0787 cand = quadform(Q, w); 0788 if (dx <= .5 && cand < min) { 0789 min = cand; 0790 xmin = w.x; 0791 ymin = w.y; 0792 } 0793 } 0794 fixx: 0795 if (Q[1][1] == 0.0) { 0796 goto corners; 0797 } 0798 for (z=0; z<2; z++) { /* value of the x-coordinate */ 0799 w.x = s.x-0.5+z; 0800 w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1]; 0801 dy = fabs(w.y-s.y); 0802 cand = quadform(Q, w); 0803 if (dy <= .5 && cand < min) { 0804 min = cand; 0805 xmin = w.x; 0806 ymin = w.y; 0807 } 0808 } 0809 corners: 0810 /* check four corners */ 0811 for (l=0; l<2; l++) { 0812 for (k=0; k<2; k++) { 0813 w.x = s.x-0.5+l; 0814 w.y = s.y-0.5+k; 0815 cand = quadform(Q, w); 0816 if (cand < min) { 0817 min = cand; 0818 xmin = w.x; 0819 ymin = w.y; 0820 } 0821 } 0822 } 0823 0824 pp->curve.vertex[i].x = xmin + x0; 0825 pp->curve.vertex[i].y = ymin + y0; 0826 continue; 0827 } 0828 0829 free(ctr); 0830 free(dir); 0831 free(q); 0832 return 0; 0833 0834 calloc_error: 0835 free(ctr); 0836 free(dir); 0837 free(q); 0838 return 1; 0839 } 0840 0841 /* ---------------------------------------------------------------------- */ 0842 /* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */ 0843 0844 /* reverse orientation of a path */ 0845 static void reverse(privcurve_t *curve) { 0846 int m = curve->n; 0847 int i, j; 0848 dpoint_t tmp; 0849 0850 for (i=0, j=m-1; i<j; i++, j--) { 0851 tmp = curve->vertex[i]; 0852 curve->vertex[i] = curve->vertex[j]; 0853 curve->vertex[j] = tmp; 0854 } 0855 } 0856 0857 /* Always succeeds */ 0858 static void smooth(privcurve_t *curve, double alphamax) { 0859 int m = curve->n; 0860 0861 int i, j, k; 0862 double dd, denom, alpha; 0863 dpoint_t p2, p3, p4; 0864 0865 /* examine each vertex and find its best fit */ 0866 for (i=0; i<m; i++) { 0867 j = mod(i+1, m); 0868 k = mod(i+2, m); 0869 p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]); 0870 0871 denom = ddenom(curve->vertex[i], curve->vertex[k]); 0872 if (denom != 0.0) { 0873 dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom; 0874 dd = fabs(dd); 0875 alpha = dd>1 ? (1 - 1.0/dd) : 0; 0876 alpha = alpha / 0.75; 0877 } else { 0878 alpha = 4/3.0; 0879 } 0880 curve->alpha0[j] = alpha; /* remember "original" value of alpha */ 0881 0882 if (alpha >= alphamax) { /* pointed corner */ 0883 curve->tag[j] = POTRACE_CORNER; 0884 curve->c[j][1] = curve->vertex[j]; 0885 curve->c[j][2] = p4; 0886 } else { 0887 if (alpha < 0.55) { 0888 alpha = 0.55; 0889 } else if (alpha > 1) { 0890 alpha = 1; 0891 } 0892 p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]); 0893 p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]); 0894 curve->tag[j] = POTRACE_CURVETO; 0895 curve->c[j][0] = p2; 0896 curve->c[j][1] = p3; 0897 curve->c[j][2] = p4; 0898 } 0899 curve->alpha[j] = alpha; /* store the "cropped" value of alpha */ 0900 curve->beta[j] = 0.5; 0901 } 0902 curve->alphacurve = 1; 0903 0904 return; 0905 } 0906 0907 /* ---------------------------------------------------------------------- */ 0908 /* Stage 5: Curve optimization (Sec. 2.4) */ 0909 0910 /* a private type for the result of opti_penalty */ 0911 struct opti_s { 0912 double pen; /* penalty */ 0913 dpoint_t c[2]; /* curve parameters */ 0914 double t, s; /* curve parameters */ 0915 double alpha; /* curve parameter */ 0916 }; 0917 typedef struct opti_s opti_t; 0918 0919 /* calculate best fit from i+.5 to j+.5. Assume i<j (cyclically). 0920 Return 0 and set badness and parameters (alpha, beta), if 0921 possible. Return 1 if impossible. */ 0922 static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) { 0923 int m = pp->curve.n; 0924 int k, k1, k2, conv, i1; 0925 double area, alpha, d, d1, d2; 0926 dpoint_t p0, p1, p2, p3, pt; 0927 double A, R, A1, A2, A3, A4; 0928 double s, t; 0929 0930 /* check convexity, corner-freeness, and maximum bend < 179 degrees */ 0931 0932 if (i==j) { /* sanity - a full loop can never be an opticurve */ 0933 return 1; 0934 } 0935 0936 k = i; 0937 i1 = mod(i+1, m); 0938 k1 = mod(k+1, m); 0939 conv = convc[k1]; 0940 if (conv == 0) { 0941 return 1; 0942 } 0943 d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]); 0944 for (k=k1; k!=j; k=k1) { 0945 k1 = mod(k+1, m); 0946 k2 = mod(k+2, m); 0947 if (convc[k1] != conv) { 0948 return 1; 0949 } 0950 if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) { 0951 return 1; 0952 } 0953 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) { 0954 return 1; 0955 } 0956 } 0957 0958 /* the curve we're working in: */ 0959 p0 = pp->curve.c[mod(i,m)][2]; 0960 p1 = pp->curve.vertex[mod(i+1,m)]; 0961 p2 = pp->curve.vertex[mod(j,m)]; 0962 p3 = pp->curve.c[mod(j,m)][2]; 0963 0964 /* determine its area */ 0965 area = areac[j] - areac[i]; 0966 area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2; 0967 if (i>=j) { 0968 area += areac[m]; 0969 } 0970 0971 /* find intersection o of p0p1 and p2p3. Let t,s such that o = 0972 interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the 0973 triangle (p0,o,p3). */ 0974 0975 A1 = dpara(p0, p1, p2); 0976 A2 = dpara(p0, p1, p3); 0977 A3 = dpara(p0, p2, p3); 0978 /* A4 = dpara(p1, p2, p3); */ 0979 A4 = A1+A3-A2; 0980 0981 if (A2 == A1) { /* this should never happen */ 0982 return 1; 0983 } 0984 0985 t = A3/(A3-A4); 0986 s = A2/(A2-A1); 0987 A = A2 * t / 2.0; 0988 0989 if (A == 0.0) { /* this should never happen */ 0990 return 1; 0991 } 0992 0993 R = area / A; /* relative area */ 0994 alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */ 0995 0996 res->c[0] = interval(t * alpha, p0, p1); 0997 res->c[1] = interval(s * alpha, p3, p2); 0998 res->alpha = alpha; 0999 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. */ 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. */ 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 }