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