|
|
1.1 root 1: /* $Header: poly.h,v 1.1 87/09/11 08:15:38 toddb Exp $ */
2: /************************************************************************
3: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
4: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
5:
6: All Rights Reserved
7:
8: Permission to use, copy, modify, and distribute this software and its
9: documentation for any purpose and without fee is hereby granted,
10: provided that the above copyright notice appear in all copies and that
11: both that copyright notice and this permission notice appear in
12: supporting documentation, and that the names of Digital or MIT not be
13: used in advertising or publicity pertaining to distribution of the
14: software without specific, written prior permission.
15:
16: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22: SOFTWARE.
23:
24: ************************************************************************/
25: #define NULL 0
26:
27:
28: /*
29: * This file contains a few macros to help track
30: * the edge of a filled object. The object is assumed
31: * to be filled in scanline order, and thus the
32: * algorithm used is an extension of Bresenham's line
33: * drawing algorithm which assumes that y is always the
34: * major axis.
35: * Since these pieces of code are the same for any filled shape,
36: * it is more convenient to gather the library in one
37: * place, but since these pieces of code are also in
38: * the inner loops of output primitives, procedure call
39: * overhead is out of the question.
40: * See the author for a derivation if needed.
41: */
42:
43:
44: /*
45: * In scan converting polygons, we want to choose those pixels
46: * which are inside the polygon. Thus, we add .5 to the starting
47: * x coordinate for both left and right edges. Now we choose the
48: * first pixel which is inside the pgon for the left edge and the
49: * first pixel which is outside the pgon for the right edge.
50: * Draw the left pixel, but not the right.
51: *
52: * How to add .5 to the starting x coordinate:
53: * If the edge is moving to the right, then subtract dy from the
54: * error term from the general form of the algorithm.
55: * If the edge is moving to the left, then add dy to the error term.
56: *
57: * The reason for the difference between edges moving to the left
58: * and edges moving to the right is simple: If an edge is moving
59: * to the right, then we want the algorithm to flip immediately.
60: * If it is moving to the left, then we don't want it to flip until
61: * we traverse an entire pixel.
62: */
63: #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
64: int dx; /* local storage */ \
65: \
66: /* \
67: * if the edge is horizontal, then it is ignored \
68: * and assumed not to be processed. Otherwise, do this stuff. \
69: */ \
70: if ((dy) != 0) { \
71: xStart = (x1); \
72: dx = (x2) - xStart; \
73: if (dx < 0) { \
74: m = dx / (dy); \
75: m1 = m - 1; \
76: incr1 = -2 * dx + 2 * (dy) * m1; \
77: incr2 = -2 * dx + 2 * (dy) * m; \
78: d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
79: } else { \
80: m = dx / (dy); \
81: m1 = m + 1; \
82: incr1 = 2 * dx - 2 * (dy) * m1; \
83: incr2 = 2 * dx - 2 * (dy) * m; \
84: d = -2 * m * (dy) + 2 * dx; \
85: } \
86: } \
87: }
88:
89: #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
90: if (m1 > 0) { \
91: if (d > 0) { \
92: minval += m1; \
93: d += incr1; \
94: } \
95: else { \
96: minval += m; \
97: d += incr2; \
98: } \
99: } else {\
100: if (d >= 0) { \
101: minval += m1; \
102: d += incr1; \
103: } \
104: else { \
105: minval += m; \
106: d += incr2; \
107: } \
108: } \
109: }
110:
111:
112: /*
113: * This structure contains all of the information needed
114: * to run the bresenham algorithm.
115: * The variables may be hardcoded into the declarations
116: * instead of using this structure to make use of
117: * register declarations.
118: */
119: typedef struct {
120: int minor_axis; /* minor axis */
121: int d; /* decision variable */
122: int m, m1; /* slope and slope+1 */
123: int incr1, incr2; /* error increments */
124: } BRESINFO;
125:
126:
127: #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
128: BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
129: bres.m, bres.m1, bres.incr1, bres.incr2)
130:
131: #define BRESINCRPGONSTRUCT(bres) \
132: BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
133:
134:
135:
136: /*
137: * These are the data structures needed to scan
138: * convert regions. Two different scan conversion
139: * methods are available -- the even-odd method, and
140: * the winding number method.
141: * The even-odd rule states that a point is inside
142: * the polygon if a ray drawn from that point in any
143: * direction will pass through an odd number of
144: * path segments.
145: * By the winding number rule, a point is decided
146: * to be inside the polygon if a ray drawn from that
147: * point in any direction passes through a different
148: * number of clockwise and counter-clockwise path
149: * segments.
150: *
151: * These data structures are adapted somewhat from
152: * the algorithm in (Foley/Van Dam) for scan converting
153: * polygons.
154: * The basic algorithm is to start at the top (smallest y)
155: * of the polygon, stepping down to the bottom of
156: * the polygon by incrementing the y coordinate. We
157: * keep a list of edges which the current scanline crosses,
158: * sorted by x. This list is called the Active Edge Table (AET)
159: * As we change the y-coordinate, we update each entry in
160: * in the active edge table to reflect the edges new xcoord.
161: * This list must be sorted at each scanline in case
162: * two edges intersect.
163: * We also keep a data structure known as the Edge Table (ET),
164: * which keeps track of all the edges which the current
165: * scanline has not yet reached. The ET is basically a
166: * list of ScanLineList structures containing a list of
167: * edges which are entered at a given scanline. There is one
168: * ScanLineList per scanline at which an edge is entered.
169: * When we enter a new edge, we move it from the ET to the AET.
170: *
171: * From the AET, we can implement the even-odd rule as in
172: * (Foley/Van Dam).
173: * The winding number rule is a little trickier. We also
174: * keep the EdgeTableEntries in the AET linked by the
175: * nextWETE (winding EdgeTableEntry) link. This allows
176: * the edges to be linked just as before for updating
177: * purposes, but only uses the edges linked by the nextWETE
178: * link as edges representing spans of the polygon to
179: * drawn (as with the even-odd rule).
180: */
181:
182: /*
183: * for the winding number rule
184: */
185: #define CLOCKWISE 1
186: #define COUNTERCLOCKWISE -1
187:
188: typedef struct _EdgeTableEntry {
189: int ymax; /* ycoord at which we exit this edge. */
190: BRESINFO bres; /* Bresenham info to run the edge */
191: struct _EdgeTableEntry *next; /* next in the list */
192: struct _EdgeTableEntry *back; /* for insertion sort */
193: struct _EdgeTableEntry *nextWETE; /* for winding num rule */
194: int ClockWise; /* flag for winding number rule */
195: } EdgeTableEntry;
196:
197:
198: typedef struct _ScanLineList{
199: int scanline; /* the scanline represented */
200: EdgeTableEntry *edgelist; /* header node */
201: struct _ScanLineList *next; /* next in the list */
202: } ScanLineList;
203:
204:
205: typedef struct {
206: int ymax; /* ymax for the polygon */
207: int ymin; /* ymin for the polygon */
208: ScanLineList scanlines; /* header node */
209: } EdgeTable;
210:
211:
212: /*
213: * Here is a struct to help with storage allocation
214: * so we can allocate a big chunk at a time, and then take
215: * pieces from this heap when we need to.
216: */
217: #define SLLSPERBLOCK 25
218:
219: typedef struct _ScanLineListBlock {
220: ScanLineList SLLs[SLLSPERBLOCK];
221: struct _ScanLineListBlock *next;
222: } ScanLineListBlock;
223:
224:
225:
226: /*
227: *
228: * a few macros for the inner loops of the fill code where
229: * performance considerations don't allow a procedure call.
230: *
231: * Evaluate the given edge at the given scanline.
232: * If the edge has expired, then we leave it and fix up
233: * the active edge table; otherwise, we increment the
234: * x value to be ready for the next scanline.
235: * The winding number rule is in effect, so we must notify
236: * the caller when the edge has been removed so he
237: * can reorder the Winding Active Edge Table.
238: */
239: #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
240: if (pAET->ymax == y) { /* leaving this edge */ \
241: pPrevAET->next = pAET->next; \
242: pAET = pPrevAET->next; \
243: fixWAET = 1; \
244: if (pAET) \
245: pAET->back = pPrevAET; \
246: } \
247: else { \
248: BRESINCRPGONSTRUCT(pAET->bres); \
249: pPrevAET = pAET; \
250: pAET = pAET->next; \
251: } \
252: }
253:
254:
255: /*
256: * Evaluate the given edge at the given scanline.
257: * If the edge has expired, then we leave it and fix up
258: * the active edge table; otherwise, we increment the
259: * x value to be ready for the next scanline.
260: * The even-odd rule is in effect.
261: */
262: #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
263: if (pAET->ymax == y) { /* leaving this edge */ \
264: pPrevAET->next = pAET->next; \
265: pAET = pPrevAET->next; \
266: if (pAET) \
267: pAET->back = pPrevAET; \
268: } \
269: else { \
270: BRESINCRPGONSTRUCT(pAET->bres); \
271: pPrevAET = pAET; \
272: pAET = pAET->next; \
273: } \
274: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.