Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/zb/line is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_zb_line
0005 #define tools_zb_line
0006 
0007 /* from X/poly.h */
0008 
0009 /*
0010  *     This file contains a few macros to help track
0011  *     the edge of a filled object.  The object is assumed
0012  *     to be filled in scanline order, and thus the
0013  *     algorithm used is an extension of Bresenham's line
0014  *     drawing algorithm which assumes that y is always the
0015  *     major axis.
0016  *     Since these pieces of code are the same for any filled shape,
0017  *     it is more convenient to gather the library in one
0018  *     place, but since these pieces of code are also in
0019  *     the inner loops of output primitives, procedure call
0020  *     overhead is out of the question.
0021  *     See the author for a derivation if needed.
0022  */
0023 
0024 
0025 /*
0026  *  In scan converting polygons, we want to choose those pixels
0027  *  which are inside the polygon.  Thus, we add .5 to the starting
0028  *  x coordinate for both left and right edges.  Now we choose the
0029  *  first pixel which is inside the pgon for the left edge and the
0030  *  first pixel which is outside the pgon for the right edge.
0031  *  Draw the left pixel, but not the right.
0032  *
0033  *  How to add .5 to the starting x coordinate:
0034  *      If the edge is moving to the right, then subtract dy from the
0035  *  error term from the general form of the algorithm.
0036  *      If the edge is moving to the left, then add dy to the error term.
0037  *
0038  *  The reason for the difference between edges moving to the left
0039  *  and edges moving to the right is simple:  If an edge is moving
0040  *  to the right, then we want the algorithm to flip immediately.
0041  *  If it is moving to the left, then we don't want it to flip until
0042  *  we traverse an entire pixel.
0043  */
0044 
0045 #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
0046     int dx;      /* local storage */ \
0047 \
0048     /* \
0049      *  if the edge is horizontal, then it is ignored \
0050      *  and assumed not to be processed.  Otherwise, do this stuff. \
0051      */ \
0052     if ((dy) != 0) { \
0053         xStart = (x1); \
0054         dx = (x2) - xStart; \
0055         if (dx < 0) { \
0056             m = dx / (dy); \
0057             m1 = m - 1; \
0058             incr1 = -2 * dx + 2 * (dy) * m1; \
0059             incr2 = -2 * dx + 2 * (dy) * m; \
0060             d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
0061         } else { \
0062             m = dx / (dy); \
0063             m1 = m + 1; \
0064             incr1 = 2 * dx - 2 * (dy) * m1; \
0065             incr2 = 2 * dx - 2 * (dy) * m; \
0066             d = -2 * m * (dy) + 2 * dx; \
0067         } \
0068     } \
0069 }
0070 
0071 #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
0072     if (m1 > 0) { \
0073         if (d > 0) { \
0074             minval += m1; \
0075             d += incr1; \
0076         } \
0077         else { \
0078             minval += m; \
0079             d += incr2; \
0080         } \
0081     } else {\
0082         if (d >= 0) { \
0083             minval += m1; \
0084             d += incr1; \
0085         } \
0086         else { \
0087             minval += m; \
0088             d += incr2; \
0089         } \
0090     } \
0091 }
0092 
0093 
0094 /*
0095  *     This structure contains all of the information needed
0096  *     to run the bresenham algorithm.
0097  *     The variables may be hardcoded into the declarations
0098  *     instead of using this structure to make use of
0099  *     register declarations.
0100  */
0101 typedef struct {
0102     int minor_axis;     /* minor axis        */
0103     int d;              /* decision variable */
0104     int m, m1;          /* slope and slope+1 */
0105     int incr1, incr2;   /* error increments */
0106 } BRESINFO;
0107 
0108 
0109 #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
0110         BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
0111                      bres.m, bres.m1, bres.incr1, bres.incr2)
0112 
0113 #define BRESINCRPGONSTRUCT(bres) \
0114         BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
0115 
0116 
0117 
0118 /*
0119  *     These are the data structures needed to scan
0120  *     convert regions.  Two different scan conversion
0121  *     methods are available -- the even-odd method, and
0122  *     the winding number method.
0123  *     The even-odd rule states that a point is inside
0124  *     the polygon if a ray drawn from that point in any
0125  *     direction will pass through an odd number of
0126  *     path segments.
0127  *     By the winding number rule, a point is decided
0128  *     to be inside the polygon if a ray drawn from that
0129  *     point in any direction passes through a different
0130  *     number of clockwise and counter-clockwise path
0131  *     segments.
0132  *
0133  *     These data structures are adapted somewhat from
0134  *     the algorithm in (Foley/Van Dam) for scan converting
0135  *     polygons.
0136  *     The basic algorithm is to start at the top (smallest y)
0137  *     of the polygon, stepping down to the bottom of
0138  *     the polygon by incrementing the y coordinate.  We
0139  *     keep a list of edges which the current scanline crosses,
0140  *     sorted by x.  This list is called the Active Edge Table (AET)
0141  *     As we change the y-coordinate, we update each entry in
0142  *     in the active edge table to reflect the edges new xcoord.
0143  *     This list must be sorted at each scanline in case
0144  *     two edges intersect.
0145  *     We also keep a data structure known as the Edge Table (ET),
0146  *     which keeps track of all the edges which the current
0147  *     scanline has not yet reached.  The ET is basically a
0148  *     list of ScanLineList structures containing a list of
0149  *     edges which are entered at a given scanline.  There is one
0150  *     ScanLineList per scanline at which an edge is entered.
0151  *     When we enter a new edge, we move it from the ET to the AET.
0152  *
0153  *     From the AET, we can implement the even-odd rule as in
0154  *     (Foley/Van Dam).
0155  *     The winding number rule is a little trickier.  We also
0156  *     keep the EdgeTableEntries in the AET linked by the
0157  *     nextWETE (winding EdgeTableEntry) link.  This allows
0158  *     the edges to be linked just as before for updating
0159  *     purposes, but only uses the edges linked by the nextWETE
0160  *     link as edges representing spans of the polygon to
0161  *     drawn (as with the even-odd rule).
0162  */
0163 
0164 /*
0165  * for the winding number rule
0166  */
0167 //#define CLOCKWISE          1
0168 //#define COUNTERCLOCKWISE  -1
0169 
0170 typedef struct _EdgeTableEntry {
0171      int ymax;             /* ycoord at which we exit this edge. */
0172      BRESINFO bres;        /* Bresenham info to run the edge     */
0173      struct _EdgeTableEntry *next;       /* next in the list     */
0174      struct _EdgeTableEntry *back;       /* for insertion sort   */
0175      struct _EdgeTableEntry *nextWETE;   /* for winding num rule */
0176      int ClockWise;        /* flag for winding number rule       */
0177 } EdgeTableEntry;
0178 
0179 
0180 typedef struct _ScanLineList{
0181      int scanline;              /* the scanline represented */
0182      EdgeTableEntry *edgelist;  /* header node              */
0183      struct _ScanLineList *next;  /* next in the list       */
0184 } ScanLineList;
0185 
0186 
0187 typedef struct {
0188      int ymax;                 /* ymax for the polygon     */
0189      int ymin;                 /* ymin for the polygon     */
0190      ScanLineList scanlines;   /* header node              */
0191 } EdgeTable;
0192 
0193 
0194 /*
0195  * Here is a struct to help with storage allocation
0196  * so we can allocate a big chunk at a time, and then take
0197  * pieces from this heap when we need to.
0198  */
0199 #define SLLSPERBLOCK 25
0200 
0201 typedef struct _ScanLineListBlock {
0202      ScanLineList SLLs[SLLSPERBLOCK];
0203      struct _ScanLineListBlock *next;
0204 } ScanLineListBlock;
0205 
0206 
0207 
0208 /*
0209  *
0210  *     a few macros for the inner loops of the fill code where
0211  *     performance considerations don't allow a procedure call.
0212  *
0213  *     Evaluate the given edge at the given scanline.
0214  *     If the edge has expired, then we leave it and fix up
0215  *     the active edge table; otherwise, we increment the
0216  *     x value to be ready for the next scanline.
0217  *     The winding number rule is in effect, so we must notify
0218  *     the caller when the edge has been removed so he
0219  *     can reorder the Winding Active Edge Table.
0220  */
0221 #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
0222    if (pAET->ymax == y) {          /* leaving this edge */ \
0223       pPrevAET->next = pAET->next; \
0224       pAET = pPrevAET->next; \
0225       fixWAET = 1; \
0226       if (pAET) \
0227          pAET->back = pPrevAET; \
0228    } \
0229    else { \
0230       BRESINCRPGONSTRUCT(pAET->bres) \
0231       pPrevAET = pAET; \
0232       pAET = pAET->next; \
0233    } \
0234 }
0235 
0236 
0237 /*
0238  *     Evaluate the given edge at the given scanline.
0239  *     If the edge has expired, then we leave it and fix up
0240  *     the active edge table; otherwise, we increment the
0241  *     x value to be ready for the next scanline.
0242  *     The even-odd rule is in effect.
0243  */
0244 #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
0245    if (pAET->ymax == y) {          /* leaving this edge */ \
0246       pPrevAET->next = pAET->next; \
0247       pAET = pPrevAET->next; \
0248       if (pAET) \
0249          pAET->back = pPrevAET; \
0250    } \
0251    else { \
0252       BRESINCRPGONSTRUCT(pAET->bres) \
0253       pPrevAET = pAET; \
0254       pAET = pAET->next; \
0255    } \
0256 }
0257 
0258 
0259 #endif