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


libgpc
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:02:04