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 #define LARGE_COORDINATE 1000000
0045 #define SMALL_COORDINATE -LARGE_COORDINATE
0046 
0047 #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
0048     int dx;      /* local storage */ \
0049 \
0050     /* \
0051      *  if the edge is horizontal, then it is ignored \
0052      *  and assumed not to be processed.  Otherwise, do this stuff. \
0053      */ \
0054     if ((dy) != 0) { \
0055         xStart = (x1); \
0056         dx = (x2) - xStart; \
0057         if (dx < 0) { \
0058             m = dx / (dy); \
0059             m1 = m - 1; \
0060             incr1 = -2 * dx + 2 * (dy) * m1; \
0061             incr2 = -2 * dx + 2 * (dy) * m; \
0062             d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
0063         } else { \
0064             m = dx / (dy); \
0065             m1 = m + 1; \
0066             incr1 = 2 * dx - 2 * (dy) * m1; \
0067             incr2 = 2 * dx - 2 * (dy) * m; \
0068             d = -2 * m * (dy) + 2 * dx; \
0069         } \
0070     } \
0071 }
0072 
0073 #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
0074     if (m1 > 0) { \
0075         if (d > 0) { \
0076             minval += m1; \
0077             d += incr1; \
0078         } \
0079         else { \
0080             minval += m; \
0081             d += incr2; \
0082         } \
0083     } else {\
0084         if (d >= 0) { \
0085             minval += m1; \
0086             d += incr1; \
0087         } \
0088         else { \
0089             minval += m; \
0090             d += incr2; \
0091         } \
0092     } \
0093 }
0094 
0095 
0096 /*
0097  *     This structure contains all of the information needed
0098  *     to run the bresenham algorithm.
0099  *     The variables may be hardcoded into the declarations
0100  *     instead of using this structure to make use of
0101  *     register declarations.
0102  */
0103 typedef struct {
0104     int minor_axis;     /* minor axis        */
0105     int d;              /* decision variable */
0106     int m, m1;          /* slope and slope+1 */
0107     int incr1, incr2;   /* error increments */
0108 } BRESINFO;
0109 
0110 
0111 #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
0112         BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
0113                      bres.m, bres.m1, bres.incr1, bres.incr2)
0114 
0115 #define BRESINCRPGONSTRUCT(bres) \
0116         BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
0117 
0118 
0119 
0120 /*
0121  *     These are the data structures needed to scan
0122  *     convert regions.  Two different scan conversion
0123  *     methods are available -- the even-odd method, and
0124  *     the winding number method.
0125  *     The even-odd rule states that a point is inside
0126  *     the polygon if a ray drawn from that point in any
0127  *     direction will pass through an odd number of
0128  *     path segments.
0129  *     By the winding number rule, a point is decided
0130  *     to be inside the polygon if a ray drawn from that
0131  *     point in any direction passes through a different
0132  *     number of clockwise and counter-clockwise path
0133  *     segments.
0134  *
0135  *     These data structures are adapted somewhat from
0136  *     the algorithm in (Foley/Van Dam) for scan converting
0137  *     polygons.
0138  *     The basic algorithm is to start at the top (smallest y)
0139  *     of the polygon, stepping down to the bottom of
0140  *     the polygon by incrementing the y coordinate.  We
0141  *     keep a list of edges which the current scanline crosses,
0142  *     sorted by x.  This list is called the Active Edge Table (AET)
0143  *     As we change the y-coordinate, we update each entry in
0144  *     in the active edge table to reflect the edges new xcoord.
0145  *     This list must be sorted at each scanline in case
0146  *     two edges intersect.
0147  *     We also keep a data structure known as the Edge Table (ET),
0148  *     which keeps track of all the edges which the current
0149  *     scanline has not yet reached.  The ET is basically a
0150  *     list of ScanLineList structures containing a list of
0151  *     edges which are entered at a given scanline.  There is one
0152  *     ScanLineList per scanline at which an edge is entered.
0153  *     When we enter a new edge, we move it from the ET to the AET.
0154  *
0155  *     From the AET, we can implement the even-odd rule as in
0156  *     (Foley/Van Dam).
0157  *     The winding number rule is a little trickier.  We also
0158  *     keep the EdgeTableEntries in the AET linked by the
0159  *     nextWETE (winding EdgeTableEntry) link.  This allows
0160  *     the edges to be linked just as before for updating
0161  *     purposes, but only uses the edges linked by the nextWETE
0162  *     link as edges representing spans of the polygon to
0163  *     drawn (as with the even-odd rule).
0164  */
0165 
0166 /*
0167  * for the winding number rule
0168  */
0169 //#define CLOCKWISE          1
0170 //#define COUNTERCLOCKWISE  -1
0171 
0172 typedef struct _EdgeTableEntry {
0173      int ymax;             /* ycoord at which we exit this edge. */
0174      BRESINFO bres;        /* Bresenham info to run the edge     */
0175      struct _EdgeTableEntry *next;       /* next in the list     */
0176      struct _EdgeTableEntry *back;       /* for insertion sort   */
0177      struct _EdgeTableEntry *nextWETE;   /* for winding num rule */
0178      int ClockWise;        /* flag for winding number rule       */
0179 } EdgeTableEntry;
0180 
0181 
0182 typedef struct _ScanLineList{
0183      int scanline;              /* the scanline represented */
0184      EdgeTableEntry *edgelist;  /* header node              */
0185      struct _ScanLineList *next;  /* next in the list       */
0186 } ScanLineList;
0187 
0188 
0189 typedef struct {
0190      int ymax;                 /* ymax for the polygon     */
0191      int ymin;                 /* ymin for the polygon     */
0192      ScanLineList scanlines;   /* header node              */
0193 } EdgeTable;
0194 
0195 
0196 /*
0197  * Here is a struct to help with storage allocation
0198  * so we can allocate a big chunk at a time, and then take
0199  * pieces from this heap when we need to.
0200  */
0201 #define SLLSPERBLOCK 25
0202 
0203 typedef struct _ScanLineListBlock {
0204      ScanLineList SLLs[SLLSPERBLOCK];
0205      struct _ScanLineListBlock *next;
0206 } ScanLineListBlock;
0207 
0208 
0209 
0210 /*
0211  *
0212  *     a few macros for the inner loops of the fill code where
0213  *     performance considerations don't allow a procedure call.
0214  *
0215  *     Evaluate the given edge at the given scanline.
0216  *     If the edge has expired, then we leave it and fix up
0217  *     the active edge table; otherwise, we increment the
0218  *     x value to be ready for the next scanline.
0219  *     The winding number rule is in effect, so we must notify
0220  *     the caller when the edge has been removed so he
0221  *     can reorder the Winding Active Edge Table.
0222  */
0223 #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
0224    if (pAET->ymax == y) {          /* leaving this edge */ \
0225       pPrevAET->next = pAET->next; \
0226       pAET = pPrevAET->next; \
0227       fixWAET = 1; \
0228       if (pAET) \
0229          pAET->back = pPrevAET; \
0230    } \
0231    else { \
0232       BRESINCRPGONSTRUCT(pAET->bres) \
0233       pPrevAET = pAET; \
0234       pAET = pAET->next; \
0235    } \
0236 }
0237 
0238 
0239 /*
0240  *     Evaluate the given edge at the given scanline.
0241  *     If the edge has expired, then we leave it and fix up
0242  *     the active edge table; otherwise, we increment the
0243  *     x value to be ready for the next scanline.
0244  *     The even-odd rule is in effect.
0245  */
0246 #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
0247    if (pAET->ymax == y) {          /* leaving this edge */ \
0248       pPrevAET->next = pAET->next; \
0249       pAET = pPrevAET->next; \
0250       if (pAET) \
0251          pAET->back = pPrevAET; \
0252    } \
0253    else { \
0254       BRESINCRPGONSTRUCT(pAET->bres) \
0255       pPrevAET = pAET; \
0256       pAET = pAET->next; \
0257    } \
0258 }
0259 
0260 
0261 #endif