OUIPUI Prlm~tiv~s producing an nrtivr r d ~ c . lisf for each scan line crossing thc polygon boundaries.
The active edge list for a scan line contains all edges crossed by that scan line, with iterative coherence calculations used to obtain the edge inte;sections.
Implementation of edge-intersection calculations t a n also be facilitated by storing Ax and ly values in the sorted edge table. Also, to ensure that we cor- rectly fill the interior of specified polygons, we can apply the considerations dis- cussed in Section 3-10. For each scan line, we fill in the pixel spans for each pair of x-intercepts starting from the leftmost x-intercept value and ending at one po- sition before the rightnlost r intercept. And each polygon edge can be shortened by one unit in they direction at the top endpoint. These measures also guarantee that pixels in adjacent polygons will not overlap each other.
The following procedure performs a solid-fill scan conversion For an input set of polygon vertices. For each scan line within the vertical extents of the poly- gon, an active edge list is set up and edge intersections are calculated. Across each scan line, the interior fill is then applied between successive pairs of edge
intersections, processed from left to right.- -
Pinclude "device.h"
typedef struct tEdge { int yupper;
float xlntersect. dxPerScan;
struct tEdge * next;
1 Edge:
. ' Inserts edge into list in order of increas.ng x1n;essect field. * I void insertEdge (Edge ' list, Edge edge)
{
Edge ' p . ' q = list;
p = q - > n e x t ; while ( p ! = NULL) i
i f (edge->xIntersect < p->xIntersectl p : NULL;
else { 9 = P:
p = p->next;
1 1
edge->next = q->next;
q->next = edge;
1
: ' For an index, return y-coordinate of next nonhorizontal li?e ' / lnt yNext (int k , int cnt, dcPt * p t s )
i int j :
j + + ;
return (pts[j 1 . y) ;
I
/ ' Srore lower-y coordiaate and inverse slope for each edge. Adjust and store upper-y coordinate for edges that are the lower member of a monotonic all\^ ixreasing or decreasing pair of edges '/
void makeEdgeRec
(dcPt lower, dcPt upper, int yComp, Edge ' edge, Edge edges[])
(
edge-~dxPerScan =
(float) upper.^
-
1ower.x) / (upper.y - 1ower.y);edge-~xIntersect = 1orer.x;
if (upper.y < yComp)
edge->yUpper = upper.y
-
1:else
edge->yUpper = upper.y;
insertEdge (edges [lower. yl , edge) ; 1
void buildEdgeList (int cnt, dcPt pts, Edge ' edges[])
(
Edge ' edge:
dcPr vl, v2;
int i, yPrev = pts[cnt - 21 .Y;
v1.x = pts[cnt-l1.x; v1.y = ptstcnt-l1.y;
for (i=O; i<cnt: i++) {
v2 = ptslil;
if Iv1.y ! = v2.y) ( /' nonhorizontal line '/
edge = (Zdge * ) malloc (sizeof (Edge));
if (v1.y < v2.y) / + up-going edge * / makeEdgeRec (vl, v2, yNext (i, cnt, pts), edge, edges) ;
else /' down-going edge * /
mdkeEdgeRec (v2, vl , yPrev, edge, edges) : I
void buildActiveList (int scan, Edge ' active, Edge ' edges[])
(
p = edges[scanl->next;
while ( p ) { q = p->next;
insertEdge (active, p);
P = g ; I
1
void fillscan lint scan, Edge ' active) Edge * pl, p2 ;
int i;
pl = active->next;
while (pl) (
p2 = pl->next;
for i1=pl-,xI1tersect; 1cg2-zx1nterr:ect; - + + )
setpixel i iintl i, scan);
pl = p2->next;
void deleteAfter (Edge ' ql
(
q->next = p->next;
free ( p ) :
I ' Delete completed edges. Update 'xIntersect' field Eor others ' /
1
;oid updateActiveList iint scan. Edge activrl I while lp)i f (scan > = p->yUpper) I p p->next;
deleLrAfter iq):
else (
p->x~ntersect = p->xintersect + p->dxPer.;can:
p = p->next;
void rescrtActiveList (Edge active) Edge q. ' p = active->next : active->next : NULL;
while ( p ) (
q = p->next;
insertEdge (active, p);
P = 9;
i )
void scanFill (int cnt, dCPt ' pts)
1
(Edge * edges [WINDOW-HEIGHT1 , + actlve;
inc i. scan;
for (i=O; icWINCOW-HEIGHT; i + + ) (
edgesli] = (Edge ' I malloc ( s i z e o f (Edge));
edgesiii->next NULL;
buildEdgeList (cnt, pts, edges);
active = (Edge ' 1 malloc (sizeof (Edge));
active->next = NULL;
for (scan=O; scan<WINWW-HEIGHT; scan++) ( buildActiveList (scan, active, edges);
if (actlve->next) ( fillscan (scan, active);
updateActlveList (scan, active) ;
ressrtActiveLisc (active);
I
1
/ + Free edge records that have been malloc'ed . . . ' I
Inside-Outside Tests
Area-filling algorithms and other graphics processes often need to identify inte- rior regions of objects. So far, we have discussed area filling only in terms of stan- dard polygon shapes. In elementary geometry, a polygon is usually defined as having no self-intersections. Examples of standard polygons include triangles, rectangles, octagons, and decagons. The component edges of these objects are joined only at the vertices, and otherwise the edges have no common points in the plane. Identifying the interior regions of standard polygons is generally a straightforward process. But in most graphics applications, we can specify any sequence for the vertices of a fill area, including sequences that produce intersect- ing edges, as in Fig. 3-40. For such shapes, it is not always clear which regions of the xy plane we should call "interior" and which regions we should designate as
"exterio!" to the object. Graphics packages normally use either the odd-even rule or the nonzero winding number rule to identify interior regions of an object.
We apply the odd-even rule, also called the odd parity rule or the even- odd rule, by conceptually drawing a line from any position P to a distant point outside the coordinate extents of the object and counting the number of edge crossings along the line. If the number of polygon edges crossed by this line is odd, then P is an interior point. Otherwise, P is an exterior point. To obtain an ac- curate edge count, we must be sure that the line path we choose does not inter- sect any polygon vertices. Figure 340(a) shows the interior and exterior regions obtained from the odd-even rule for a self-intersecting set of edges. The scan-line polygon fill algorithm discussed in the previous section is an example of area fill- ing using the odd-even rule.
Another method for defining interior regions is the nonzero winding num- ber rule, which.counts the number of times the polygon edges wind around a particular point in the counterclockwise direction. This count is called the wind- ing number, and the interior points of a two-dimensional object are defined to be
Nonnm W~nding Number Rule Ibl
Figure 3-40
Identifying interior and exterior regions for a self-intersecting polygon.