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