|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 00015 #include <stdlib.h> 00016 #include <stdio.h> 00017 #include <setjmp.h> 00018 #ifdef HAVE_MALLOC_H 00019 #include <malloc.h> 00020 #endif 00021 #include <math.h> 00022 #include "pathutil.h" 00023 #include "solvers.h" 00024 00025 #ifdef DMALLOC 00026 #include "dmalloc.h" 00027 #endif 00028 00029 #define EPSILON1 1E-3 00030 #define EPSILON2 1E-6 00031 00032 #define ABS(a) ((a) >= 0 ? (a) : -(a)) 00033 00034 typedef struct tna_t { 00035 double t; 00036 Ppoint_t a[2]; 00037 } tna_t; 00038 00039 #define prerror(msg) \ 00040 fprintf (stderr, "libpath/%s:%d: %s\n", __FILE__, __LINE__, (msg)) 00041 00042 #define DISTSQ(a, b) ( \ 00043 (((a).x - (b).x) * ((a).x - (b).x)) + (((a).y - (b).y) * ((a).y - (b).y)) \ 00044 ) 00045 00046 #define POINTSIZE sizeof (Ppoint_t) 00047 00048 #define LT(pa, pbp) ((pa.y > pbp->y) || ((pa.y == pbp->y) && (pa.x < pbp->x))) 00049 #define GT(pa, pbp) ((pa.y < pbp->y) || ((pa.y == pbp->y) && (pa.x > pbp->x))) 00050 00051 typedef struct p2e_t { 00052 Ppoint_t *pp; 00053 Pedge_t *ep; 00054 } p2e_t; 00055 00056 typedef struct elist_t { 00057 Pedge_t *ep; 00058 struct elist_t *next, *prev; 00059 } elist_t; 00060 00061 static jmp_buf jbuf; 00062 00063 #if 0 00064 static p2e_t *p2es; 00065 static int p2en; 00066 #endif 00067 00068 #if 0 00069 static elist_t *elist; 00070 #endif 00071 00072 static Ppoint_t *ops; 00073 static int opn, opl; 00074 00075 static int reallyroutespline(Pedge_t *, int, 00076 Ppoint_t *, int, Ppoint_t, Ppoint_t); 00077 static int mkspline(Ppoint_t *, int, tna_t *, Ppoint_t, Ppoint_t, 00078 Ppoint_t *, Ppoint_t *, Ppoint_t *, Ppoint_t *); 00079 static int splinefits(Pedge_t *, int, Ppoint_t, Pvector_t, Ppoint_t, 00080 Pvector_t, Ppoint_t *, int); 00081 static int splineisinside(Pedge_t *, int, Ppoint_t *); 00082 static int splineintersectsline(Ppoint_t *, Ppoint_t *, double *); 00083 static void points2coeff(double, double, double, double, double *); 00084 static void addroot(double, double *, int *); 00085 00086 static Pvector_t normv(Pvector_t); 00087 00088 static void growops(int); 00089 00090 static Ppoint_t add(Ppoint_t, Ppoint_t); 00091 static Ppoint_t sub(Ppoint_t, Ppoint_t); 00092 static double dist(Ppoint_t, Ppoint_t); 00093 static Ppoint_t scale(Ppoint_t, double); 00094 static double dot(Ppoint_t, Ppoint_t); 00095 static double B0(double t); 00096 static double B1(double t); 00097 static double B2(double t); 00098 static double B3(double t); 00099 static double B01(double t); 00100 static double B23(double t); 00101 #if 0 00102 static int cmpp2efunc(const void *, const void *); 00103 00104 static void listdelete(Pedge_t *); 00105 static void listreplace(Pedge_t *, Pedge_t *); 00106 static void listinsert(Pedge_t *, Ppoint_t); 00107 #endif 00108 00109 /* Proutespline: 00110 * Given a set of edgen line segments edges as obstacles, a template 00111 * path input, and endpoint vectors evs, construct a spline fitting the 00112 * input and endpoing vectors, and return in output. 00113 * Return 0 on success and -1 on failure, including no memory. 00114 */ 00115 int Proutespline(Pedge_t * edges, int edgen, Ppolyline_t input, 00116 Ppoint_t * evs, Ppolyline_t * output) 00117 { 00118 #if 0 00119 Ppoint_t p0, p1, p2, p3; 00120 Ppoint_t *pp; 00121 Pvector_t v1, v2, v12, v23; 00122 int ipi, opi; 00123 int ei, p2ei; 00124 Pedge_t *e0p, *e1p; 00125 #endif 00126 Ppoint_t *inps; 00127 int inpn; 00128 00129 /* unpack into previous format rather than modify legacy code */ 00130 inps = input.ps; 00131 inpn = input.pn; 00132 00133 #if 0 00134 if (!(p2es = (p2e_t *) malloc(sizeof(p2e_t) * (p2en = edgen * 2)))) { 00135 prerror("cannot malloc p2es"); 00136 return -1; 00137 } 00138 for (ei = 0, p2ei = 0; ei < edgen; ei++) { 00139 if (edges[ei].a.x == edges[ei].b.x 00140 && edges[ei].a.y == edges[ei].b.y) 00141 continue; 00142 p2es[p2ei].pp = &edges[ei].a; 00143 p2es[p2ei++].ep = &edges[ei]; 00144 p2es[p2ei].pp = &edges[ei].b; 00145 p2es[p2ei++].ep = &edges[ei]; 00146 } 00147 p2en = p2ei; 00148 qsort(p2es, p2en, sizeof(p2e_t), cmpp2efunc); 00149 elist = NULL; 00150 for (p2ei = 0; p2ei < p2en; p2ei += 2) { 00151 pp = p2es[p2ei].pp; 00152 #if DEBUG >= 1 00153 fprintf(stderr, "point: %d %lf %lf\n", p2ei, pp->x, pp->y); 00154 #endif 00155 e0p = p2es[p2ei].ep; 00156 e1p = p2es[p2ei + 1].ep; 00157 p0 = (&e0p->a == p2es[p2ei].pp) ? e0p->b : e0p->a; 00158 p1 = (&e0p->a == p2es[p2ei + 1].pp) ? e1p->b : e1p->a; 00159 if (LT(p0, pp) && LT(p1, pp)) { 00160 listdelete(e0p), listdelete(e1p); 00161 } else if (GT(p0, pp) && GT(p1, pp)) { 00162 listinsert(e0p, *pp), listinsert(e1p, *pp); 00163 } else { 00164 if (LT(p0, pp)) 00165 listreplace(e0p, e1p); 00166 else 00167 listreplace(e1p, e0p); 00168 } 00169 } 00170 #endif 00171 if (setjmp(jbuf)) 00172 return -1; 00173 00174 /* generate the splines */ 00175 evs[0] = normv(evs[0]); 00176 evs[1] = normv(evs[1]); 00177 opl = 0; 00178 growops(4); 00179 ops[opl++] = inps[0]; 00180 if (reallyroutespline(edges, edgen, inps, inpn, evs[0], evs[1]) == -1) 00181 return -1; 00182 output->pn = opl; 00183 output->ps = ops; 00184 00185 #if 0 00186 fprintf(stderr, "edge\na\nb\n"); 00187 fprintf(stderr, "points\n%d\n", inpn); 00188 for (ipi = 0; ipi < inpn; ipi++) 00189 fprintf(stderr, "%f %f\n", inps[ipi].x, inps[ipi].y); 00190 fprintf(stderr, "splpoints\n%d\n", opl); 00191 for (opi = 0; opi < opl; opi++) 00192 fprintf(stderr, "%f %f\n", ops[opi].x, ops[opi].y); 00193 #endif 00194 00195 return 0; 00196 } 00197 00198 static int reallyroutespline(Pedge_t * edges, int edgen, 00199 Ppoint_t * inps, int inpn, Ppoint_t ev0, 00200 Ppoint_t ev1) 00201 { 00202 Ppoint_t p1, p2, cp1, cp2, p; 00203 Pvector_t v1, v2, splitv, splitv1, splitv2; 00204 double maxd, d, t; 00205 int maxi, i, spliti; 00206 00207 static tna_t *tnas; 00208 static int tnan; 00209 00210 if (tnan < inpn) { 00211 if (!tnas) { 00212 if (!(tnas = malloc(sizeof(tna_t) * inpn))) 00213 return -1; 00214 } else { 00215 if (!(tnas = realloc(tnas, sizeof(tna_t) * inpn))) 00216 return -1; 00217 } 00218 tnan = inpn; 00219 } 00220 tnas[0].t = 0; 00221 for (i = 1; i < inpn; i++) 00222 tnas[i].t = tnas[i - 1].t + dist(inps[i], inps[i - 1]); 00223 for (i = 1; i < inpn; i++) 00224 tnas[i].t /= tnas[inpn - 1].t; 00225 for (i = 0; i < inpn; i++) { 00226 tnas[i].a[0] = scale(ev0, B1(tnas[i].t)); 00227 tnas[i].a[1] = scale(ev1, B2(tnas[i].t)); 00228 } 00229 if (mkspline(inps, inpn, tnas, ev0, ev1, &p1, &v1, &p2, &v2) == -1) 00230 return -1; 00231 if (splinefits(edges, edgen, p1, v1, p2, v2, inps, inpn)) 00232 return 0; 00233 cp1 = add(p1, scale(v1, 1 / 3.0)); 00234 cp2 = sub(p2, scale(v2, 1 / 3.0)); 00235 for (maxd = -1, maxi = -1, i = 1; i < inpn - 1; i++) { 00236 t = tnas[i].t; 00237 p.x = B0(t) * p1.x + B1(t) * cp1.x + B2(t) * cp2.x + B3(t) * p2.x; 00238 p.y = B0(t) * p1.y + B1(t) * cp1.y + B2(t) * cp2.y + B3(t) * p2.y; 00239 if ((d = dist(p, inps[i])) > maxd) 00240 maxd = d, maxi = i; 00241 } 00242 spliti = maxi; 00243 splitv1 = normv(sub(inps[spliti], inps[spliti - 1])); 00244 splitv2 = normv(sub(inps[spliti + 1], inps[spliti])); 00245 splitv = normv(add(splitv1, splitv2)); 00246 reallyroutespline(edges, edgen, inps, spliti + 1, ev0, splitv); 00247 reallyroutespline(edges, edgen, &inps[spliti], inpn - spliti, splitv, 00248 ev1); 00249 return 0; 00250 } 00251 00252 static int mkspline(Ppoint_t * inps, int inpn, tna_t * tnas, Ppoint_t ev0, 00253 Ppoint_t ev1, Ppoint_t * sp0, Ppoint_t * sv0, 00254 Ppoint_t * sp1, Ppoint_t * sv1) 00255 { 00256 Ppoint_t tmp; 00257 double c[2][2], x[2], det01, det0X, detX1; 00258 double d01, scale0, scale3; 00259 int i; 00260 00261 scale0 = scale3 = 0.0; 00262 c[0][0] = c[0][1] = c[1][0] = c[1][1] = 0.0; 00263 x[0] = x[1] = 0.0; 00264 for (i = 0; i < inpn; i++) { 00265 c[0][0] += dot(tnas[i].a[0], tnas[i].a[0]); 00266 c[0][1] += dot(tnas[i].a[0], tnas[i].a[1]); 00267 c[1][0] = c[0][1]; 00268 c[1][1] += dot(tnas[i].a[1], tnas[i].a[1]); 00269 tmp = sub(inps[i], add(scale(inps[0], B01(tnas[i].t)), 00270 scale(inps[inpn - 1], B23(tnas[i].t)))); 00271 x[0] += dot(tnas[i].a[0], tmp); 00272 x[1] += dot(tnas[i].a[1], tmp); 00273 } 00274 det01 = c[0][0] * c[1][1] - c[1][0] * c[0][1]; 00275 det0X = c[0][0] * x[1] - c[0][1] * x[0]; 00276 detX1 = x[0] * c[1][1] - x[1] * c[0][1]; 00277 if (ABS(det01) >= 1e-6) { 00278 scale0 = detX1 / det01; 00279 scale3 = det0X / det01; 00280 } 00281 if (ABS(det01) < 1e-6 || scale0 <= 0.0 || scale3 <= 0.0) { 00282 d01 = dist(inps[0], inps[inpn - 1]) / 3.0; 00283 scale0 = d01; 00284 scale3 = d01; 00285 } 00286 *sp0 = inps[0]; 00287 *sv0 = scale(ev0, scale0); 00288 *sp1 = inps[inpn - 1]; 00289 *sv1 = scale(ev1, scale3); 00290 return 0; 00291 } 00292 00293 static double dist_n(Ppoint_t * p, int n) 00294 { 00295 int i; 00296 double rv; 00297 00298 rv = 0.0; 00299 for (i = 1; i < n; i++) { 00300 rv += 00301 sqrt((p[i].x - p[i - 1].x) * (p[i].x - p[i - 1].x) + 00302 (p[i].y - p[i - 1].y) * (p[i].y - p[i - 1].y)); 00303 } 00304 return rv; 00305 } 00306 00307 static int splinefits(Pedge_t * edges, int edgen, Ppoint_t pa, 00308 Pvector_t va, Ppoint_t pb, Pvector_t vb, 00309 Ppoint_t * inps, int inpn) 00310 { 00311 Ppoint_t sps[4]; 00312 double a, b; 00313 #if 0 00314 double d; 00315 #endif 00316 int pi; 00317 int forceflag; 00318 int first = 1; 00319 00320 forceflag = (inpn == 2 ? 1 : 0); 00321 00322 #if 0 00323 d = sqrt((pb.x - pa.x) * (pb.x - pa.x) + 00324 (pb.y - pa.y) * (pb.y - pa.y)); 00325 a = d, b = d; 00326 #else 00327 a = b = 4; 00328 #endif 00329 for (;;) { 00330 sps[0].x = pa.x; 00331 sps[0].y = pa.y; 00332 sps[1].x = pa.x + a * va.x / 3.0; 00333 sps[1].y = pa.y + a * va.y / 3.0; 00334 sps[2].x = pb.x - b * vb.x / 3.0; 00335 sps[2].y = pb.y - b * vb.y / 3.0; 00336 sps[3].x = pb.x; 00337 sps[3].y = pb.y; 00338 00339 /* shortcuts (paths shorter than the shortest path) not allowed - 00340 * they must be outside the constraint polygon. this can happen 00341 * if the candidate spline intersects the constraint polygon exactly 00342 * on sides or vertices. maybe this could be more elegant, but 00343 * it solves the immediate problem. we could also try jittering the 00344 * constraint polygon, or computing the candidate spline more carefully, 00345 * for example using the path. SCN */ 00346 00347 if (first && (dist_n(sps, 4) < (dist_n(inps, inpn) - EPSILON1))) 00348 return 0; 00349 first = 0; 00350 00351 if (splineisinside(edges, edgen, &sps[0])) { 00352 growops(opl + 4); 00353 for (pi = 1; pi < 4; pi++) 00354 ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y; 00355 #if DEBUG >= 1 00356 fprintf(stderr, "success: %f %f\n", a, b); 00357 #endif 00358 return 1; 00359 } 00360 if (a == 0 && b == 0) { 00361 if (forceflag) { 00362 growops(opl + 4); 00363 for (pi = 1; pi < 4; pi++) 00364 ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y; 00365 #if DEBUG >= 1 00366 fprintf(stderr, "forced straight line: %f %f\n", a, b); 00367 #endif 00368 return 1; 00369 } 00370 break; 00371 } 00372 if (a > .01) 00373 a /= 2, b /= 2; 00374 else 00375 a = b = 0; 00376 } 00377 #if DEBUG >= 1 00378 fprintf(stderr, "failure\n"); 00379 #endif 00380 return 0; 00381 } 00382 00383 static int splineisinside(Pedge_t * edges, int edgen, Ppoint_t * sps) 00384 { 00385 double roots[4]; 00386 int rooti, rootn; 00387 int ei; 00388 Ppoint_t lps[2], ip; 00389 double t, ta, tb, tc, td; 00390 00391 for (ei = 0; ei < edgen; ei++) { 00392 lps[0] = edges[ei].a, lps[1] = edges[ei].b; 00393 /* if ((rootn = splineintersectsline (sps, lps, roots)) == 4) 00394 return 1; */ 00395 if ((rootn = splineintersectsline(sps, lps, roots)) == 4) 00396 continue; 00397 for (rooti = 0; rooti < rootn; rooti++) { 00398 if (roots[rooti] < EPSILON2 || roots[rooti] > 1 - EPSILON2) 00399 continue; 00400 t = roots[rooti]; 00401 td = t * t * t; 00402 tc = 3 * t * t * (1 - t); 00403 tb = 3 * t * (1 - t) * (1 - t); 00404 ta = (1 - t) * (1 - t) * (1 - t); 00405 ip.x = ta * sps[0].x + tb * sps[1].x + 00406 tc * sps[2].x + td * sps[3].x; 00407 ip.y = ta * sps[0].y + tb * sps[1].y + 00408 tc * sps[2].y + td * sps[3].y; 00409 if (DISTSQ(ip, lps[0]) < EPSILON1 || 00410 DISTSQ(ip, lps[1]) < EPSILON1) 00411 continue; 00412 return 0; 00413 } 00414 } 00415 return 1; 00416 } 00417 00418 static int splineintersectsline(Ppoint_t * sps, Ppoint_t * lps, 00419 double *roots) 00420 { 00421 double scoeff[4], xcoeff[2], ycoeff[2]; 00422 double xroots[3], yroots[3], tv, sv, rat; 00423 int rootn, xrootn, yrootn, i, j; 00424 00425 xcoeff[0] = lps[0].x; 00426 xcoeff[1] = lps[1].x - lps[0].x; 00427 ycoeff[0] = lps[0].y; 00428 ycoeff[1] = lps[1].y - lps[0].y; 00429 rootn = 0; 00430 if (xcoeff[1] == 0) { 00431 if (ycoeff[1] == 0) { 00432 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff); 00433 scoeff[0] -= xcoeff[0]; 00434 xrootn = solve3(scoeff, xroots); 00435 points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y, scoeff); 00436 scoeff[0] -= ycoeff[0]; 00437 yrootn = solve3(scoeff, yroots); 00438 if (xrootn == 4) 00439 if (yrootn == 4) 00440 return 4; 00441 else 00442 for (j = 0; j < yrootn; j++) 00443 addroot(yroots[j], roots, &rootn); 00444 else if (yrootn == 4) 00445 for (i = 0; i < xrootn; i++) 00446 addroot(xroots[i], roots, &rootn); 00447 else 00448 for (i = 0; i < xrootn; i++) 00449 for (j = 0; j < yrootn; j++) 00450 if (xroots[i] == yroots[j]) 00451 addroot(xroots[i], roots, &rootn); 00452 return rootn; 00453 } else { 00454 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff); 00455 scoeff[0] -= xcoeff[0]; 00456 xrootn = solve3(scoeff, xroots); 00457 if (xrootn == 4) 00458 return 4; 00459 for (i = 0; i < xrootn; i++) { 00460 tv = xroots[i]; 00461 if (tv >= 0 && tv <= 1) { 00462 points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y, 00463 scoeff); 00464 sv = scoeff[0] + tv * (scoeff[1] + tv * 00465 (scoeff[2] + tv * scoeff[3])); 00466 sv = (sv - ycoeff[0]) / ycoeff[1]; 00467 if ((0 <= sv) && (sv <= 1)) 00468 addroot(tv, roots, &rootn); 00469 } 00470 } 00471 return rootn; 00472 } 00473 } else { 00474 rat = ycoeff[1] / xcoeff[1]; 00475 points2coeff(sps[0].y - rat * sps[0].x, sps[1].y - rat * sps[1].x, 00476 sps[2].y - rat * sps[2].x, sps[3].y - rat * sps[3].x, 00477 scoeff); 00478 scoeff[0] += rat * xcoeff[0] - ycoeff[0]; 00479 xrootn = solve3(scoeff, xroots); 00480 if (xrootn == 4) 00481 return 4; 00482 for (i = 0; i < xrootn; i++) { 00483 tv = xroots[i]; 00484 if (tv >= 0 && tv <= 1) { 00485 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, 00486 scoeff); 00487 sv = scoeff[0] + tv * (scoeff[1] + 00488 tv * (scoeff[2] + tv * scoeff[3])); 00489 sv = (sv - xcoeff[0]) / xcoeff[1]; 00490 if ((0 <= sv) && (sv <= 1)) 00491 addroot(tv, roots, &rootn); 00492 } 00493 } 00494 return rootn; 00495 } 00496 } 00497 00498 static void points2coeff(double v0, double v1, double v2, double v3, 00499 double *coeff) 00500 { 00501 coeff[3] = v3 + 3 * v1 - (v0 + 3 * v2); 00502 coeff[2] = 3 * v0 + 3 * v2 - 6 * v1; 00503 coeff[1] = 3 * (v1 - v0); 00504 coeff[0] = v0; 00505 } 00506 00507 static void addroot(double root, double *roots, int *rootnp) 00508 { 00509 if (root >= 0 && root <= 1) 00510 roots[*rootnp] = root, (*rootnp)++; 00511 } 00512 00513 static Pvector_t normv(Pvector_t v) 00514 { 00515 double d; 00516 00517 d = v.x * v.x + v.y * v.y; 00518 if (d > 1e-6) { 00519 d = sqrt(d); 00520 v.x /= d, v.y /= d; 00521 } 00522 return v; 00523 } 00524 00525 static void growops(int newopn) 00526 { 00527 if (newopn <= opn) 00528 return; 00529 if (!ops) { 00530 if (!(ops = (Ppoint_t *) malloc(POINTSIZE * newopn))) { 00531 prerror("cannot malloc ops"); 00532 longjmp(jbuf,1); 00533 } 00534 } else { 00535 if (!(ops = (Ppoint_t *) realloc((void *) ops, 00536 POINTSIZE * newopn))) { 00537 prerror("cannot realloc ops"); 00538 longjmp(jbuf,1); 00539 } 00540 } 00541 opn = newopn; 00542 } 00543 00544 static Ppoint_t add(Ppoint_t p1, Ppoint_t p2) 00545 { 00546 p1.x += p2.x, p1.y += p2.y; 00547 return p1; 00548 } 00549 00550 static Ppoint_t sub(Ppoint_t p1, Ppoint_t p2) 00551 { 00552 p1.x -= p2.x, p1.y -= p2.y; 00553 return p1; 00554 } 00555 00556 static double dist(Ppoint_t p1, Ppoint_t p2) 00557 { 00558 double dx, dy; 00559 00560 dx = p2.x - p1.x, dy = p2.y - p1.y; 00561 return sqrt(dx * dx + dy * dy); 00562 } 00563 00564 static Ppoint_t scale(Ppoint_t p, double c) 00565 { 00566 p.x *= c, p.y *= c; 00567 return p; 00568 } 00569 00570 static double dot(Ppoint_t p1, Ppoint_t p2) 00571 { 00572 return p1.x * p2.x + p1.y * p2.y; 00573 } 00574 00575 static double B0(double t) 00576 { 00577 double tmp = 1.0 - t; 00578 return tmp * tmp * tmp; 00579 } 00580 00581 static double B1(double t) 00582 { 00583 double tmp = 1.0 - t; 00584 return 3 * t * tmp * tmp; 00585 } 00586 00587 static double B2(double t) 00588 { 00589 double tmp = 1.0 - t; 00590 return 3 * t * t * tmp; 00591 } 00592 00593 static double B3(double t) 00594 { 00595 return t * t * t; 00596 } 00597 00598 static double B01(double t) 00599 { 00600 double tmp = 1.0 - t; 00601 return tmp * tmp * (tmp + 3 * t); 00602 } 00603 00604 static double B23(double t) 00605 { 00606 double tmp = 1.0 - t; 00607 return t * t * (3 * tmp + t); 00608 } 00609 00610 #if 0 00611 static int cmpp2efunc(const void *v0p, const void *v1p) 00612 { 00613 p2e_t *p2e0p, *p2e1p; 00614 double x0, x1; 00615 00616 p2e0p = (p2e_t *) v0p, p2e1p = (p2e_t *) v1p; 00617 if (p2e0p->pp->y > p2e1p->pp->y) 00618 return -1; 00619 else if (p2e0p->pp->y < p2e1p->pp->y) 00620 return 1; 00621 if (p2e0p->pp->x < p2e1p->pp->x) 00622 return -1; 00623 else if (p2e0p->pp->x > p2e1p->pp->x) 00624 return 1; 00625 x0 = (p2e0p->pp == &p2e0p->ep->a) ? p2e0p->ep->b.x : p2e0p->ep->a.x; 00626 x1 = (p2e1p->pp == &p2e1p->ep->a) ? p2e1p->ep->b.x : p2e1p->ep->a.x; 00627 if (x0 < x1) 00628 return -1; 00629 else if (x0 > x1) 00630 return 1; 00631 return 0; 00632 } 00633 00634 static void listdelete(Pedge_t * ep) 00635 { 00636 elist_t *lp; 00637 00638 for (lp = elist; lp; lp = lp->next) { 00639 if (lp->ep != ep) 00640 continue; 00641 if (lp->prev) 00642 lp->prev->next = lp->next; 00643 if (lp->next) 00644 lp->next->prev = lp->prev; 00645 if (elist == lp) 00646 elist = lp->next; 00647 free(lp); 00648 return; 00649 } 00650 if (!lp) { 00651 prerror("cannot find list element to delete"); 00652 abort(); 00653 } 00654 } 00655 00656 static void listreplace(Pedge_t * oldep, Pedge_t * newep) 00657 { 00658 elist_t *lp; 00659 00660 for (lp = elist; lp; lp = lp->next) { 00661 if (lp->ep != oldep) 00662 continue; 00663 lp->ep = newep; 00664 return; 00665 } 00666 if (!lp) { 00667 prerror("cannot find list element to replace"); 00668 abort(); 00669 } 00670 } 00671 00672 static void listinsert(Pedge_t * ep, Ppoint_t p) 00673 { 00674 elist_t *lp, *newlp, *lastlp; 00675 double lx; 00676 00677 if (!(newlp = (elist_t *) malloc(sizeof(elist_t)))) { 00678 prerror("cannot malloc newlp"); 00679 abort(); 00680 } 00681 newlp->ep = ep; 00682 newlp->next = newlp->prev = NULL; 00683 if (!elist) { 00684 elist = newlp; 00685 return; 00686 } 00687 for (lp = elist; lp; lp = lp->next) { 00688 lastlp = lp; 00689 lx = lp->ep->a.x + (lp->ep->b.x - lp->ep->a.x) * (p.y - 00690 lp->ep->a.y) / 00691 (lp->ep->b.y - lp->ep->a.y); 00692 if (lx <= p.x) 00693 continue; 00694 if (lp->prev) 00695 lp->prev->next = newlp; 00696 newlp->prev = lp->prev; 00697 newlp->next = lp; 00698 lp->prev = newlp; 00699 if (elist == lp) 00700 elist = newlp; 00701 return; 00702 } 00703 lastlp->next = newlp; 00704 newlp->prev = lastlp; 00705 if (!elist) 00706 elist = newlp; 00707 } 00708 #endif
1.7.5