00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "gpc/gpc.h"
00041 #include <stdlib.h>
00042 #include <float.h>
00043 #include <math.h>
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef TRUE
00053 #define FALSE 0
00054 #define TRUE 1
00055 #endif
00056
00057 #define LEFT 0
00058 #define RIGHT 1
00059
00060 #define ABOVE 0
00061 #define BELOW 1
00062
00063 #define CLIP 0
00064 #define SUBJ 1
00065
00066 #define INVERT_TRISTRIPS FALSE
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define EQ(a, b) (fabs((a) - (b)) <= GPC_EPSILON)
00076
00077 #define PREV_INDEX(i, n) ((i - 1 + n) % n)
00078 #define NEXT_INDEX(i, n) ((i + 1 ) % n)
00079
00080 #define OPTIMAL(v, i, n) ((v[PREV_INDEX(i, n)].y != v[i].y) || \
00081 (v[NEXT_INDEX(i, n)].y != v[i].y))
00082
00083 #define FWD_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y >= v[i].vertex.y) \
00084 && (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y))
00085
00086 #define NOT_FMAX(v, i, n) (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y)
00087
00088 #define REV_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) \
00089 && (v[NEXT_INDEX(i, n)].vertex.y >= v[i].vertex.y))
00090
00091 #define NOT_RMAX(v, i, n) (v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y)
00092
00093 #define VERTEX(e,p,s,x,y) {add_vertex(&((e)->outp[(p)]->v[(s)]), x, y); \
00094 (e)->outp[(p)]->active++;}
00095
00096 #define P_EDGE(d,e,p,i,j) {(d)= (e); \
00097 do {(d)= (d)->prev;} while (!(d)->outp[(p)]); \
00098 (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);}
00099
00100 #define N_EDGE(d,e,p,i,j) {(d)= (e); \
00101 do {(d)= (d)->next;} while (!(d)->outp[(p)]); \
00102 (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);}
00103
00104 #define MALLOC(p, b, s, t) {if ((b) > 0) { \
00105 p= (t*)malloc(b); if (!(p)) { \
00106 fprintf(stderr, "gpc malloc failure: %s\n", s); \
00107 exit(0);}} else p= NULL;}
00108
00109 #define FREE(p) {if (p) {free(p); (p)= NULL;}}
00110
00111
00112
00113
00114
00115
00116
00117
00118 typedef enum
00119 {
00120 NUL,
00121 EMX,
00122 ELI,
00123 TED,
00124 ERI,
00125 RED,
00126 IMM,
00127 IMN,
00128 EMN,
00129 EMM,
00130 LED,
00131 ILI,
00132 BED,
00133 IRI,
00134 IMX,
00135 FUL
00136 } vertex_type;
00137
00138 typedef enum
00139 {
00140 NH,
00141 BH,
00142 TH
00143 } h_state;
00144
00145 typedef enum
00146 {
00147 UNBUNDLED,
00148 BUNDLE_HEAD,
00149 BUNDLE_TAIL
00150 } bundle_state;
00151
00152 typedef struct v_shape
00153 {
00154 double x;
00155 double y;
00156 struct v_shape *next;
00157 } vertex_node;
00158
00159 typedef struct p_shape
00160 {
00161 int active;
00162 int hole;
00163 vertex_node *v[2];
00164 struct p_shape *next;
00165 struct p_shape *proxy;
00166 } polygon_node;
00167
00168 typedef struct edge_shape
00169 {
00170 gpc_vertex vertex;
00171 gpc_vertex bot;
00172 gpc_vertex top;
00173 double xb;
00174 double xt;
00175 double dx;
00176 int type;
00177 int bundle[2][2];
00178 int bside[2];
00179 bundle_state bstate[2];
00180 polygon_node *outp[2];
00181 struct edge_shape *prev;
00182 struct edge_shape *next;
00183 struct edge_shape *pred;
00184 struct edge_shape *succ;
00185 struct edge_shape *next_bound;
00186 } edge_node;
00187
00188 typedef struct lmt_shape
00189 {
00190 double y;
00191 edge_node *first_bound;
00192 struct lmt_shape *next;
00193 } lmt_node;
00194
00195 typedef struct sbt_t_shape
00196 {
00197 double y;
00198 struct sbt_t_shape *less;
00199 struct sbt_t_shape *more;
00200 } sb_tree;
00201
00202 typedef struct it_shape
00203 {
00204 edge_node *ie[2];
00205 gpc_vertex point;
00206 struct it_shape *next;
00207 } it_node;
00208
00209 typedef struct st_shape
00210 {
00211 edge_node *edge;
00212 double xb;
00213 double xt;
00214 double dx;
00215 struct st_shape *prev;
00216 } st_node;
00217
00218 typedef struct bbox_shape
00219 {
00220 double xmin;
00221 double ymin;
00222 double xmax;
00223 double ymax;
00224 } bbox;
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 const h_state next_h_state[3][6]=
00235 {
00236
00237
00238 {BH, TH, TH, BH, NH, NH},
00239 {NH, NH, NH, NH, TH, TH},
00240 {NH, NH, NH, NH, BH, BH}
00241 };
00242
00243
00244
00245
00246
00247
00248
00249
00250 static void reset_it(it_node **it)
00251 {
00252 it_node *itn;
00253
00254 while (*it)
00255 {
00256 itn= (*it)->next;
00257 FREE(*it);
00258 *it= itn;
00259 }
00260 }
00261
00262
00263 static void reset_lmt(lmt_node **lmt)
00264 {
00265 lmt_node *lmtn;
00266
00267 while (*lmt)
00268 {
00269 lmtn= (*lmt)->next;
00270 FREE(*lmt);
00271 *lmt= lmtn;
00272 }
00273 }
00274
00275
00276 static void insert_bound(edge_node **b, edge_node *e)
00277 {
00278 edge_node *existing_bound;
00279
00280 if (!*b)
00281 {
00282
00283 *b= e;
00284 }
00285 else
00286 {
00287
00288 if (e[0].bot.x < (*b)[0].bot.x)
00289 {
00290
00291 existing_bound= *b;
00292 *b= e;
00293 (*b)->next_bound= existing_bound;
00294 }
00295 else
00296 {
00297 if (e[0].bot.x == (*b)[0].bot.x)
00298 {
00299
00300 if (e[0].dx < (*b)[0].dx)
00301 {
00302
00303 existing_bound= *b;
00304 *b= e;
00305 (*b)->next_bound= existing_bound;
00306 }
00307 else
00308 {
00309
00310 insert_bound(&((*b)->next_bound), e);
00311 }
00312 }
00313 else
00314 {
00315
00316 insert_bound(&((*b)->next_bound), e);
00317 }
00318 }
00319 }
00320 }
00321
00322
00323 static edge_node **bound_list(lmt_node **lmt, double y)
00324 {
00325 lmt_node *existing_node;
00326
00327 if (!*lmt)
00328 {
00329
00330 MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node);
00331 (*lmt)->y= y;
00332 (*lmt)->first_bound= NULL;
00333 (*lmt)->next= NULL;
00334 return &((*lmt)->first_bound);
00335 }
00336 else
00337 if (y < (*lmt)->y)
00338 {
00339
00340 existing_node= *lmt;
00341 MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node);
00342 (*lmt)->y= y;
00343 (*lmt)->first_bound= NULL;
00344 (*lmt)->next= existing_node;
00345 return &((*lmt)->first_bound);
00346 }
00347 else
00348 if (y > (*lmt)->y)
00349
00350 return bound_list(&((*lmt)->next), y);
00351 else
00352
00353 return &((*lmt)->first_bound);
00354 }
00355
00356
00357 static void add_to_sbtree(int *entries, sb_tree **sbtree, double y)
00358 {
00359 if (!*sbtree)
00360 {
00361
00362 MALLOC(*sbtree, sizeof(sb_tree), "scanbeam tree insertion", sb_tree);
00363 (*sbtree)->y= y;
00364 (*sbtree)->less= NULL;
00365 (*sbtree)->more= NULL;
00366 (*entries)++;
00367 }
00368 else
00369 {
00370 if ((*sbtree)->y > y)
00371 {
00372
00373 add_to_sbtree(entries, &((*sbtree)->less), y);
00374 }
00375 else
00376 {
00377 if ((*sbtree)->y < y)
00378 {
00379
00380 add_to_sbtree(entries, &((*sbtree)->more), y);
00381 }
00382 }
00383 }
00384 }
00385
00386
00387 static void build_sbt(int *entries, double *sbt, sb_tree *sbtree)
00388 {
00389 if (sbtree->less)
00390 build_sbt(entries, sbt, sbtree->less);
00391 sbt[*entries]= sbtree->y;
00392 (*entries)++;
00393 if (sbtree->more)
00394 build_sbt(entries, sbt, sbtree->more);
00395 }
00396
00397
00398 static void free_sbtree(sb_tree **sbtree)
00399 {
00400 if (*sbtree)
00401 {
00402 free_sbtree(&((*sbtree)->less));
00403 free_sbtree(&((*sbtree)->more));
00404 FREE(*sbtree);
00405 }
00406 }
00407
00408
00409 static int count_optimal_vertices(gpc_vertex_list c)
00410 {
00411 int result= 0, i;
00412
00413
00414 if (c.num_vertices > 0)
00415 {
00416 for (i= 0; i < c.num_vertices; i++)
00417
00418 if (OPTIMAL(c.vertex, i, c.num_vertices))
00419 result++;
00420 }
00421 return result;
00422 }
00423
00424
00425 static edge_node *build_lmt(lmt_node **lmt, sb_tree **sbtree,
00426 int *sbt_entries, gpc_polygon *p, int type,
00427 gpc_op op)
00428 {
00429 int c, i, min, max, num_edges, v, num_vertices;
00430 int total_vertices= 0, e_index=0;
00431 edge_node *e, *edge_table;
00432
00433 for (c= 0; c < p->num_contours; c++)
00434 total_vertices+= count_optimal_vertices(p->contour[c]);
00435
00436
00437 MALLOC(edge_table, total_vertices * sizeof(edge_node),
00438 "edge table creation", edge_node);
00439
00440 for (c= 0; c < p->num_contours; c++)
00441 {
00442 if (p->contour[c].num_vertices < 0)
00443 {
00444
00445 p->contour[c].num_vertices= -p->contour[c].num_vertices;
00446 }
00447 else
00448 {
00449
00450 num_vertices= 0;
00451 for (i= 0; i < p->contour[c].num_vertices; i++)
00452 if (OPTIMAL(p->contour[c].vertex, i, p->contour[c].num_vertices))
00453 {
00454 edge_table[num_vertices].vertex.x= p->contour[c].vertex[i].x;
00455 edge_table[num_vertices].vertex.y= p->contour[c].vertex[i].y;
00456
00457
00458 add_to_sbtree(sbt_entries, sbtree,
00459 edge_table[num_vertices].vertex.y);
00460
00461 num_vertices++;
00462 }
00463
00464
00465 for (min= 0; min < num_vertices; min++)
00466 {
00467
00468 if (FWD_MIN(edge_table, min, num_vertices))
00469 {
00470
00471 num_edges= 1;
00472 max= NEXT_INDEX(min, num_vertices);
00473 while (NOT_FMAX(edge_table, max, num_vertices))
00474 {
00475 num_edges++;
00476 max= NEXT_INDEX(max, num_vertices);
00477 }
00478
00479
00480 e= &edge_table[e_index];
00481 e_index+= num_edges;
00482 v= min;
00483 e[0].bstate[BELOW]= UNBUNDLED;
00484 e[0].bundle[BELOW][CLIP]= FALSE;
00485 e[0].bundle[BELOW][SUBJ]= FALSE;
00486 for (i= 0; i < num_edges; i++)
00487 {
00488 e[i].xb= edge_table[v].vertex.x;
00489 e[i].bot.x= edge_table[v].vertex.x;
00490 e[i].bot.y= edge_table[v].vertex.y;
00491
00492 v= NEXT_INDEX(v, num_vertices);
00493
00494 e[i].top.x= edge_table[v].vertex.x;
00495 e[i].top.y= edge_table[v].vertex.y;
00496 e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) /
00497 (e[i].top.y - e[i].bot.y);
00498 e[i].type= type;
00499 e[i].outp[ABOVE]= NULL;
00500 e[i].outp[BELOW]= NULL;
00501 e[i].next= NULL;
00502 e[i].prev= NULL;
00503 e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ?
00504 &(e[i + 1]) : NULL;
00505 e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL;
00506 e[i].next_bound= NULL;
00507 e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT;
00508 e[i].bside[SUBJ]= LEFT;
00509 }
00510 insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
00511 }
00512 }
00513
00514
00515 for (min= 0; min < num_vertices; min++)
00516 {
00517
00518 if (REV_MIN(edge_table, min, num_vertices))
00519 {
00520
00521 num_edges= 1;
00522 max= PREV_INDEX(min, num_vertices);
00523 while (NOT_RMAX(edge_table, max, num_vertices))
00524 {
00525 num_edges++;
00526 max= PREV_INDEX(max, num_vertices);
00527 }
00528
00529
00530 e= &edge_table[e_index];
00531 e_index+= num_edges;
00532 v= min;
00533 e[0].bstate[BELOW]= UNBUNDLED;
00534 e[0].bundle[BELOW][CLIP]= FALSE;
00535 e[0].bundle[BELOW][SUBJ]= FALSE;
00536 for (i= 0; i < num_edges; i++)
00537 {
00538 e[i].xb= edge_table[v].vertex.x;
00539 e[i].bot.x= edge_table[v].vertex.x;
00540 e[i].bot.y= edge_table[v].vertex.y;
00541
00542 v= PREV_INDEX(v, num_vertices);
00543
00544 e[i].top.x= edge_table[v].vertex.x;
00545 e[i].top.y= edge_table[v].vertex.y;
00546 e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) /
00547 (e[i].top.y - e[i].bot.y);
00548 e[i].type= type;
00549 e[i].outp[ABOVE]= NULL;
00550 e[i].outp[BELOW]= NULL;
00551 e[i].next= NULL;
00552 e[i].prev= NULL;
00553 e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ?
00554 &(e[i + 1]) : NULL;
00555 e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL;
00556 e[i].next_bound= NULL;
00557 e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT;
00558 e[i].bside[SUBJ]= LEFT;
00559 }
00560 insert_bound(bound_list(lmt, edge_table[min].vertex.y), e);
00561 }
00562 }
00563 }
00564 }
00565 return edge_table;
00566 }
00567
00568
00569 static void add_edge_to_aet(edge_node **aet, edge_node *edge, edge_node *prev)
00570 {
00571 if (!*aet)
00572 {
00573
00574 *aet= edge;
00575 edge->prev= prev;
00576 edge->next= NULL;
00577 }
00578 else
00579 {
00580
00581 if (edge->xb < (*aet)->xb)
00582 {
00583
00584 edge->prev= prev;
00585 edge->next= *aet;
00586 (*aet)->prev= edge;
00587 *aet= edge;
00588 }
00589 else
00590 {
00591 if (edge->xb == (*aet)->xb)
00592 {
00593
00594 if (edge->dx < (*aet)->dx)
00595 {
00596
00597 edge->prev= prev;
00598 edge->next= *aet;
00599 (*aet)->prev= edge;
00600 *aet= edge;
00601 }
00602 else
00603 {
00604
00605 add_edge_to_aet(&((*aet)->next), edge, *aet);
00606 }
00607 }
00608 else
00609 {
00610
00611 add_edge_to_aet(&((*aet)->next), edge, *aet);
00612 }
00613 }
00614 }
00615 }
00616
00617
00618 static void add_intersection(it_node **it, edge_node *edge0, edge_node *edge1,
00619 double x, double y)
00620 {
00621 it_node *existing_node;
00622
00623 if (!*it)
00624 {
00625
00626 MALLOC(*it, sizeof(it_node), "IT insertion", it_node);
00627 (*it)->ie[0]= edge0;
00628 (*it)->ie[1]= edge1;
00629 (*it)->point.x= x;
00630 (*it)->point.y= y;
00631 (*it)->next= NULL;
00632 }
00633 else
00634 {
00635 if ((*it)->point.y > y)
00636 {
00637
00638 existing_node= *it;
00639 MALLOC(*it, sizeof(it_node), "IT insertion", it_node);
00640 (*it)->ie[0]= edge0;
00641 (*it)->ie[1]= edge1;
00642 (*it)->point.x= x;
00643 (*it)->point.y= y;
00644 (*it)->next= existing_node;
00645 }
00646 else
00647
00648 add_intersection(&((*it)->next), edge0, edge1, x, y);
00649 }
00650 }
00651
00652
00653 static void add_st_edge(st_node **st, it_node **it, edge_node *edge,
00654 double dy)
00655 {
00656 st_node *existing_node;
00657 double den, r, x, y;
00658
00659 if (!*st)
00660 {
00661
00662 MALLOC(*st, sizeof(st_node), "ST insertion", st_node);
00663 (*st)->edge= edge;
00664 (*st)->xb= edge->xb;
00665 (*st)->xt= edge->xt;
00666 (*st)->dx= edge->dx;
00667 (*st)->prev= NULL;
00668 }
00669 else
00670 {
00671 den= ((*st)->xt - (*st)->xb) - (edge->xt - edge->xb);
00672
00673
00674 if ((edge->xt >= (*st)->xt) || (edge->dx == (*st)->dx) ||
00675 (fabs(den) <= DBL_EPSILON))
00676 {
00677
00678 existing_node= *st;
00679 MALLOC(*st, sizeof(st_node), "ST insertion", st_node);
00680 (*st)->edge= edge;
00681 (*st)->xb= edge->xb;
00682 (*st)->xt= edge->xt;
00683 (*st)->dx= edge->dx;
00684 (*st)->prev= existing_node;
00685 }
00686 else
00687 {
00688
00689 r= (edge->xb - (*st)->xb) / den;
00690 x= (*st)->xb + r * ((*st)->xt - (*st)->xb);
00691 y= r * dy;
00692
00693
00694 add_intersection(it, (*st)->edge, edge, x, y);
00695
00696
00697 add_st_edge(&((*st)->prev), it, edge, dy);
00698 }
00699 }
00700 }
00701
00702
00703 static void build_intersection_table(it_node **it, edge_node *aet, double dy)
00704 {
00705 st_node *st, *stp;
00706 edge_node *edge;
00707
00708
00709 reset_it(it);
00710 st= NULL;
00711
00712
00713 for (edge= aet; edge; edge= edge->next)
00714 {
00715 if ((edge->bstate[ABOVE] == BUNDLE_HEAD) ||
00716 edge->bundle[ABOVE][CLIP] || edge->bundle[ABOVE][SUBJ])
00717 add_st_edge(&st, it, edge, dy);
00718 }
00719
00720
00721 while (st)
00722 {
00723 stp= st->prev;
00724 FREE(st);
00725 st= stp;
00726 }
00727 }
00728
00729 static int count_contours(polygon_node *polygon)
00730 {
00731 int nc, nv;
00732 vertex_node *v, *nextv;
00733
00734 for (nc= 0; polygon; polygon= polygon->next)
00735 if (polygon->active)
00736 {
00737
00738 nv= 0;
00739 for (v= polygon->proxy->v[LEFT]; v; v= v->next)
00740 nv++;
00741
00742
00743 if (nv > 2)
00744 {
00745 polygon->active= nv;
00746 nc++;
00747 }
00748 else
00749 {
00750
00751 for (v= polygon->proxy->v[LEFT]; v; v= nextv)
00752 {
00753 nextv= v->next;
00754 FREE(v);
00755 }
00756 polygon->active= 0;
00757 }
00758 }
00759 return nc;
00760 }
00761
00762
00763 static void add_left(polygon_node *p, double x, double y)
00764 {
00765 vertex_node *nv;
00766
00767
00768 MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
00769 nv->x= x;
00770 nv->y= y;
00771
00772
00773 nv->next= p->proxy->v[LEFT];
00774
00775
00776 p->proxy->v[LEFT]= nv;
00777 }
00778
00779
00780 static void merge_left(polygon_node *p, polygon_node *q, polygon_node *list)
00781 {
00782 polygon_node *target;
00783
00784
00785 q->proxy->hole= TRUE;
00786
00787 if (p->proxy != q->proxy)
00788 {
00789
00790 p->proxy->v[RIGHT]->next= q->proxy->v[LEFT];
00791 q->proxy->v[LEFT]= p->proxy->v[LEFT];
00792
00793
00794
00795 for (target= p->proxy; list; list= list->next)
00796 {
00797 if (list->proxy == target)
00798 {
00799 list->active= FALSE;
00800 list->proxy= q->proxy;
00801 }
00802 }
00803 }
00804 }
00805
00806
00807 static void add_right(polygon_node *p, double x, double y)
00808 {
00809 vertex_node *nv;
00810
00811
00812 MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
00813 nv->x= x;
00814 nv->y= y;
00815 nv->next= NULL;
00816
00817
00818 p->proxy->v[RIGHT]->next= nv;
00819
00820
00821 p->proxy->v[RIGHT]= nv;
00822 }
00823
00824
00825 static void merge_right(polygon_node *p, polygon_node *q, polygon_node *list)
00826 {
00827 polygon_node *target;
00828
00829
00830 q->proxy->hole= FALSE;
00831
00832 if (p->proxy != q->proxy)
00833 {
00834
00835 q->proxy->v[RIGHT]->next= p->proxy->v[LEFT];
00836 q->proxy->v[RIGHT]= p->proxy->v[RIGHT];
00837
00838
00839 for (target= p->proxy; list; list= list->next)
00840 {
00841 if (list->proxy == target)
00842 {
00843 list->active= FALSE;
00844 list->proxy= q->proxy;
00845 }
00846 }
00847 }
00848 }
00849
00850
00851 static void add_local_min(polygon_node **p, edge_node *edge,
00852 double x, double y)
00853 {
00854 polygon_node *existing_min;
00855 vertex_node *nv;
00856
00857 existing_min= *p;
00858
00859 MALLOC(*p, sizeof(polygon_node), "polygon node creation", polygon_node);
00860
00861
00862 MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node);
00863 nv->x= x;
00864 nv->y= y;
00865 nv->next= NULL;
00866
00867
00868 (*p)->proxy= (*p);
00869 (*p)->active= TRUE;
00870 (*p)->next= existing_min;
00871
00872
00873 (*p)->v[LEFT]= nv;
00874 (*p)->v[RIGHT]= nv;
00875
00876
00877 edge->outp[ABOVE]= *p;
00878 }
00879
00880
00881 static int count_tristrips(polygon_node *tn)
00882 {
00883 int total;
00884
00885 for (total= 0; tn; tn= tn->next)
00886 if (tn->active > 2)
00887 total++;
00888 return total;
00889 }
00890
00891
00892 static void add_vertex(vertex_node **t, double x, double y)
00893 {
00894 if (!(*t))
00895 {
00896 MALLOC(*t, sizeof(vertex_node), "tristrip vertex creation", vertex_node);
00897 (*t)->x= x;
00898 (*t)->y= y;
00899 (*t)->next= NULL;
00900 }
00901 else
00902
00903 add_vertex(&((*t)->next), x, y);
00904 }
00905
00906
00907 static void new_tristrip(polygon_node **tn, edge_node *edge,
00908 double x, double y)
00909 {
00910 if (!(*tn))
00911 {
00912 MALLOC(*tn, sizeof(polygon_node), "tristrip node creation", polygon_node);
00913 (*tn)->next= NULL;
00914 (*tn)->v[LEFT]= NULL;
00915 (*tn)->v[RIGHT]= NULL;
00916 (*tn)->active= 1;
00917 add_vertex(&((*tn)->v[LEFT]), x, y);
00918 edge->outp[ABOVE]= *tn;
00919 }
00920 else
00921
00922 new_tristrip(&((*tn)->next), edge, x, y);
00923 }
00924
00925
00926 static bbox *create_contour_bboxes(gpc_polygon *p)
00927 {
00928 bbox *box;
00929 int c, v;
00930
00931 MALLOC(box, p->num_contours * sizeof(bbox), "Bounding box creation", bbox);
00932
00933
00934 for (c= 0; c < p->num_contours; c++)
00935 {
00936
00937 box[c].xmin= DBL_MAX;
00938 box[c].ymin= DBL_MAX;
00939 box[c].xmax= -DBL_MAX;
00940 box[c].ymax= -DBL_MAX;
00941
00942 for (v= 0; v < p->contour[c].num_vertices; v++)
00943 {
00944
00945 if (p->contour[c].vertex[v].x < box[c].xmin)
00946 box[c].xmin= p->contour[c].vertex[v].x;
00947 if (p->contour[c].vertex[v].y < box[c].ymin)
00948 box[c].ymin= p->contour[c].vertex[v].y;
00949 if (p->contour[c].vertex[v].x > box[c].xmax)
00950 box[c].xmax= p->contour[c].vertex[v].x;
00951 if (p->contour[c].vertex[v].y > box[c].ymax)
00952 box[c].ymax= p->contour[c].vertex[v].y;
00953 }
00954 }
00955 return box;
00956 }
00957
00958
00959 static void minimax_test(gpc_polygon *subj, gpc_polygon *clip, gpc_op op)
00960 {
00961 bbox *s_bbox, *c_bbox;
00962 int s, c, *o_table, overlap;
00963
00964 s_bbox= create_contour_bboxes(subj);
00965 c_bbox= create_contour_bboxes(clip);
00966
00967 MALLOC(o_table, subj->num_contours * clip->num_contours * sizeof(int),
00968 "overlap table creation", int);
00969
00970
00971 for (s= 0; s < subj->num_contours; s++)
00972 for (c= 0; c < clip->num_contours; c++)
00973 o_table[c * subj->num_contours + s]=
00974 (!((s_bbox[s].xmax < c_bbox[c].xmin) ||
00975 (s_bbox[s].xmin > c_bbox[c].xmax))) &&
00976 (!((s_bbox[s].ymax < c_bbox[c].ymin) ||
00977 (s_bbox[s].ymin > c_bbox[c].ymax)));
00978
00979
00980 for (c= 0; c < clip->num_contours; c++)
00981 {
00982 overlap= 0;
00983 for (s= 0; (!overlap) && (s < subj->num_contours); s++)
00984 overlap= o_table[c * subj->num_contours + s];
00985
00986 if (!overlap)
00987
00988 clip->contour[c].num_vertices = -clip->contour[c].num_vertices;
00989 }
00990
00991 if (op == GPC_INT)
00992 {
00993
00994 for (s= 0; s < subj->num_contours; s++)
00995 {
00996 overlap= 0;
00997 for (c= 0; (!overlap) && (c < clip->num_contours); c++)
00998 overlap= o_table[c * subj->num_contours + s];
00999
01000 if (!overlap)
01001
01002 subj->contour[s].num_vertices = -subj->contour[s].num_vertices;
01003 }
01004 }
01005
01006 FREE(s_bbox);
01007 FREE(c_bbox);
01008 FREE(o_table);
01009 }
01010
01011
01012
01013
01014
01015
01016
01017
01018 void gpc_free_polygon(gpc_polygon *p)
01019 {
01020 int c;
01021
01022 for (c= 0; c < p->num_contours; c++)
01023 FREE(p->contour[c].vertex);
01024 FREE(p->hole);
01025 FREE(p->contour);
01026 p->num_contours= 0;
01027 }
01028
01029
01030 void gpc_read_polygon(FILE *fp, int read_hole_flags, gpc_polygon *p)
01031 {
01032 int c, v;
01033
01034 fscanf(fp, "%d", &(p->num_contours));
01035 MALLOC(p->hole, p->num_contours * sizeof(int),
01036 "hole flag array creation", int);
01037 MALLOC(p->contour, p->num_contours
01038 * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
01039 for (c= 0; c < p->num_contours; c++)
01040 {
01041 fscanf(fp, "%d", &(p->contour[c].num_vertices));
01042
01043 if (read_hole_flags)
01044 fscanf(fp, "%d", &(p->hole[c]));
01045 else
01046 p->hole[c]= FALSE;
01047
01048 MALLOC(p->contour[c].vertex, p->contour[c].num_vertices
01049 * sizeof(gpc_vertex), "vertex creation", gpc_vertex);
01050 for (v= 0; v < p->contour[c].num_vertices; v++)
01051 fscanf(fp, "%lf %lf", &(p->contour[c].vertex[v].x),
01052 &(p->contour[c].vertex[v].y));
01053 }
01054 }
01055
01056
01057 void gpc_write_polygon(FILE *fp, int write_hole_flags, gpc_polygon *p)
01058 {
01059 int c, v;
01060
01061 fprintf(fp, "%d\n", p->num_contours);
01062 for (c= 0; c < p->num_contours; c++)
01063 {
01064 fprintf(fp, "%d\n", p->contour[c].num_vertices);
01065
01066 if (write_hole_flags)
01067 fprintf(fp, "%d\n", p->hole[c]);
01068
01069 for (v= 0; v < p->contour[c].num_vertices; v++)
01070 fprintf(fp, "% .*lf % .*lf\n",
01071 DBL_DIG, p->contour[c].vertex[v].x,
01072 DBL_DIG, p->contour[c].vertex[v].y);
01073 }
01074 }
01075
01076
01077 void gpc_add_contour(gpc_polygon *p, gpc_vertex_list *new_contour, int hole)
01078 {
01079 int *extended_hole, c, v;
01080 gpc_vertex_list *extended_contour;
01081
01082
01083 MALLOC(extended_hole, (p->num_contours + 1)
01084 * sizeof(int), "contour hole addition", int);
01085
01086
01087 MALLOC(extended_contour, (p->num_contours + 1)
01088 * sizeof(gpc_vertex_list), "contour addition", gpc_vertex_list);
01089
01090
01091 for (c= 0; c < p->num_contours; c++)
01092 {
01093 extended_hole[c]= p->hole[c];
01094 extended_contour[c]= p->contour[c];
01095 }
01096
01097
01098 c= p->num_contours;
01099 extended_hole[c]= hole;
01100 extended_contour[c].num_vertices= new_contour->num_vertices;
01101 MALLOC(extended_contour[c].vertex, new_contour->num_vertices
01102 * sizeof(gpc_vertex), "contour addition", gpc_vertex);
01103 for (v= 0; v < new_contour->num_vertices; v++)
01104 extended_contour[c].vertex[v]= new_contour->vertex[v];
01105
01106
01107 FREE(p->contour);
01108 FREE(p->hole);
01109
01110
01111 p->num_contours++;
01112 p->hole= extended_hole;
01113 p->contour= extended_contour;
01114 }
01115
01116
01117 void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
01118 gpc_polygon *result)
01119 {
01120 sb_tree *sbtree= NULL;
01121 it_node *it= NULL, *intersect;
01122 edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1;
01123 edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL;
01124 lmt_node *lmt= NULL, *local_min;
01125 polygon_node *out_poly= NULL, *p, *q, *poly, *npoly, *cf= NULL;
01126 vertex_node *vtx, *nv;
01127 h_state horiz[2];
01128 int in[2], exists[2], parity[2]= {LEFT, LEFT};
01129 int c, v, contributing, search, scanbeam= 0, sbt_entries= 0;
01130 int vclass, bl, br, tl, tr;
01131 double *sbt= NULL, xb, px, yb, yt, dy, ix, iy;
01132
01133
01134 if (((subj->num_contours == 0) && (clip->num_contours == 0))
01135 || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF)))
01136 || ((clip->num_contours == 0) && (op == GPC_INT)))
01137 {
01138 result->num_contours= 0;
01139 result->hole= NULL;
01140 result->contour= NULL;
01141 return;
01142 }
01143
01144
01145 if (((op == GPC_INT) || (op == GPC_DIFF))
01146 && (subj->num_contours > 0) && (clip->num_contours > 0))
01147 minimax_test(subj, clip, op);
01148
01149
01150 if (subj->num_contours > 0)
01151 s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op);
01152 if (clip->num_contours > 0)
01153 c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op);
01154
01155
01156 if (lmt == NULL)
01157 {
01158 result->num_contours= 0;
01159 result->hole= NULL;
01160 result->contour= NULL;
01161 reset_lmt(&lmt);
01162 FREE(s_heap);
01163 FREE(c_heap);
01164 return;
01165 }
01166
01167
01168 MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double);
01169 build_sbt(&scanbeam, sbt, sbtree);
01170 scanbeam= 0;
01171 free_sbtree(&sbtree);
01172
01173
01174 if (subj == result)
01175 gpc_free_polygon(subj);
01176 if (clip == result)
01177 gpc_free_polygon(clip);
01178
01179
01180 if (op == GPC_DIFF)
01181 parity[CLIP]= RIGHT;
01182
01183 local_min= lmt;
01184
01185
01186 while (scanbeam < sbt_entries)
01187 {
01188
01189 yb= sbt[scanbeam++];
01190 if (scanbeam < sbt_entries)
01191 {
01192 yt= sbt[scanbeam];
01193 dy= yt - yb;
01194 }
01195
01196
01197
01198
01199 if (local_min)
01200 {
01201 if (local_min->y == yb)
01202 {
01203
01204 for (edge= local_min->first_bound; edge; edge= edge->next_bound)
01205 add_edge_to_aet(&aet, edge, NULL);
01206
01207 local_min= local_min->next;
01208 }
01209 }
01210
01211
01212 px= -DBL_MAX;
01213
01214
01215 e0= aet;
01216 e1= aet;
01217
01218
01219 aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb);
01220 aet->bundle[ABOVE][!aet->type]= FALSE;
01221 aet->bstate[ABOVE]= UNBUNDLED;
01222
01223 for (next_edge= aet->next; next_edge; next_edge= next_edge->next)
01224 {
01225
01226 next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb);
01227 next_edge->bundle[ABOVE][!next_edge->type]= FALSE;
01228 next_edge->bstate[ABOVE]= UNBUNDLED;
01229
01230
01231 if (next_edge->bundle[ABOVE][next_edge->type])
01232 {
01233 if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx)
01234 && (e0->top.y != yb))
01235 {
01236 next_edge->bundle[ABOVE][ next_edge->type]^=
01237 e0->bundle[ABOVE][ next_edge->type];
01238 next_edge->bundle[ABOVE][!next_edge->type]=
01239 e0->bundle[ABOVE][!next_edge->type];
01240 next_edge->bstate[ABOVE]= BUNDLE_HEAD;
01241 e0->bundle[ABOVE][CLIP]= FALSE;
01242 e0->bundle[ABOVE][SUBJ]= FALSE;
01243 e0->bstate[ABOVE]= BUNDLE_TAIL;
01244 }
01245 e0= next_edge;
01246 }
01247 }
01248
01249 horiz[CLIP]= NH;
01250 horiz[SUBJ]= NH;
01251
01252
01253 for (edge= aet; edge; edge= edge->next)
01254 {
01255 exists[CLIP]= edge->bundle[ABOVE][CLIP] +
01256 (edge->bundle[BELOW][CLIP] << 1);
01257 exists[SUBJ]= edge->bundle[ABOVE][SUBJ] +
01258 (edge->bundle[BELOW][SUBJ] << 1);
01259
01260 if (exists[CLIP] || exists[SUBJ])
01261 {
01262
01263 edge->bside[CLIP]= parity[CLIP];
01264 edge->bside[SUBJ]= parity[SUBJ];
01265
01266
01267 switch (op)
01268 {
01269 case GPC_DIFF:
01270 case GPC_INT:
01271 contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ]))
01272 || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP]))
01273 || (exists[CLIP] && exists[SUBJ]
01274 && (parity[CLIP] == parity[SUBJ]));
01275 br= (parity[CLIP])
01276 && (parity[SUBJ]);
01277 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01278 && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01279 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01280 && (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01281 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01282 && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01283 break;
01284 case GPC_XOR:
01285 contributing= exists[CLIP] || exists[SUBJ];
01286 br= (parity[CLIP])
01287 ^ (parity[SUBJ]);
01288 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01289 ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01290 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01291 ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01292 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01293 ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01294 break;
01295 case GPC_UNION:
01296 contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ]))
01297 || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP]))
01298 || (exists[CLIP] && exists[SUBJ]
01299 && (parity[CLIP] == parity[SUBJ]));
01300 br= (parity[CLIP])
01301 || (parity[SUBJ]);
01302 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01303 || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01304 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01305 || (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01306 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01307 || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01308 break;
01309 }
01310
01311
01312 parity[CLIP]^= edge->bundle[ABOVE][CLIP];
01313 parity[SUBJ]^= edge->bundle[ABOVE][SUBJ];
01314
01315
01316 if (exists[CLIP])
01317 horiz[CLIP]=
01318 next_h_state[horiz[CLIP]]
01319 [((exists[CLIP] - 1) << 1) + parity[CLIP]];
01320 if (exists[SUBJ])
01321 horiz[SUBJ]=
01322 next_h_state[horiz[SUBJ]]
01323 [((exists[SUBJ] - 1) << 1) + parity[SUBJ]];
01324
01325 vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
01326
01327 if (contributing)
01328 {
01329 xb= edge->xb;
01330
01331 switch (vclass)
01332 {
01333 case EMN:
01334 case IMN:
01335 add_local_min(&out_poly, edge, xb, yb);
01336 px= xb;
01337 cf= edge->outp[ABOVE];
01338 break;
01339 case ERI:
01340 if (xb != px)
01341 {
01342 add_right(cf, xb, yb);
01343 px= xb;
01344 }
01345 edge->outp[ABOVE]= cf;
01346 cf= NULL;
01347 break;
01348 case ELI:
01349 add_left(edge->outp[BELOW], xb, yb);
01350 px= xb;
01351 cf= edge->outp[BELOW];
01352 break;
01353 case EMX:
01354 if (xb != px)
01355 {
01356 add_left(cf, xb, yb);
01357 px= xb;
01358 }
01359 merge_right(cf, edge->outp[BELOW], out_poly);
01360 cf= NULL;
01361 break;
01362 case ILI:
01363 if (xb != px)
01364 {
01365 add_left(cf, xb, yb);
01366 px= xb;
01367 }
01368 edge->outp[ABOVE]= cf;
01369 cf= NULL;
01370 break;
01371 case IRI:
01372 add_right(edge->outp[BELOW], xb, yb);
01373 px= xb;
01374 cf= edge->outp[BELOW];
01375 edge->outp[BELOW]= NULL;
01376 break;
01377 case IMX:
01378 if (xb != px)
01379 {
01380 add_right(cf, xb, yb);
01381 px= xb;
01382 }
01383 merge_left(cf, edge->outp[BELOW], out_poly);
01384 cf= NULL;
01385 edge->outp[BELOW]= NULL;
01386 break;
01387 case IMM:
01388 if (xb != px)
01389 {
01390 add_right(cf, xb, yb);
01391 px= xb;
01392 }
01393 merge_left(cf, edge->outp[BELOW], out_poly);
01394 edge->outp[BELOW]= NULL;
01395 add_local_min(&out_poly, edge, xb, yb);
01396 cf= edge->outp[ABOVE];
01397 break;
01398 case EMM:
01399 if (xb != px)
01400 {
01401 add_left(cf, xb, yb);
01402 px= xb;
01403 }
01404 merge_right(cf, edge->outp[BELOW], out_poly);
01405 edge->outp[BELOW]= NULL;
01406 add_local_min(&out_poly, edge, xb, yb);
01407 cf= edge->outp[ABOVE];
01408 break;
01409 case LED:
01410 if (edge->bot.y == yb)
01411 add_left(edge->outp[BELOW], xb, yb);
01412 edge->outp[ABOVE]= edge->outp[BELOW];
01413 px= xb;
01414 break;
01415 case RED:
01416 if (edge->bot.y == yb)
01417 add_right(edge->outp[BELOW], xb, yb);
01418 edge->outp[ABOVE]= edge->outp[BELOW];
01419 px= xb;
01420 break;
01421 default:
01422 break;
01423 }
01424 }
01425 }
01426 }
01427
01428
01429 for (edge= aet; edge; edge= edge->next)
01430 {
01431 if (edge->top.y == yb)
01432 {
01433 prev_edge= edge->prev;
01434 next_edge= edge->next;
01435 if (prev_edge)
01436 prev_edge->next= next_edge;
01437 else
01438 aet= next_edge;
01439 if (next_edge)
01440 next_edge->prev= prev_edge;
01441
01442
01443 if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge)
01444 {
01445 if (prev_edge->bstate[BELOW] == BUNDLE_TAIL)
01446 {
01447 prev_edge->outp[BELOW]= edge->outp[BELOW];
01448 prev_edge->bstate[BELOW]= UNBUNDLED;
01449 if (prev_edge->prev)
01450 if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL)
01451 prev_edge->bstate[BELOW]= BUNDLE_HEAD;
01452 }
01453 }
01454 }
01455 else
01456 {
01457 if (edge->top.y == yt)
01458 edge->xt= edge->top.x;
01459 else
01460 edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y);
01461 }
01462 }
01463
01464 if (scanbeam < sbt_entries)
01465 {
01466
01467
01468 build_intersection_table(&it, aet, dy);
01469
01470
01471 for (intersect= it; intersect; intersect= intersect->next)
01472 {
01473 e0= intersect->ie[0];
01474 e1= intersect->ie[1];
01475
01476
01477 if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ])
01478 && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ]))
01479 {
01480 p= e0->outp[ABOVE];
01481 q= e1->outp[ABOVE];
01482 ix= intersect->point.x;
01483 iy= intersect->point.y + yb;
01484
01485 in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP])
01486 || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP])
01487 || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP]
01488 && e0->bside[CLIP] && e1->bside[CLIP]);
01489 in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ])
01490 || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ])
01491 || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ]
01492 && e0->bside[SUBJ] && e1->bside[SUBJ]);
01493
01494
01495 switch (op)
01496 {
01497 case GPC_DIFF:
01498 case GPC_INT:
01499 tr= (in[CLIP])
01500 && (in[SUBJ]);
01501 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
01502 && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
01503 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
01504 && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01505 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
01506 && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01507 break;
01508 case GPC_XOR:
01509 tr= (in[CLIP])
01510 ^ (in[SUBJ]);
01511 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
01512 ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
01513 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
01514 ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01515 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
01516 ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01517 break;
01518 case GPC_UNION:
01519 tr= (in[CLIP])
01520 || (in[SUBJ]);
01521 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
01522 || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
01523 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
01524 || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01525 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
01526 || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
01527 break;
01528 }
01529
01530 vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
01531
01532 switch (vclass)
01533 {
01534 case EMN:
01535 add_local_min(&out_poly, e0, ix, iy);
01536 e1->outp[ABOVE]= e0->outp[ABOVE];
01537 break;
01538 case ERI:
01539 if (p)
01540 {
01541 add_right(p, ix, iy);
01542 e1->outp[ABOVE]= p;
01543 e0->outp[ABOVE]= NULL;
01544 }
01545 break;
01546 case ELI:
01547 if (q)
01548 {
01549 add_left(q, ix, iy);
01550 e0->outp[ABOVE]= q;
01551 e1->outp[ABOVE]= NULL;
01552 }
01553 break;
01554 case EMX:
01555 if (p && q)
01556 {
01557 add_left(p, ix, iy);
01558 merge_right(p, q, out_poly);
01559 e0->outp[ABOVE]= NULL;
01560 e1->outp[ABOVE]= NULL;
01561 }
01562 break;
01563 case IMN:
01564 add_local_min(&out_poly, e0, ix, iy);
01565 e1->outp[ABOVE]= e0->outp[ABOVE];
01566 break;
01567 case ILI:
01568 if (p)
01569 {
01570 add_left(p, ix, iy);
01571 e1->outp[ABOVE]= p;
01572 e0->outp[ABOVE]= NULL;
01573 }
01574 break;
01575 case IRI:
01576 if (q)
01577 {
01578 add_right(q, ix, iy);
01579 e0->outp[ABOVE]= q;
01580 e1->outp[ABOVE]= NULL;
01581 }
01582 break;
01583 case IMX:
01584 if (p && q)
01585 {
01586 add_right(p, ix, iy);
01587 merge_left(p, q, out_poly);
01588 e0->outp[ABOVE]= NULL;
01589 e1->outp[ABOVE]= NULL;
01590 }
01591 break;
01592 case IMM:
01593 if (p && q)
01594 {
01595 add_right(p, ix, iy);
01596 merge_left(p, q, out_poly);
01597 add_local_min(&out_poly, e0, ix, iy);
01598 e1->outp[ABOVE]= e0->outp[ABOVE];
01599 }
01600 break;
01601 case EMM:
01602 if (p && q)
01603 {
01604 add_left(p, ix, iy);
01605 merge_right(p, q, out_poly);
01606 add_local_min(&out_poly, e0, ix, iy);
01607 e1->outp[ABOVE]= e0->outp[ABOVE];
01608 }
01609 break;
01610 default:
01611 break;
01612 }
01613 }
01614
01615
01616 if (e0->bundle[ABOVE][CLIP])
01617 e1->bside[CLIP]= !e1->bside[CLIP];
01618 if (e1->bundle[ABOVE][CLIP])
01619 e0->bside[CLIP]= !e0->bside[CLIP];
01620 if (e0->bundle[ABOVE][SUBJ])
01621 e1->bside[SUBJ]= !e1->bside[SUBJ];
01622 if (e1->bundle[ABOVE][SUBJ])
01623 e0->bside[SUBJ]= !e0->bside[SUBJ];
01624
01625
01626 prev_edge= e0->prev;
01627 next_edge= e1->next;
01628 if (next_edge)
01629 next_edge->prev= e0;
01630
01631 if (e0->bstate[ABOVE] == BUNDLE_HEAD)
01632 {
01633 search= TRUE;
01634 while (search)
01635 {
01636 prev_edge= prev_edge->prev;
01637 if (prev_edge)
01638 {
01639 if (prev_edge->bstate[ABOVE] != BUNDLE_TAIL)
01640 search= FALSE;
01641 }
01642 else
01643 search= FALSE;
01644 }
01645 }
01646 if (!prev_edge)
01647 {
01648 aet->prev= e1;
01649 e1->next= aet;
01650 aet= e0->next;
01651 }
01652 else
01653 {
01654 prev_edge->next->prev= e1;
01655 e1->next= prev_edge->next;
01656 prev_edge->next= e0->next;
01657 }
01658 e0->next->prev= prev_edge;
01659 e1->next->prev= e1;
01660 e0->next= next_edge;
01661 }
01662
01663
01664 for (edge= aet; edge; edge= next_edge)
01665 {
01666 next_edge= edge->next;
01667 succ_edge= edge->succ;
01668
01669 if ((edge->top.y == yt) && succ_edge)
01670 {
01671
01672 succ_edge->outp[BELOW]= edge->outp[ABOVE];
01673 succ_edge->bstate[BELOW]= edge->bstate[ABOVE];
01674 succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
01675 succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
01676 prev_edge= edge->prev;
01677 if (prev_edge)
01678 prev_edge->next= succ_edge;
01679 else
01680 aet= succ_edge;
01681 if (next_edge)
01682 next_edge->prev= succ_edge;
01683 succ_edge->prev= prev_edge;
01684 succ_edge->next= next_edge;
01685 }
01686 else
01687 {
01688
01689 edge->outp[BELOW]= edge->outp[ABOVE];
01690 edge->bstate[BELOW]= edge->bstate[ABOVE];
01691 edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
01692 edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
01693 edge->xb= edge->xt;
01694 }
01695 edge->outp[ABOVE]= NULL;
01696 }
01697 }
01698 }
01699
01700
01701 result->contour= NULL;
01702 result->hole= NULL;
01703 result->num_contours= count_contours(out_poly);
01704 if (result->num_contours > 0)
01705 {
01706 MALLOC(result->hole, result->num_contours
01707 * sizeof(int), "hole flag table creation", int);
01708 MALLOC(result->contour, result->num_contours
01709 * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
01710
01711 c= 0;
01712 for (poly= out_poly; poly; poly= npoly)
01713 {
01714 npoly= poly->next;
01715 if (poly->active)
01716 {
01717 result->hole[c]= poly->proxy->hole;
01718 result->contour[c].num_vertices= poly->active;
01719 MALLOC(result->contour[c].vertex,
01720 result->contour[c].num_vertices * sizeof(gpc_vertex),
01721 "vertex creation", gpc_vertex);
01722
01723 v= result->contour[c].num_vertices - 1;
01724 for (vtx= poly->proxy->v[LEFT]; vtx; vtx= nv)
01725 {
01726 nv= vtx->next;
01727 result->contour[c].vertex[v].x= vtx->x;
01728 result->contour[c].vertex[v].y= vtx->y;
01729 FREE(vtx);
01730 v--;
01731 }
01732 c++;
01733 }
01734 FREE(poly);
01735 }
01736 }
01737 else
01738 {
01739 for (poly= out_poly; poly; poly= npoly)
01740 {
01741 npoly= poly->next;
01742 FREE(poly);
01743 }
01744 }
01745
01746
01747 reset_it(&it);
01748 reset_lmt(&lmt);
01749 FREE(c_heap);
01750 FREE(s_heap);
01751 FREE(sbt);
01752 }
01753
01754
01755 void gpc_free_tristrip(gpc_tristrip *t)
01756 {
01757 int s;
01758
01759 for (s= 0; s < t->num_strips; s++)
01760 FREE(t->strip[s].vertex);
01761 FREE(t->strip);
01762 t->num_strips= 0;
01763 }
01764
01765
01766 void gpc_polygon_to_tristrip(gpc_polygon *s, gpc_tristrip *t)
01767 {
01768 gpc_polygon c;
01769
01770 c.num_contours= 0;
01771 c.hole= NULL;
01772 c.contour= NULL;
01773 gpc_tristrip_clip(GPC_DIFF, s, &c, t);
01774 }
01775
01776
01777 void gpc_tristrip_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
01778 gpc_tristrip *result)
01779 {
01780 sb_tree *sbtree= NULL;
01781 it_node *it= NULL, *intersect;
01782 edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1;
01783 edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL, *cf;
01784 lmt_node *lmt= NULL, *local_min;
01785 polygon_node *tlist= NULL, *tn, *tnn, *p, *q;
01786 vertex_node *lt, *ltn, *rt, *rtn;
01787 h_state horiz[2];
01788 vertex_type cft;
01789 int in[2], exists[2], parity[2]= {LEFT, LEFT};
01790 int s, v, contributing, search, scanbeam= 0, sbt_entries= 0;
01791 int vclass, bl, br, tl, tr;
01792 double *sbt= NULL, xb, px, nx, yb, yt, dy, ix, iy;
01793
01794
01795 if (((subj->num_contours == 0) && (clip->num_contours == 0))
01796 || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF)))
01797 || ((clip->num_contours == 0) && (op == GPC_INT)))
01798 {
01799 result->num_strips= 0;
01800 result->strip= NULL;
01801 return;
01802 }
01803
01804
01805 if (((op == GPC_INT) || (op == GPC_DIFF))
01806 && (subj->num_contours > 0) && (clip->num_contours > 0))
01807 minimax_test(subj, clip, op);
01808
01809
01810 if (subj->num_contours > 0)
01811 s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op);
01812 if (clip->num_contours > 0)
01813 c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op);
01814
01815
01816 if (lmt == NULL)
01817 {
01818 result->num_strips= 0;
01819 result->strip= NULL;
01820 reset_lmt(&lmt);
01821 FREE(s_heap);
01822 FREE(c_heap);
01823 return;
01824 }
01825
01826
01827 MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double);
01828 build_sbt(&scanbeam, sbt, sbtree);
01829 scanbeam= 0;
01830 free_sbtree(&sbtree);
01831
01832
01833 if (op == GPC_DIFF)
01834 parity[CLIP]= RIGHT;
01835
01836 local_min= lmt;
01837
01838
01839 while (scanbeam < sbt_entries)
01840 {
01841
01842 yb= sbt[scanbeam++];
01843 if (scanbeam < sbt_entries)
01844 {
01845 yt= sbt[scanbeam];
01846 dy= yt - yb;
01847 }
01848
01849
01850
01851
01852 if (local_min)
01853 {
01854 if (local_min->y == yb)
01855 {
01856
01857 for (edge= local_min->first_bound; edge; edge= edge->next_bound)
01858 add_edge_to_aet(&aet, edge, NULL);
01859
01860 local_min= local_min->next;
01861 }
01862 }
01863
01864
01865 px= -DBL_MAX;
01866
01867
01868 e0= aet;
01869 e1= aet;
01870
01871
01872 aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb);
01873 aet->bundle[ABOVE][!aet->type]= FALSE;
01874 aet->bstate[ABOVE]= UNBUNDLED;
01875
01876 for (next_edge= aet->next; next_edge; next_edge= next_edge->next)
01877 {
01878
01879 next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb);
01880 next_edge->bundle[ABOVE][!next_edge->type]= FALSE;
01881 next_edge->bstate[ABOVE]= UNBUNDLED;
01882
01883
01884 if (next_edge->bundle[ABOVE][next_edge->type])
01885 {
01886 if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx)
01887 && (e0->top.y != yb))
01888 {
01889 next_edge->bundle[ABOVE][ next_edge->type]^=
01890 e0->bundle[ABOVE][ next_edge->type];
01891 next_edge->bundle[ABOVE][!next_edge->type]=
01892 e0->bundle[ABOVE][!next_edge->type];
01893 next_edge->bstate[ABOVE]= BUNDLE_HEAD;
01894 e0->bundle[ABOVE][CLIP]= FALSE;
01895 e0->bundle[ABOVE][SUBJ]= FALSE;
01896 e0->bstate[ABOVE]= BUNDLE_TAIL;
01897 }
01898 e0= next_edge;
01899 }
01900 }
01901
01902 horiz[CLIP]= NH;
01903 horiz[SUBJ]= NH;
01904
01905
01906 for (edge= aet; edge; edge= edge->next)
01907 {
01908 exists[CLIP]= edge->bundle[ABOVE][CLIP] +
01909 (edge->bundle[BELOW][CLIP] << 1);
01910 exists[SUBJ]= edge->bundle[ABOVE][SUBJ] +
01911 (edge->bundle[BELOW][SUBJ] << 1);
01912
01913 if (exists[CLIP] || exists[SUBJ])
01914 {
01915
01916 edge->bside[CLIP]= parity[CLIP];
01917 edge->bside[SUBJ]= parity[SUBJ];
01918
01919
01920 switch (op)
01921 {
01922 case GPC_DIFF:
01923 case GPC_INT:
01924 contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ]))
01925 || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP]))
01926 || (exists[CLIP] && exists[SUBJ]
01927 && (parity[CLIP] == parity[SUBJ]));
01928 br= (parity[CLIP])
01929 && (parity[SUBJ]);
01930 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01931 && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01932 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01933 && (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01934 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01935 && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01936 break;
01937 case GPC_XOR:
01938 contributing= exists[CLIP] || exists[SUBJ];
01939 br= (parity[CLIP])
01940 ^ (parity[SUBJ]);
01941 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01942 ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01943 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01944 ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01945 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01946 ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01947 break;
01948 case GPC_UNION:
01949 contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ]))
01950 || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP]))
01951 || (exists[CLIP] && exists[SUBJ]
01952 && (parity[CLIP] == parity[SUBJ]));
01953 br= (parity[CLIP])
01954 || (parity[SUBJ]);
01955 bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP])
01956 || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]);
01957 tr= (parity[CLIP] ^ (horiz[CLIP]!=NH))
01958 || (parity[SUBJ] ^ (horiz[SUBJ]!=NH));
01959 tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP])
01960 || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]);
01961 break;
01962 }
01963
01964
01965 parity[CLIP]^= edge->bundle[ABOVE][CLIP];
01966 parity[SUBJ]^= edge->bundle[ABOVE][SUBJ];
01967
01968
01969 if (exists[CLIP])
01970 horiz[CLIP]=
01971 next_h_state[horiz[CLIP]]
01972 [((exists[CLIP] - 1) << 1) + parity[CLIP]];
01973 if (exists[SUBJ])
01974 horiz[SUBJ]=
01975 next_h_state[horiz[SUBJ]]
01976 [((exists[SUBJ] - 1) << 1) + parity[SUBJ]];
01977
01978 vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
01979
01980 if (contributing)
01981 {
01982 xb= edge->xb;
01983
01984 switch (vclass)
01985 {
01986 case EMN:
01987 new_tristrip(&tlist, edge, xb, yb);
01988 cf= edge;
01989 break;
01990 case ERI:
01991 edge->outp[ABOVE]= cf->outp[ABOVE];
01992 if (xb != cf->xb)
01993 VERTEX(edge, ABOVE, RIGHT, xb, yb);
01994 cf= NULL;
01995 break;
01996 case ELI:
01997 VERTEX(edge, BELOW, LEFT, xb, yb);
01998 edge->outp[ABOVE]= NULL;
01999 cf= edge;
02000 break;
02001 case EMX:
02002 if (xb != cf->xb)
02003 VERTEX(edge, BELOW, RIGHT, xb, yb);
02004 edge->outp[ABOVE]= NULL;
02005 cf= NULL;
02006 break;
02007 case IMN:
02008 if (cft == LED)
02009 {
02010 if (cf->bot.y != yb)
02011 VERTEX(cf, BELOW, LEFT, cf->xb, yb);
02012 new_tristrip(&tlist, cf, cf->xb, yb);
02013 }
02014 edge->outp[ABOVE]= cf->outp[ABOVE];
02015 VERTEX(edge, ABOVE, RIGHT, xb, yb);
02016 break;
02017 case ILI:
02018 new_tristrip(&tlist, edge, xb, yb);
02019 cf= edge;
02020 cft= ILI;
02021 break;
02022 case IRI:
02023 if (cft == LED)
02024 {
02025 if (cf->bot.y != yb)
02026 VERTEX(cf, BELOW, LEFT, cf->xb, yb);
02027 new_tristrip(&tlist, cf, cf->xb, yb);
02028 }
02029 VERTEX(edge, BELOW, RIGHT, xb, yb);
02030 edge->outp[ABOVE]= NULL;
02031 break;
02032 case IMX:
02033 VERTEX(edge, BELOW, LEFT, xb, yb);
02034 edge->outp[ABOVE]= NULL;
02035 cft= IMX;
02036 break;
02037 case IMM:
02038 VERTEX(edge, BELOW, LEFT, xb, yb);
02039 edge->outp[ABOVE]= cf->outp[ABOVE];
02040 if (xb != cf->xb)
02041 VERTEX(cf, ABOVE, RIGHT, xb, yb);
02042 cf= edge;
02043 break;
02044 case EMM:
02045 VERTEX(edge, BELOW, RIGHT, xb, yb);
02046 edge->outp[ABOVE]= NULL;
02047 new_tristrip(&tlist, edge, xb, yb);
02048 cf= edge;
02049 break;
02050 case LED:
02051 if (edge->bot.y == yb)
02052 VERTEX(edge, BELOW, LEFT, xb, yb);
02053 edge->outp[ABOVE]= edge->outp[BELOW];
02054 cf= edge;
02055 cft= LED;
02056 break;
02057 case RED:
02058 edge->outp[ABOVE]= cf->outp[ABOVE];
02059 if (cft == LED)
02060 {
02061 if (cf->bot.y == yb)
02062 {
02063 VERTEX(edge, BELOW, RIGHT, xb, yb);
02064 }
02065 else
02066 {
02067 if (edge->bot.y == yb)
02068 {
02069 VERTEX(cf, BELOW, LEFT, cf->xb, yb);
02070 VERTEX(edge, BELOW, RIGHT, xb, yb);
02071 }
02072 }
02073 }
02074 else
02075 {
02076 VERTEX(edge, BELOW, RIGHT, xb, yb);
02077 VERTEX(edge, ABOVE, RIGHT, xb, yb);
02078 }
02079 cf= NULL;
02080 break;
02081 default:
02082 break;
02083 }
02084 }
02085 }
02086 }
02087
02088
02089 for (edge= aet; edge; edge= edge->next)
02090 {
02091 if (edge->top.y == yb)
02092 {
02093 prev_edge= edge->prev;
02094 next_edge= edge->next;
02095 if (prev_edge)
02096 prev_edge->next= next_edge;
02097 else
02098 aet= next_edge;
02099 if (next_edge)
02100 next_edge->prev= prev_edge;
02101
02102
02103 if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge)
02104 {
02105 if (prev_edge->bstate[BELOW] == BUNDLE_TAIL)
02106 {
02107 prev_edge->outp[BELOW]= edge->outp[BELOW];
02108 prev_edge->bstate[BELOW]= UNBUNDLED;
02109 if (prev_edge->prev)
02110 if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL)
02111 prev_edge->bstate[BELOW]= BUNDLE_HEAD;
02112 }
02113 }
02114 }
02115 else
02116 {
02117 if (edge->top.y == yt)
02118 edge->xt= edge->top.x;
02119 else
02120 edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y);
02121 }
02122 }
02123
02124 if (scanbeam < sbt_entries)
02125 {
02126
02127
02128 build_intersection_table(&it, aet, dy);
02129
02130
02131 for (intersect= it; intersect; intersect= intersect->next)
02132 {
02133 e0= intersect->ie[0];
02134 e1= intersect->ie[1];
02135
02136
02137 if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ])
02138 && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ]))
02139 {
02140 p= e0->outp[ABOVE];
02141 q= e1->outp[ABOVE];
02142 ix= intersect->point.x;
02143 iy= intersect->point.y + yb;
02144
02145 in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP])
02146 || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP])
02147 || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP]
02148 && e0->bside[CLIP] && e1->bside[CLIP]);
02149 in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ])
02150 || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ])
02151 || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ]
02152 && e0->bside[SUBJ] && e1->bside[SUBJ]);
02153
02154
02155 switch (op)
02156 {
02157 case GPC_DIFF:
02158 case GPC_INT:
02159 tr= (in[CLIP])
02160 && (in[SUBJ]);
02161 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
02162 && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
02163 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
02164 && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02165 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
02166 && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02167 break;
02168 case GPC_XOR:
02169 tr= (in[CLIP])
02170 ^ (in[SUBJ]);
02171 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
02172 ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
02173 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
02174 ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02175 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
02176 ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02177 break;
02178 case GPC_UNION:
02179 tr= (in[CLIP])
02180 || (in[SUBJ]);
02181 tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP])
02182 || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]);
02183 br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP])
02184 || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02185 bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP])
02186 || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]);
02187 break;
02188 }
02189
02190 vclass= tr + (tl << 1) + (br << 2) + (bl << 3);
02191
02192 switch (vclass)
02193 {
02194 case EMN:
02195 new_tristrip(&tlist, e1, ix, iy);
02196 e0->outp[ABOVE]= e1->outp[ABOVE];
02197 break;
02198 case ERI:
02199 if (p)
02200 {
02201 P_EDGE(prev_edge, e0, ABOVE, px, iy);
02202 VERTEX(prev_edge, ABOVE, LEFT, px, iy);
02203 VERTEX(e0, ABOVE, RIGHT, ix, iy);
02204 e1->outp[ABOVE]= e0->outp[ABOVE];
02205 e0->outp[ABOVE]= NULL;
02206 }
02207 break;
02208 case ELI:
02209 if (q)
02210 {
02211 N_EDGE(next_edge, e1, ABOVE, nx, iy);
02212 VERTEX(e1, ABOVE, LEFT, ix, iy);
02213 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02214 e0->outp[ABOVE]= e1->outp[ABOVE];
02215 e1->outp[ABOVE]= NULL;
02216 }
02217 break;
02218 case EMX:
02219 if (p && q)
02220 {
02221 VERTEX(e0, ABOVE, LEFT, ix, iy);
02222 e0->outp[ABOVE]= NULL;
02223 e1->outp[ABOVE]= NULL;
02224 }
02225 break;
02226 case IMN:
02227 P_EDGE(prev_edge, e0, ABOVE, px, iy);
02228 VERTEX(prev_edge, ABOVE, LEFT, px, iy);
02229 N_EDGE(next_edge, e1, ABOVE, nx, iy);
02230 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02231 new_tristrip(&tlist, prev_edge, px, iy);
02232 e1->outp[ABOVE]= prev_edge->outp[ABOVE];
02233 VERTEX(e1, ABOVE, RIGHT, ix, iy);
02234 new_tristrip(&tlist, e0, ix, iy);
02235 next_edge->outp[ABOVE]= e0->outp[ABOVE];
02236 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02237 break;
02238 case ILI:
02239 if (p)
02240 {
02241 VERTEX(e0, ABOVE, LEFT, ix, iy);
02242 N_EDGE(next_edge, e1, ABOVE, nx, iy);
02243 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02244 e1->outp[ABOVE]= e0->outp[ABOVE];
02245 e0->outp[ABOVE]= NULL;
02246 }
02247 break;
02248 case IRI:
02249 if (q)
02250 {
02251 VERTEX(e1, ABOVE, RIGHT, ix, iy);
02252 P_EDGE(prev_edge, e0, ABOVE, px, iy);
02253 VERTEX(prev_edge, ABOVE, LEFT, px, iy);
02254 e0->outp[ABOVE]= e1->outp[ABOVE];
02255 e1->outp[ABOVE]= NULL;
02256 }
02257 break;
02258 case IMX:
02259 if (p && q)
02260 {
02261 VERTEX(e0, ABOVE, RIGHT, ix, iy);
02262 VERTEX(e1, ABOVE, LEFT, ix, iy);
02263 e0->outp[ABOVE]= NULL;
02264 e1->outp[ABOVE]= NULL;
02265 P_EDGE(prev_edge, e0, ABOVE, px, iy);
02266 VERTEX(prev_edge, ABOVE, LEFT, px, iy);
02267 new_tristrip(&tlist, prev_edge, px, iy);
02268 N_EDGE(next_edge, e1, ABOVE, nx, iy);
02269 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02270 next_edge->outp[ABOVE]= prev_edge->outp[ABOVE];
02271 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02272 }
02273 break;
02274 case IMM:
02275 if (p && q)
02276 {
02277 VERTEX(e0, ABOVE, RIGHT, ix, iy);
02278 VERTEX(e1, ABOVE, LEFT, ix, iy);
02279 P_EDGE(prev_edge, e0, ABOVE, px, iy);
02280 VERTEX(prev_edge, ABOVE, LEFT, px, iy);
02281 new_tristrip(&tlist, prev_edge, px, iy);
02282 N_EDGE(next_edge, e1, ABOVE, nx, iy);
02283 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02284 e1->outp[ABOVE]= prev_edge->outp[ABOVE];
02285 VERTEX(e1, ABOVE, RIGHT, ix, iy);
02286 new_tristrip(&tlist, e0, ix, iy);
02287 next_edge->outp[ABOVE]= e0->outp[ABOVE];
02288 VERTEX(next_edge, ABOVE, RIGHT, nx, iy);
02289 }
02290 break;
02291 case EMM:
02292 if (p && q)
02293 {
02294 VERTEX(e0, ABOVE, LEFT, ix, iy);
02295 new_tristrip(&tlist, e1, ix, iy);
02296 e0->outp[ABOVE]= e1->outp[ABOVE];
02297 }
02298 break;
02299 default:
02300 break;
02301 }
02302 }
02303
02304
02305 if (e0->bundle[ABOVE][CLIP])
02306 e1->bside[CLIP]= !e1->bside[CLIP];
02307 if (e1->bundle[ABOVE][CLIP])
02308 e0->bside[CLIP]= !e0->bside[CLIP];
02309 if (e0->bundle[ABOVE][SUBJ])
02310 e1->bside[SUBJ]= !e1->bside[SUBJ];
02311 if (e1->bundle[ABOVE][SUBJ])
02312 e0->bside[SUBJ]= !e0->bside[SUBJ];
02313
02314
02315 prev_edge= e0->prev;
02316 next_edge= e1->next;
02317 if (e1->next)
02318 e1->next->prev= e0;
02319
02320 if (e0->bstate[ABOVE] == BUNDLE_HEAD)
02321 {
02322 search= TRUE;
02323 while (search)
02324 {
02325 prev_edge= prev_edge->prev;
02326 if (prev_edge)
02327 {
02328 if (prev_edge->bundle[ABOVE][CLIP]
02329 || prev_edge->bundle[ABOVE][SUBJ]
02330 || (prev_edge->bstate[ABOVE] == BUNDLE_HEAD))
02331 search= FALSE;
02332 }
02333 else
02334 search= FALSE;
02335 }
02336 }
02337 if (!prev_edge)
02338 {
02339 e1->next= aet;
02340 aet= e0->next;
02341 }
02342 else
02343 {
02344 e1->next= prev_edge->next;
02345 prev_edge->next= e0->next;
02346 }
02347 e0->next->prev= prev_edge;
02348 e1->next->prev= e1;
02349 e0->next= next_edge;
02350 }
02351
02352
02353 for (edge= aet; edge; edge= next_edge)
02354 {
02355 next_edge= edge->next;
02356 succ_edge= edge->succ;
02357
02358 if ((edge->top.y == yt) && succ_edge)
02359 {
02360
02361 succ_edge->outp[BELOW]= edge->outp[ABOVE];
02362 succ_edge->bstate[BELOW]= edge->bstate[ABOVE];
02363 succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
02364 succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
02365 prev_edge= edge->prev;
02366 if (prev_edge)
02367 prev_edge->next= succ_edge;
02368 else
02369 aet= succ_edge;
02370 if (next_edge)
02371 next_edge->prev= succ_edge;
02372 succ_edge->prev= prev_edge;
02373 succ_edge->next= next_edge;
02374 }
02375 else
02376 {
02377
02378 edge->outp[BELOW]= edge->outp[ABOVE];
02379 edge->bstate[BELOW]= edge->bstate[ABOVE];
02380 edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP];
02381 edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ];
02382 edge->xb= edge->xt;
02383 }
02384 edge->outp[ABOVE]= NULL;
02385 }
02386 }
02387 }
02388
02389
02390 result->strip= NULL;
02391 result->num_strips= count_tristrips(tlist);
02392 if (result->num_strips > 0)
02393 {
02394 MALLOC(result->strip, result->num_strips * sizeof(gpc_vertex_list),
02395 "tristrip list creation", gpc_vertex_list);
02396
02397 s= 0;
02398 for (tn= tlist; tn; tn= tnn)
02399 {
02400 tnn= tn->next;
02401
02402 if (tn->active > 2)
02403 {
02404
02405 result->strip[s].num_vertices= tn->active;
02406 MALLOC(result->strip[s].vertex, tn->active * sizeof(gpc_vertex),
02407 "tristrip creation", gpc_vertex);
02408 v= 0;
02409 if (INVERT_TRISTRIPS)
02410 {
02411 lt= tn->v[RIGHT];
02412 rt= tn->v[LEFT];
02413 }
02414 else
02415 {
02416 lt= tn->v[LEFT];
02417 rt= tn->v[RIGHT];
02418 }
02419 while (lt || rt)
02420 {
02421 if (lt)
02422 {
02423 ltn= lt->next;
02424 result->strip[s].vertex[v].x= lt->x;
02425 result->strip[s].vertex[v].y= lt->y;
02426 v++;
02427 FREE(lt);
02428 lt= ltn;
02429 }
02430 if (rt)
02431 {
02432 rtn= rt->next;
02433 result->strip[s].vertex[v].x= rt->x;
02434 result->strip[s].vertex[v].y= rt->y;
02435 v++;
02436 FREE(rt);
02437 rt= rtn;
02438 }
02439 }
02440 s++;
02441 }
02442 else
02443 {
02444
02445 for (lt= tn->v[LEFT]; lt; lt= ltn)
02446 {
02447 ltn= lt->next;
02448 FREE(lt);
02449 }
02450 for (rt= tn->v[RIGHT]; rt; rt=rtn)
02451 {
02452 rtn= rt->next;
02453 FREE(rt);
02454 }
02455 }
02456 FREE(tn);
02457 }
02458 }
02459
02460
02461 reset_it(&it);
02462 reset_lmt(&lmt);
02463 FREE(c_heap);
02464 FREE(s_heap);
02465 FREE(sbt);
02466 }
02467
02468
02469
02470
02471
02472