• Aucun résultat trouvé

Scan Converting Polygons

Dans le document Computer Graphics and Geometric Modeling (Page 65-70)

2.9 More Drawing Algorithms

2.9.1 Scan Converting Polygons

The Bresenham line-drawing algorithm discussed in Section 2.5.2 dealt with scan con-verting a single segment. There may be several segments we want to scan convert such as the boundary of a polygon. In that case one can use the coherenceinherent in that problem and use an algorithm that is more efficient that simply scan con-verting each bounding edge separately.

Consider the edges in Figure 2.16. As we move down from the top of the picture one scan line at a time we do not need to compute the intersections of the edges with the scan line each time. These can be computed incrementally. Since not every edge will intersect current scan line, by using an active edge list (AEL), we do not have to look at every edge each time. Here are the steps to scan convert these edges efficiently:

Step 1. Associate a “bucket” to each scan line and initialize it to empty.

Step 2. Find the largest y value for each edge and put the edge into the correspon-ding scan line’s bucket.

Step 3. For each edge emaintain the following information:

x – initially the x-coordinate of the highest point of the edge e(in general the x-coordinate xe of the intersection of ewith the current scan line) dx – change in x from line to line (the reciprocal of the slope of the line) dy – initially the number of scan lines crossed by e

Step 4. Initialize the active edge list to empty. Set y to the height of the top scan line.

Step 5. Add any edges in the bucket for y to the active edge list.

Step 6. For each edge in the active edge list draw (x,y), change the x to x +dx, and decrement dy. If dy becomes 0, then remove that edge from the list.

Step 7. Decrement y. If y is 0, then quit; otherwise, go back to Step 5.

In Figure 2.16, when we reach scan line y1, the edges ABandBCwill be added to the active edge list. At scan line y2 nothing special happens. When we get to scan line y3, the edges CDand DEwill be added to the list. Finally, at scan line y5 there are only the two edges BCandCDon the list and they will now be removed.

To avoid having fixed bucket sizes and limiting the amount of data for each scan line, one stores pointers only and stores all information sequentially in an array. Alter-natively, one can use a linked list to be able to add and delete easily.

A problem related to scan converting lists of edges which is of more practical importance is scan converting solid polygons. This leads to polygon based fill algo-rithms. The pixel-based analog was already discussed earlier in Section 2.4.

Assume that XMIN, XMAX, YMIN, and YMAX are the minimum and maximum values for the x- and y-coordinates of pixels. The basic idea here is the following:

for i:=YMIN to YMAX do for j:=XMIN to XMAX do

if Inside (polygon,j,i) then Draw (j,i);

The Boolean-valued function “Inside” counts the intersections of the line from (j,i) to (-•,i) with the polygon. If this number is odd, then the function returns true,

other-Figure 2.16. Scan converting a polygon.

wise it returns false. Of course, this algorithm is too slow. One needs to take scan line coherenceinto account. This leads us to what are called ordered edge listfill algo-rithms. They have the following general form:

for each scan line do begin

Find all intersections of edges with the scan line;

Sort the intersections by increasing x;

Fill alternate segments;

end;

For example, consider the scan line y4 in Figure 2.16. Notice how filling the alternate segments [b,c] and [d,e] does in fact fill what we want. That this works is justified by a parity type argument. An active edge list again helps. Algorithm 2.9.1.1 shows a more detailed version.

linerec=record real x, dx;

integer dy;

end;

linerecs = linerec list;

begin

linerecs array [0.. ] edges; { the edges of the polygons } linerecs ael; { the active edge list } integer y;

Scan the polygon and set up the edges table;

ael :=nil;

for y:=YMIN to YMAX do begin

Add all edges in edges [y] to ael;

if ael πnil then begin

Sort ael by increasing x;

Fill pixels along y by scanning ael and filling alternate x segments;

Delete from ael edges for which dy = 0 ; Update each x in ael by dx;

end end end;

Algorithm 2.9.1.1. An ordered edge list fill algorithm.

The following points need to be made about Algorithm 2.9.1.1:

(1) The polygon is assumed to lie entirely in window.

