|
|
1.1 ! root 1: /* $Header: mipoly.h,v 1.1 87/09/11 07:20:03 toddb Exp $ */ ! 2: /* ! 3: * fill.h ! 4: * ! 5: * Created by Brian Kelleher; Oct 1985 ! 6: * ! 7: * Include file for filled polygon routines. ! 8: * ! 9: * These are the data structures needed to scan ! 10: * convert regions. Two different scan conversion ! 11: * methods are available -- the even-odd method, and ! 12: * the winding number method. ! 13: * The even-odd rule states that a point is inside ! 14: * the polygon if a ray drawn from that point in any ! 15: * direction will pass through an odd number of ! 16: * path segments. ! 17: * By the winding number rule, a point is decided ! 18: * to be inside the polygon if a ray drawn from that ! 19: * point in any direction passes through a different ! 20: * number of clockwise and counter-clockwise path ! 21: * segments. ! 22: * ! 23: * These data structures are adapted somewhat from ! 24: * the algorithm in (Foley/Van Dam) for scan converting ! 25: * polygons. ! 26: * The basic algorithm is to start at the top (smallest y) ! 27: * of the polygon, stepping down to the bottom of ! 28: * the polygon by incrementing the y coordinate. We ! 29: * keep a list of edges which the current scanline crosses, ! 30: * sorted by x. This list is called the Active Edge Table (AET) ! 31: * As we change the y-coordinate, we update each entry in ! 32: * in the active edge table to reflect the edges new xcoord. ! 33: * This list must be sorted at each scanline in case ! 34: * two edges intersect. ! 35: * We also keep a data structure known as the Edge Table (ET), ! 36: * which keeps track of all the edges which the current ! 37: * scanline has not yet reached. The ET is basically a ! 38: * list of ScanLineList structures containing a list of ! 39: * edges which are entered at a given scanline. There is one ! 40: * ScanLineList per scanline at which an edge is entered. ! 41: * When we enter a new edge, we move it from the ET to the AET. ! 42: * ! 43: * From the AET, we can implement the even-odd rule as in ! 44: * (Foley/Van Dam). ! 45: * The winding number rule is a little trickier. We also ! 46: * keep the EdgeTableEntries in the AET linked by the ! 47: * nextWETE (winding EdgeTableEntry) link. This allows ! 48: * the edges to be linked just as before for updating ! 49: * purposes, but only uses the edges linked by the nextWETE ! 50: * link as edges representing spans of the polygon to ! 51: * drawn (as with the even-odd rule). ! 52: */ ! 53: ! 54: /* ! 55: * for the winding number rule ! 56: */ ! 57: #define CLOCKWISE 1 ! 58: #define COUNTERCLOCKWISE -1 ! 59: ! 60: typedef struct _EdgeTableEntry { ! 61: int ymax; /* ycoord at which we exit this edge. */ ! 62: BRESINFO bres; /* Bresenham info to run the edge */ ! 63: struct _EdgeTableEntry *next; /* next in the list */ ! 64: struct _EdgeTableEntry *back; /* for insertion sort */ ! 65: struct _EdgeTableEntry *nextWETE; /* for winding num rule */ ! 66: int ClockWise; /* flag for winding number rule */ ! 67: } EdgeTableEntry; ! 68: ! 69: ! 70: typedef struct _ScanLineList{ ! 71: int scanline; /* the scanline represented */ ! 72: EdgeTableEntry *edgelist; /* header node */ ! 73: struct _ScanLineList *next; /* next in the list */ ! 74: } ScanLineList; ! 75: ! 76: ! 77: typedef struct { ! 78: int ymax; /* ymax for the polygon */ ! 79: int ymin; /* ymin for the polygon */ ! 80: ScanLineList scanlines; /* header node */ ! 81: } EdgeTable; ! 82: ! 83: ! 84: /* ! 85: * Here is a struct to help with storage allocation ! 86: * so we can allocate a big chunk at a time, and then take ! 87: * pieces from this heap when we need to. ! 88: */ ! 89: #define SLLSPERBLOCK 25 ! 90: ! 91: typedef struct _ScanLineListBlock { ! 92: ScanLineList SLLs[SLLSPERBLOCK]; ! 93: struct _ScanLineListBlock *next; ! 94: } ScanLineListBlock; ! 95: ! 96: /* ! 97: * number of points to buffer before sending them off ! 98: * to scanlines() : Must be an even number ! 99: */ ! 100: #define NUMPTSTOBUFFER 200 ! 101: ! 102: ! 103: /* ! 104: * ! 105: * a few macros for the inner loops of the fill code where ! 106: * performance considerations don't allow a procedure call. ! 107: * ! 108: * Evaluate the given edge at the given scanline. ! 109: * If the edge has expired, then we leave it and fix up ! 110: * the active edge table; otherwise, we increment the ! 111: * x value to be ready for the next scanline. ! 112: * The winding number rule is in effect, so we must notify ! 113: * the caller when the edge has been removed so he ! 114: * can reorder the Winding Active Edge Table. ! 115: */ ! 116: #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ ! 117: if (pAET->ymax == y) { /* leaving this edge */ \ ! 118: pPrevAET->next = pAET->next; \ ! 119: pAET = pPrevAET->next; \ ! 120: fixWAET = 1; \ ! 121: if (pAET) \ ! 122: pAET->back = pPrevAET; \ ! 123: } \ ! 124: else { \ ! 125: BRESINCRPGONSTRUCT(pAET->bres); \ ! 126: pPrevAET = pAET; \ ! 127: pAET = pAET->next; \ ! 128: } \ ! 129: } ! 130: ! 131: ! 132: /* ! 133: * Evaluate the given edge at the given scanline. ! 134: * If the edge has expired, then we leave it and fix up ! 135: * the active edge table; otherwise, we increment the ! 136: * x value to be ready for the next scanline. ! 137: * The even-odd rule is in effect. ! 138: */ ! 139: #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ ! 140: if (pAET->ymax == y) { /* leaving this edge */ \ ! 141: pPrevAET->next = pAET->next; \ ! 142: pAET = pPrevAET->next; \ ! 143: if (pAET) \ ! 144: pAET->back = pPrevAET; \ ! 145: } \ ! 146: else { \ ! 147: BRESINCRPGONSTRUCT(pAET->bres); \ ! 148: pPrevAET = pAET; \ ! 149: pAET = pAET->next; \ ! 150: } \ ! 151: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.