0% found this document useful (0 votes)
88 views

Area-Filling Algorithms What's The Point of Filling Algorithms?

This document summarizes different area-filling algorithms: - Parity and winding number fills determine if a point is inside or outside a polygon by counting the number of times a ray from the point crosses the polygon boundary. - Boundary fills start at a known interior point and recursively fill neighboring pixels until the boundary is reached. This allows recoloring of shapes without knowledge of other primitives. - Examples are shown of the parity fill algorithm's behavior and using a boundary fill interactively. Area-filling allows efficient rendering during scan conversion and recoloring of vector drawings.

Uploaded by

fubaresque
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
88 views

Area-Filling Algorithms What's The Point of Filling Algorithms?

This document summarizes different area-filling algorithms: - Parity and winding number fills determine if a point is inside or outside a polygon by counting the number of times a ray from the point crosses the polygon boundary. - Boundary fills start at a known interior point and recursively fill neighboring pixels until the boundary is reached. This allows recoloring of shapes without knowledge of other primitives. - Examples are shown of the parity fill algorithm's behavior and using a boundary fill interactively. Area-filling allows efficient rendering during scan conversion and recoloring of vector drawings.

Uploaded by

fubaresque
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.

837 Fall ’98 Page 1

Area-Filling Algorithms What’s the Point of Filling Algorithms?

We’ve assumed that areas are filled during scan conversion


Fill region after its boundary is determined.
Irregular boundaries
Parity and Wrapping-Number Fills
Boundary and Flood Fills
YATA, YATA Freehand drawings
Project #2 Update Deferred fills for speed
Allows us to recolor primitives
Often used to select regions

Hearn & Baker, pp 125-130 (Study)


Unaware of any other primitives
previously drawn.

Lecture 8 Slide 1 6.837 Fall ’98 Lecture 8 Slide 2 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/homepage.html 05:29:36 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide02.html 05:29:41 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Parity Fill Winding Number


Problem: Imagine yourself watching a point traverse the boundary of the polygon in a counter-clockwise
direction and pivoting so that you are always facing at it.
For each pixel determine if it is inside or outside of a given polygon.
Approach:
from the point being tested cast a ray in an arbitary direction
if the number of crossings is odd then the point is inside
if the number of crossings is even then the point is outside

Your winding number is the number of full revolutions that you complete.
Very fragile algorithm If you winding number is 0 then you are outside of the polygon, otherwise you are inside.
Ray crosses a vertex
Ray is coincident with an edge
Commonly used in ECAD
Suitable for H/W

Lecture 8 Slide 4 6.837 Fall ’98

Lecture 8 Slide 3 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide03.html 05:29:48 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide04.html 05:29:54 10/10/98


Lecture 8 --- 6.837 Fall ’98 Page 1
Lecture 8 --- 6.837 Fall ’98 Page 1

Boundary Fills Let’s Watch it in Action


Boundary fills start from a point known to be inside of a region
and fill the region until a boundry is found.

A simple recursive algorithm can be used:


public void boundaryFill(int x, int y, int fill, int boundary) {
First, you should guess how you expect the algorithm to behave. Then select a point
if ((x < 0) || (x >= raster.width)) return; on the figure’s interior. Did the algorithm act as you expected?
if ((y < 0)|| (y >= raster.height)) return;
int current = raster.getPixel(x, y); Lecture 8 Slide 6 6.837 Fall ’98

if ((current != boundary) & (current != fill)) {


raster.setPixel(fill, x, y);
boundaryFill(x+1, y, fill, boundary);
boundaryFill(x, y+1, fill, boundary);
boundaryFill(x-1, y, fill, boundary);
boundaryFill(x, y-1, fill, boundary);
}
}

Lecture 8 Slide 5 6.837 Fall ’98