(2) Horizontal edges need not be considered because they get filled automatically.

(3) There is a problem with parity at vertices unless one takes precautions.

To understand the parity problem at vertices consider Figure 2.16 again. At vertices, their x values would be listed twice in the active edge list. In the case of a local maximum like vertex B =(xB,yB), the algorithm would fill the segments [XMIN,xB], [xB,xB], and [xB,XMAX] on the scan line y =yBto the background color, the color of the polygon, and the background color, respectively. This is as we would want it. On the other hand, when the algorithm gets to vertex A=(xA,yA), assuming that there was another edge below this vertex, it would fill [XMIN,xA] to the background color, [xA,xBA] to the color of the polygon, and [xBA, xBC] to the background color, etc. This isnotcorrect. Furthermore, we cannot simply skip duplicate x-coordinates as we scan the active edge list. If we did, then vertices like Awould be handled correctly, but the algorithm would now fail at local maxima and minima like B. The way that this parity problem is usually resolved is to shorten one of the (two) edges that meet in a vertex that is not at a local extremum. For example, change the lower vertex (x,y) of the upper edge to (x,y +1) (leaving the upper vertex of the lower edge in tact). No short-ening takes place at vertices that are local extrema. With this change to the edges, Algorithm 2.9.1.1 will now work correctly, but we need a test for when vertices are local extrema. Here is one:

if adjacent edges have the same sign for their slope then the common vertex is not a local extremum

else test the opposite endpoints for whether or not they lie on the same side of the scan line as the vertex: if they do, then the vertex is a local extremum, otherwise, not

To see that a further test is required in the else case, consider Figure 2.17 and the two pairs of segments ([(-1,-1),(0,0)],[(0,0),(1,-1)]) and ([(-1,-1),(0,0)],[(0,0),(-1,1)]).

In both pairs, the segments have opposite slopes, but (0,0) is a local extremum for the first pair but not for the second. One can tell the two apart however because the end-points (-1,-1) and (-1,1) for the first pair lie on opposite sides of the scan line for (0,0), whereas the endpoints (-1,-1) and (1,-1) both lie on the same side of the scan line.

Finally, note that the ordered edge list fill algorithm “works” for polygons with self-intersections and/or holes. See Figure 2.18. One needs to understand what “works”

Figure 2.17. Testing for local extrema.

means though. For example, the inside of the inner loop of Figure 2.18(a) will be drawn in the background color.

Looking ahead to Chapter 7, which is on visible surface determination, we can deal with multiple polygons here if we have an associated priority number with each, where having a higher priority means being in front of or not obscuring. In the algorithm above, as we go along we must now keep track of the polygon to which the “current” segment “belongs.” One way to do this is to maintain the following additional data:

(1) covers – a Boolean array so that covers[i] is true for the ith polygon if it covers the current segment

(2) numcover – the number of polygons covering the current segment (3) visiblePoly – a pointer to the foremost polygon, if any

As we move from segment to segment in a scan line, numcover is incremented or decremented appropriately. The array covers is initialized to falseand every time that one runs into an edge of the ith polygon, covers[i] is negated. The pointer visiblePoly tells us the color of the current segment.

In conclusion, here are some points to consider when deciding on a fill algorithm.

The main advantages of ordered edge list algorithms are that pixels are visited only once and they are well suited for shading algorithms since both ends of a span are computed before the span is drawn so that one can interpolate intensities. The main disadvantage is the large amount of processing required maintaining and sorting various lists. The main advantage to seed fill algorithms is that they can fill arbitrary planar contours, not just those bounded by polygonal curves. The main disadvantages are that some pixels are visited many times and one requires an initial interior point.

The latter is not a problem in interactive situations but would be in a fully automated one. One would then have to invoke another algorithm to find such a point. See [AckW81] for some conclusions based on performance tests. Basically, fill time tends to be dominated by the time required to set pixels making the ordered edge list rithms the most attractive overall. [FisB85] compares various specific seed fill algo-rithms. An antialiased scan conversion algorithm is described in [Morr90].

Figure 2.18. Various types of polygon.

Dans le document Computer Graphics and Geometric Modeling (Page 65-70)