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