Raster-Based Fill Algorithms
Raster-Based Fill Algorithms
Lecture 5
Rasterization:
Raster-Based Fill Algorithms
Review
Region filling: The process of coloring in a region of an image
Requirements:
1. A digital representation of a closed shape
2. A test for determining if a point is inside or outside of the shape
3. A rule or procedure for determining the colors of each point
inside the shape
Review
Seed Fill Algorithms
Raster-Based Filling
Fill the interior one raster scan
line at a time
Geometric descriptions
Even-odd parity rule
Non-zero winding number rule
Scan line
j0+M-1
x0
x1
x2
j0+M-1
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0
x-intersection array
xN-1
Scan line
j0+M-1
x04
x03
x02
e0 x01
x00
Intersections for edge e0
x1
x2
xN-1
j0+M-1
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
x0
j0
x04
x03
x02
x01
x00
e1 x
12
x10
x13
Scan line
j0+M-1
x11
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0+M-1
j0
x0
x1
x2
xN-1
x12
x12
x11
x10
x04
x03
x02
x01
x00
x20
x21
x22
e2
x23
x24
Scan line
j0+M-1
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0+M-1
j0
x0
x1
x13
x12
x11
x10
x04
x03
x02
x01
x00
x20
x21
x22
x23
x24
x2
xN-1
Scan line
j0+M-1
j0+M-1
x71
x70
e7
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0
x0
x1
x13
x12
x11
x10
x03
x02
x02
x01
x00
x20 x42
x21 x41
x22 x40
x23 x51
x24 x50
x65
x66
x70
x71
x2
xN-1
x60
x61
x62
x63
x64
Scan line
j0+M-1
j0+M-1
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0
x0
x1
x13
x12
x11
x10
x03
x02
x02
x01
x00
x20 x42
x21 x41
x22 x40
x23 x51
x24 x50
x65
x66
x70
x71
x2
x60
x61
x62
x63
x64
xN-1
Scan line
j0+M-1
j0+M-1
x01
x00
x71
x70
j0+3
j0+3
j0+2
j0+2
j0+1
j0+1
j0
j0
x0
x1
x13
x12
x11
x10
x03
x02
x02
x01
x00
x20 x42
x21 x41
x22 x40
x23 x51
x24 x50
x65
x66
x70
x71
x2
x60
x61
x62
x63
x64
xN-1
Exercise
Fill this polygon using the non-zero winding rule
For each edge, compute the x-intersections
Also store Winding Number Increment (WNI = +1 or -1)
Scan
line
j=8
x07
e0
e3
x14
j=3
j=0
x07
WNI
x37
-1
+1
x15
j=4
j=1
WNI
x16
j=5
j=2
j=7
j=6
e1
x13
x22
e2
x21
x12
1
0
x11
x20
x10
WNI
Exercise
Fill this polygon using the non-zero winding rule
For each edge, compute the x-intersections
Also store Winding Number Increment (WNI = +1 or -1)
Scan
line
j=8
x07
e0
j=7
j=6
e3
x16
j=5
x15
j=4
x14
j=3
j=2
j=1
j=0
e1
x13
x22
e2
x21
x12
x11
x20
x10
x
WNI
x07
x16
x15
x14
x13
x12
x11
x10
x
WNI
x37
-1
+1
x36
-1
+1
x35
-1
+1
x34
-1
+1
x33
-1
+1
x22
-1
+1
x21
-1
-1
x20
+1
+1
WNI
Exercise
Sort edge intersections from left to right
Scan
line
j=8
x07
e0
j=7
j=6
e3
x16
j=5
x15
j=4
x14
j=3
j=2
j=1
j=0
e1
x13
x22
e2
x21
x12
x11
x20
x10
x
WNI
x07
x16
x15
x34
x33
x22
x21
x20
x
WNI
x37
-1
+1
x36
-1
+1
x35
-1
+1
x14
+1
-1
x13
+1
-1
x12
+1
-1
x11
+1
+1
x10
-1
-1
WNI
Exercise
For each scan line, fill pixels according to the winding number
Scan
line
j=8
x07
e0
j=7
j=6
e3
x16
j=5
x15
j=4
x14
j=3
j=2
j=1
j=0
e1
x13
x22
e2
x21
x12
x11
x20
x10
x
WNI
x07
x16
x15
x34
x33
x22
x21
x20
x
WNI
x37
-1
+1
x36
-1
+1
x35
-1
+1
x14
+1
-1
x13
+1
-1
x12
+1
-1
x11
+1
+1
x10
-1
-1
WNI
Memory considerations
A large x-intersection array is needed for
General or concave polygons (M could be large)
High resolution images (N large)
Convex polygon
A maximum of two x-intersections per scan line
M = 2
Sorting is easy
Concave polygon
Subdivide to convex polygons
+
+
+
+
+
+
+
(x1, y1)
+
+
+
+
+
+
+
(x0, y0)
+
+
dy
+
+
+
+
dx
j0 = y0
(int)y0 + 1
+
+
+
+
j0
, if y0 is an integer
, otherwise
(x, j0)
+
e8
Edge
e7
e6
e5
e3
e4
e0
e1
e2
e0
e1
e2
e8
Edge
e7
e6
e5
e3
e0
e1
e2
a0
a1
a2
a3
a1
a2
a3
An example
Create a global edge list:
e5
e1
e2
e4
e3
e0
e7
General polygon
e6
An example
Create a global edge list:
Pre-process each edge for fast intersection computation
Pre-compute the data needed:
mInv = dx/dy, j0, x(j0), y1, and the edges winding number increment,
if using the non-zero winding rule
Store pre-processed data in the global edge list
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
e4
e3
(x4,y4)
e6
(x3,y3)
e0
(x0,y0)
(x6,y6)
(x7,y7)
e7
General polygon
Edge
e0
e1
e2
e3
e4
e5
e6
e7
Edge data
mInv0, j00, x(j0)0, y10,
mInv1, j01, x(j0)1, y11,
mInv2, j02, x(j0)2, y12,
mInv3, j03, x(j0)3, y13,
mInv4, j04, x(j0)4, y14,
mInv5, j05, x(j0)5, y15,
mInv6, j06, x(j0)6, y16,
mInv7, j07, x(j0)7, y17,
An example
Create a global edge list:
Pre-process each edge for fast intersection computation
Pre-compute the data needed:
mInv = dx/dy, j0, x(j0), y1, and the edges winding number increment,
if using the non-zero winding rule
Store pre-processed data in the global edge list
Sort the global edge list according to each edges bottom vertex
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
e4
e3
(x4,y4)
e6
(x3,y3)
e0
(x0,y0)
(x6,y6)
(x7,y7)
e7
General polygon
Edge
e0
e7
e6
e2
e3
e1
e4
e5
Edge data
mInv0, j00, x(j0)0, y10,
mInv7, j07, x(j0)7, y17,
mInv6, j06, x(j0)6, y16,
mInv2, j02, x(j0)2, y12,
mInv4, j04, x(j0)4, y14,
mInv1, j01, x(j0)1, y11,
mInv3, j03, x(j0)3, y13,
mInv5, j05, x(j0)5, y15,
An example
Keeps track of which edges are intersected by the current scan line
Initialize the active edge list with edges intersected by the lowest scan line
Active edges are sorted from left to right
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
(x6,y6)
e4
e3
(x4,y4)
e6
(x3,y3)
e0
(x0,y0)
(x7,y7)
e7
General polygon
Edge
e0
e7
e6
e2
e3
e1
e4
e5
Edge data
mInv0, j00, x(j0)0, y10,
mInv7, j07, x(j0)7, y17,
Edge
a0
a1
e0
e7
An example
Process each scan line
Determine the x-intersections for each active edge using DDA
Set pixels in the spans between pairs of x-intersections using the fill rule
(even-odd parity rule or non-zero winding rule)
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
(x6,y6)
e4
e3
(x4,y4)
e6
(x3,y3)
e0
(x0,y0)
(x7,y7)
e7
General polygon
Edge
e0
e7
e6
e2
e3
e1
e4
e5
Edge data
mInv0, j00, x(j0)0, y10,
mInv7, j07, x(j0)7, y17,
Edge
a0
a1
e0
e7
An example
Update the active edge list
Remove edges whose top vertex is on or below the next scan line
Add edges from the global edge list whose bottom vertex lies between this
scan line and the next scan line or on the next scan line
Re-sort the edges in the active edge list from left to right
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
e4
e3
(x4,y4)
e6
(x3,y3)
e0
(x0,y0)
(x6,y6)
(x7,y7)
e7
General polygon
j+1
j
Edge
e0
e7
e6
e2
e3
e1
e4
e5
Edge data
mInv0, j00, x(j0)0, y10,
mInv7, j07, x(j0)7, y17,
Edge
a0
a1
e0
e6
An example
Update the active edge list
Remove edges whose top vertex is on or below the next scan line
Add edges from the global edge list whose bottom vertex lies between this
scan line and the next scan line or on the next scan line
Re-sort the edges in the active edge list from left to right
(x2,y2)
e1
e2
(x1,y1)
(x5,y5)
e5
e4
e3
(x4,y4)
e6
j+2
(x3,y3)
e0
(x0,y0)
(x6,y6)
(x7,y7)
e7
General polygon
j+1
Edge
e0
e7
e6
e2
e3
e1
e4
e5
Edge data
mInv0, j00, x(j0)0, y10,
mInv7, j07, x(j0)7, y17,
mInv6, j06, x(j0)6, y16,
mInv2, j02, x(j0)2, y12,
Edge
a0
a1
a2
a3
e0
e2
e3
e6
Horizontal edges
If a horizontal edge lies between scan lines
It does not intersect any scan line
Shared vertices
If the scan line intersects a shared vertex
The edge crossing could be counted more than once
Yields incorrect, inconsistent even-odd parity and winding numbers
P
P
Shared vertices
One approach:
Ensure that the scan line does not intersect a vertex
Preprocess: Add a small y-offset to a vertex if it falls on a scan line
P1
P0
Shared vertices
Another approach:
Use a convention to include/exclude vertices
Include the bottom vertex of each edge if it falls on a scan line
Do not include the top vertex of each edge if it falls on a scan line
Shared vertices
Another approach:
Use a convention to include/exclude vertices
Include the bottom vertex of each edge if it falls on a scan line
Do not include the top vertex of each edge if it falls on a scan line
e1
e0
Shared vertices
Another approach:
Use a convention to include/exclude vertices
Include the bottom vertex of each edge if it falls on a scan line
Do not include the top vertex of each edge if it falls on a scan line
e2
e3
Shared vertices
Another approach:
Use a convention to include/exclude vertices
Include the bottom vertex of each edge if it falls on a scan line
Do not include the top vertex of each edge if it falls on a scan line
e0
Include the bottom
vertex of edge e0
e4
Include the bottom
vertex of edge e4
Sliver polygons
So thin that some scan lines have only one pixel or no pixels
No simple solution
Avoid long thin triangles
Want triangles with a good aspect ratio
Example of an aliasing problem
(more on these next week)
(4,5.5)
e2
(0,4.5)
e1
e3
e0
(2,2)
(0,0.5)
e4
(4,0.5)
Edge
e0
(0, 0.5)
(0, 4.5)
e1
(2, 2)
(0, 4.5)
e2
(2, 2)
(0, 5.5)
e3
(4, 0.5)
(4, 5.5)
e4
(4,5.5)
e0
e2
(0,4.5)
e1
e1
e2
e3
e0
(2,2)
(0,0.5)
Active Edges
e4
(4,0.5)
e3
(4,5.5)
e2
(0,4.5)
e1
j
e0
j-1
+
(0,0.5)
+
+(2,2)
e4
+e3
+
(4,0.5)
Previous x
dx/dy
e0
e1
-2/2.5
e2
2/3.5
e3
Data structures
EdgeData: For each edge,
j0 = bottom-most scan line
intersected by the edge
j1 = top-most scan line intersected
by the edge
x = the value of the x-intersection
with the current scan line, initialized
to x(j0)
dx = the change in the value of the
x-intersection for the next scan line
dir = the direction of the edge (1 if
the original edge is upward, -1 if the
original edge is downward)
j1
j0
x = x(j0)
dx
Data structures
EdgeData: For each edge,
j0 = bottom-most scan line
intersected by the edge
j1 = top-most scan line intersected
by the edge
x = the value of the x-intersection
with the current scan line, initialized
to x(j0)
dx = the change in the value of the
x-intersection for the next scan line
dir = the direction of the edge (1 if
the original edge is upward, -1 if the
original edge is downward)
j1
j0
x = x(j0)
dx
Data structures
typedef struct {
int j0;
//Bottom-most scan line intersecting edge
int j1;
//Top-most scan line intersecting edge
float x;
//x-intersection with current scan line
float dx; //Displacement of x-intersect for next scan line
float dir; //1 if edge is upward, -1 if edge is downward
} EdgeData;
(4.5,5.5)
j=5
j=4
Edge
e2
(0,4.5)
e0
e1
j=3
e3
e0
j=2
(2,2.00001)
e1
e2
e3
j=1
j=0
e4
(0,0.5)
e4
(4.5,0.5)
Global edge list
(4.5,5.5)
j=5
j=4
Edge
e2
(0,4.5)
e1
j=3
e3
e0
j=2
(2,2.00001)
j=1
j=0
(0,0.5)
e4
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
e4
1, 0, 0, 0, 0
(4.5,0.5)
Global edge list
(4.5,5.5)
j=5
j=4
Edge
e2
(0,4.5)
e1
j=3
e3
e0
j=2
(2,2.00001)
j=1
j=0
(0,0.5)
e4
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
e4
1, 0, 0, 0, 0
(4.5,0.5)
Global edge list
(4.5,5.5)
j=5
j=4
Edge
e2
(0,4.5)
e1
j=3
e3
e0
j=2
(2,2.00001)
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
j=1
j=0
(0,0.5)
e4
(4.5,0.5)
Global edge list
Edge
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
Edge
e0 is the lowest, leftmost edge:
no swap is needed
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
Edge
e0
1, 4, 0, 0, 1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
e3
1, 5, 4.5, 0, -1
Edge
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e2
3, 5, 2.71, 0.71, 1
e1
3, 4, 1.2, -0.8, -1
Edge
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e2
3, 5, 2.71, 0.71, 1
e1
3, 4, 1.2, -0.8, -1
Edge
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
Edge
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
(4.5,5.5)
j=5
j=4
Edge
e2
(0,4.5)
e1
j=3
e3
e0
j=2
(2,2.00001)
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
j=1
j=0
(0,0.5)
e4
(4.5,0.5)
Global edge list
Initialize the active list with indices of edges that intersect the first scan line
Update the active list with each new scan line
Remove edges if j1 is below the new scan line
Update x for each edge remaining in the active edge list
Add edges whose j0 falls between the previous and the new scan line
Sort edges in the active edge list from left to right (e.g., insertion sort)
Exercise
A. Fill in the active edge table with
the ordered active edges at each
scan line
B. Use non-zero winding to determine
which ranges of x values are
inside the polygon
Edge
e0
1, 4, 0, 0, 1
e3
1, 5, 4.5, 0, -1
e1
3, 4, 1.2, -0.8, -1
e2
3, 5, 2.71, 0.71, 1
Global edge list
(4.5,5.5)
j=5
e2
(0,4.5)
j=4
Scan line
e1
j=1
j=3
e3
e0
j=2
0, 3
2
3
(2,2.00001)
j=1
j=0
Edge index
(0,0.5)
e4
(4.5,0.5)
Summary
Raster-based filling of polygons
X-intersection array algorithm
Improve efficiency with DDA
Edge list algorithm
Special considerations: horizontal edges, shared vertices, slivers
Implementation with active edge array
Both approaches find limits of interior spans, fill pixels between the limits
74
Next time
Coloring and texturing polygons
Third polygon filling approach: Pinedas algorithm
Uses coherence of square tiles rather than rows of pixels
Computes color/texture interpolation
75