A second important class of area-filling algorithms start at a point know to be inside a figure and start filling in the figure outward from the point. Using
these algorithms a graphics artist may sketch the outline of a figure and then select a color or patten from a menu with which to fill it. The actual filling
process begins when a point inside of the figure is slected. These routines are like the paint-can function seen in common interactive paint packages.

The first such method that we will discuss is called the boundary-fill algorithm. The boundary-fill method requires the coordinate of a starting point, a fill
color, and a background color as arguments.

public void boundaryFill(int x, int y, int fill, int boundary) {


if ((x < 0)|| (x >= raster.width)) return;
if ((y < 0)|| (y >= raster.height)) return;
int current = raster.getPixel(x, y);
if ((current != boundary) & (current != fill)) {
raster.setPixel(fill, x, y);
file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE05.HTML 05:30:23 10/10/98
http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide06.html 05:30:35 10/10/98
boundaryFill(x+1, y, fill, boundary);

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Serial Recursion is Depth-First At Full Speed


So the fill algorithm will continue in
one direction until a boundary is
reached. To the right is the same algorithm operating at full speed.
It will then change directions
momentarily and attempt to continue
back in the original direction. Left-button click inside one of the regions to start the fill process. Click the right button to reset
the image to its original state
Will parallel execution of the Lecture 8 Slide 8 6.837 Fall ’98
algorithm behave the same way?

Lecture 8 Slide 7 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide07.html 05:30:42 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide08.html 05:30:52 10/10/98


Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

A Flood-Fill Flood-Fill in Action


Sometimes we’d like a area fill algorithm that replaces all connected pixels of a selected color
with a fill color. The flood-fill algorithm does exactly that.
public void floodFill(int x, int y, int fill, int old) {
if ((x < 0) || (x >= raster.width)) return;
if ((y < 0) || (y >= raster.height)) return;
if (raster.getPixel(x, y) == old) { It’s a little awkward to kick off a flood fill algorithm, because it requires that the old color must be
raster.setPixel(fill, x, y);
floodFill(x+1, y, fill, old);
read before it is invoked.
floodFill(x, y+1, fill, old); Lecture 8 Slide 10 6.837 Fall ’98
floodFill(x-1, y, fill, old);
floodFill(x, y-1, fill, old);
}
}

This algorithm replaces old pixels with the fill color.


Usually, the initial pixel (x, y) establishes the old value.
Lecture 8 Slide 9 6.837 Fall ’98

file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE09.HTML 05:34:06 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide10.html 05:34:14 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Self-Starting Fast Flood-Fill Algorithm Fill East


The follow implementation self-starts, and is also somewhat faster.
private void fillEast(int x, int y, int fill, int old) {
public void fillFast(int x, int y, int fill) if (x >= raster.width) return;
{ if (raster.getPixel(x, y) == old) {
if ((x < 0) || (x >= raster.width)) return; raster.setPixel(fill, x, y);
if ((y < 0) || (y >= raster.height)) return; fillEast(x+1, y, fill, old);
int old = raster.getPixel(x, y); fillSouth(x, y+1, fill, old);
if (old == fill) return; fillNorth(x, y-1, fill, old);
raster.setPixel(fill, x, y); }
fillEast(x+1, y, fill, old); }
fillSouth(x, y+1, fill, old);
fillWest(x-1, y, fill, old); Note:
fillNorth(x, y-1, fill, old);
} There is only one clipping test, and only three subsequent calls.
Why?
Lecture 8 Slide 11 6.837 Fall ’98 How much faster do you expect this algorithm to be?
Lecture 8 Slide 12 6.837 Fall ’98

file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE11.HTML 05:34:27 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide12.html 05:34:41 10/10/98


Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Working Algorithm 4-Way and 8-Way Connectedness

private void fillSouth(int x, int y, int fill, int old) {


if (y >= raster.height) return; A final consideration when writing a area-fill algorithm is the size and connectivity of the
if (raster.getPixel(x, y) == old) { neighborhood, around a given pixel.
raster.setPixel(fill, x, y);
fillEast(x+1, y, fill, old);
fillSouth(x, y+1, fill, old);
fillWest(x-1, y, fill, old);
}
} An eight-connected neighborhood is able to get into knooks and crannies that an algorithm based
on a four-connected neighborhood cannot.
Lecture 8 Slide 14 6.837 Fall ’98
You can figure out the other routines yourself.
Lecture 8 Slide 13 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide13.html 05:34:51 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide14.html 05:34:58 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Code for an 8-Way Connected Flood Fill More 8-Way Connectedness

public void floodFill8(int x, int y, int fill, int old) {


if ((x < 0) || (x >= raster.width)) return;
if ((y < 0) || (y >= raster.height)) return; Sometimes 8-way connectedness can be too much.
if (raster.getPixel(x, y) == old) { Lecture 8 Slide 16 6.837 Fall ’98
raster.setPixel(fill, x, y);
floodFill8(x+1, y, fill, old);
floodFill8(x, y+1, fill, old);
floodFill8(x-1, y, fill, old);
floodFill8(x, y-1, fill, old);
floodFill8(x+1, y+1, fill, old);
floodFill8(x-1, y+1, fill, old);
floodFill8(x-1, y-1, fill, old);
floodFill8(x+1, y-1, fill, old);
}
}

Lecture 8 Slide 15 6.837 Fall ’98

file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE15.HTML 05:35:08 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide16.html 05:35:15 10/10/98


Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Flood-Fill Embellishments YATA (Yet Another Triangle Renderer)


The flood-fill and boundary-fill algorithms can easily be modified for a wide variety A simple modification of the boundary-fill algorithm produces a triangle renderer.
of new uses: We need two things:
1. Patterned fills
2. Approximate fills 1. A boundary (terminating condition)
3. Gradient fills Edge Equations
4. Region selects
5. Triangle Rendering!
2. An interior point (initial condition)

Lecture 8 Slide 18 6.837 Fall ’98

Lecture 8 Slide 17 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide17.html 05:35:24 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide18.html 05:35:33 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

More Subtle Issues Implementation Details


Connectedness public void Draw(Raster raster) {
this.raster = raster;
if (!triangleSetup( )) return;

/*
find the triangle’s centroid
*/
int x = (int) ((v[0].x + v[1].x + v[2].x)/3 + 0.5);
int y = (int) ((v[0].y + v[1].y + v[2].y)/3 + 0.5);

We can use our plane equations to generate the fill color /*


initialize parameters
*/
int param[] = new int[7];
param[0] = edge[0].evaluate(x, y);
param[1] = edge[1].evaluate(x, y);
param[2] = edge[2].evaluate(x, y);
Lecture 8 Slide 19 6.837 Fall ’98
param[3] = alpha.evaluate(x, y) + (1 << (EdgeEqn.FRACBITS - 1));
param[4] = red.evaluate(x, y) + (1 << (EdgeEqn.FRACBITS - 1));
param[5] = green.evaluate(x, y) + (1 << (EdgeEqn.FRACBITS - 1));
param[6] = blue.evaluate(x, y) + (1 << (EdgeEqn.FRACBITS - 1));
fillTri(x, y, param);
}
Lecture 8 Slide 20 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide19.html 05:35:40 10/10/98 file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE20.HTML 05:35:55 10/10/98


Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 2

param[2] -= edge[2].A;
Modified Boundary Fill param[3] -= alpha.A;
param[4] -= red.A;
private void fillTri(int x, int y, int param[]) {
param[5] -= green.A;
/*
param[6] -= blue.A;
pixel inside bounding box?
fillTri(x-1, y+1, param);
*/
if ((x > xMax) || (x < xMin)) return;
param[0] -= edge[0].B;
if ((y > yMax) || (y < yMin)) return;
param[1] -= edge[1].B;
param[2] -= edge[2].B;
/*
param[3] -= alpha.B;
pixel inside triangle?
param[4] -= red.B;
*/
param[5] -= green.B;
if ((param[0]|param[1]|param[2]) < 0) return;
param[6] -= blue.B;
fillTri(x-1, y, param);
/*
compute fill color
param[0] -= edge[0].B;
*/
param[1] -= edge[1].B;
int pixa = (param[3] >> EdgeEqn.FRACBITS);
param[2] -= edge[2].B;
int pixr = (param[4] >> EdgeEqn.FRACBITS);
param[3] -= alpha.B;
int pixg = (param[5] >> EdgeEqn.FRACBITS);
param[4] -= red.B;
int pixb = (param[6] >> EdgeEqn.FRACBITS);
param[5] -= green.B;
pixa = ((pixa & ~255) == 0) ? pixa << 24 : ((pixa < 0) ? 0 : 255
param[6] -= blue.B;
param[0] -= edge[0].A;
fillTri(x-1, y-1, param);
param[1] -= edge[1].A;
param[2] -= edge[2].A;
param[0] += edge[0].A;
param[3] -= alpha.A;
param[1] += edge[1].A;
param[4] -= red.A;
param[2] += edge[2].A;
param[5] -= green.A;
param[3] += alpha.A;
param[6] -= blue.A;
param[4] += red.A;
fillTri(x, y+1, param);
param[5] += green.A;
param[6] += blue.A;
param[0] -= edge[0].A;
fillTri(x, y-1, param);
param[1] -= edge[1].A;
file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE21.HTML 05:36:08 10/10/98 file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE21.HTML 05:36:08 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 3


Lecture 8 --- 6.837 Fall ’98 Page 1
param[0] += edge[0].A;
param[1] += edge[1].A; Test Case
param[2] += edge[2].A;
param[3] += alpha.A;
param[4] += red.A;
param[5] += green.A; Above is our simple test case from last lecture. Using the TriTest applet from your Project #2 assignment.
param[6] += blue.A; Lecture 8 Slide 22 6.837 Fall ’98
fillTri(x+1, y-1, param);

/*
fix it up back to the way we found it (Why?)
*/
param[0] += edge[0].B - edge[0].A;
param[1] += edge[1].B - edge[1].A;
param[2] += edge[2].B - edge[2].A;
param[3] += alpha.B - alpha.A;
param[4] += red.B - red.A;
param[5] += green.B - green.A;
param[6] += blue.B - blue.A;
}
}
Lecture 8 Slide 21 6.837 Fall ’98

file://localhost/E:/6.837/GRAPHICS.LCS.MIT.EDU/CLASSES/6.837/F98/LECTURE8/SLIDE21.HTML 05:36:08 10/10/98


http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide22.html 05:36:20 10/10/98
Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Harder Cases Discuss Problems


Triangles interiors are not necessarily 8-way connected!
These two triangle databases are a little more diffficult to get right.
Lecture 8 Slide 23 6.837 Fall ’98

The rounded coordinates of a triangle’s centroid are not necessarily inside of the triangle!

Solutions?
Redefine what it means to be inside of a triangle
Different routines for nasty little triangles
Lecture 8 Slide 24 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide23.html 05:36:27 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide24.html 05:36:35 10/10/98

Lecture 8 --- 6.837 Fall ’98 Page 1 Lecture 8 --- 6.837 Fall ’98 Page 1

Project #2: One Last Visit Next Time

I’ve never seen a purple cow


I never hoped to draw one
But I can tell you anyhow
I’d rather draw than gnaw one

with apologies to Gelett Burgess


(MIT class of 1887)
Lecture 8 Slide 25 6.837 Fall ’98

Lecture 8 Slide 26 6.837 Fall ’98

http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide25.html 05:36:41 10/10/98 http://graphics.lcs.mit.edu/classes/6.837/F98/Lecture8/Slide26.html 05:36:47 10/10/98

You might also like