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