Computer Graphics Implementation I. Algorithms for Drawing 2D Primitives. Line Drawing Algorithms DDA algorithm Midpoint algorithm Bresenhamâ€™s line algorithm Circle Generating Algorithms Bresenhamâ€™s circle algorithm Extension to Ellipse drawing. Line Drawing. Line Drawing
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
ImplementationI
Draw a line on a raster screen between two points
What’s wrong with statement of problem?
doesn’t say anything about which points are allowed as endpoints
doesn’t give a clear meaning of “draw”
doesn’t say what constitutes a “line” in raster world
doesn’t say how to measure success of proposed algorithms
Problem Statement
Given two points P and Q in XY plane, both with integer coordinates, determine which pixels on raster screen should be on in order to make picture of a unitwidth line segment starting at P and ending at Q
Scan Converting Lines
Horizontal Line:
Draw pixel P and increment x coordinate value by 1 to get next pixel.
Vertical Line:
Draw pixel P and increment y coordinate value by 1 to get next pixel.
Diagonal Line:
Draw pixel P and increment both x and y coordinate by 1 to get next pixel.
What should we do in general case? => Fast
 Digital differential analyzer (DDA) algorithm
 Midpoint algorithm
 Bresenham algorithm
Finding next pixel:
y = mx + h
Find equation of line that connects two points P(x1,y1) and Q(x2,y2)
Starting with leftmost point P, increment xi by 1 to calculate yi= m*xi+ h
where m = slope, h = y intercept
Draw pixel at (xi, Round(yi)) where
Round (yi) = Floor (0.5 + yi)
dy/dx = m = Dy/Dx = (y2y1)/(x2x1)
For(x=x1; x<=x2,x++) {
y+=m;
write_pixel(x, round(y), line_color)
}
// Incremental Line Algorithm
// Assume x0 < x1
void Line(int x0, int y0,
int x1, int y1) {
int x, y;
float dy = y1 – y0;
float dx = x1 – x0;
float m = dy / dx;
y = y0;
for (x = x0; x < x1; x++) {
WritePixel(x, Round(y));
y = y + m;
}
}
void Line(int x0, int y0,
int x1, int y1) {
int x, y;
float dy = y1 – y0;
float dx = x1 – x0;
float m = dy / dx;
y = y0;
for (x = x0; x < x1; x++) {
WritePixel(x, Round(y));
y = y + m;
}
}
Rounding takes time
Call lower left endpoint (x0, y0) and upper right endpoint (x1, y1)
Assume that we have just selected pixel P at (xp, yp)
Next, we must choose between pixel to right (E pixel) (xp+1, yp), or one right and one up (NE pixel) (xp+1, yp+1)
Let Q be intersection point of line being scanconverted and vertical line x=xp+1
Strategy 2 – Midpoint Line
Algorithm (1/3)
Algorithm (2/3)
NE pixel
Q
Midpoint M
E pixel
Previous pixel
Choices for current pixel
Choices for next pixel
Point that is closer to intersection point Q must be chosen
Observe on which side of line midpoint M lies:
E is closer to line if midpoint M lies above line, i.e., line crosses bottom half
NE is closer to line if midpoint M lies below line, i.e., line crosses top half
Error (vertical distance between chosen pixel and actual line) is always <= ½
NE pixel
Q
M
E pixel
Strategy 2 – Midpoint Line
Algorithm (3/3)
Line equation as implicit function:
for coefficients a, b, c, where a, b ≠ 0
from above,
Properties (proof by case analysis):
f(xm, ym) = 0 when any point M is on line
f(xm, ym) < 0 when any point M is above line
f(xm, ym) > 0 when any point M is below line
Our decision will be based on value of function at midpoint M at (xp + 1, yp + ½)
Line
void MidpointLine(int x0, int y0, int x1, int y1) {
int dx = x1  x0;
int dy = y1  y0;
int x = x0;
int y = y0;
float c = y0 * dx – dy * x0;
writePixel(x, y);
x++;
while (x < x1) {
d = dy * x – (y + 0.5) * dx + c;
if (d > 0) { // Northeast Case
y++;
}
writePixel(x, y);
x++;
} /* while */
}
We only need sign of f(xp+ 1, yp + ½) to see where line lies, and then pick nearest pixel
d = f(xp + 1, yp + ½)
 if d > 0 choose pixel NE
 if d < 0 choose pixel E
 if d = 0 choose either one consistently
How do we incrementally update d?
On basis of picking E or NE, figure out location of M for that pixel, and corresponding value d for next grid line
We can derive d for the next pixel based on our current decision
Decision Variable
dnew = f(xp + 2, yp + ½)
= a(xp + 2) + b(yp + ½) + c
dold = a(xp + 1)+ b(yp + ½)+ c
dnew  dold is the incremental difference E
dnew= dold+ a
E= a = dy
We can compute value of decision variable at next step incrementally without computing F(M) directly
dnew= dold + E= dold+ dy
E can be thought of as correction or update factor to take dold to dnew
It is referred to as forward difference
Strategy 3 – Bresenham algorithm
If E was chosen:
dnew= F(xp + 2, yp + 3/2)
= a(xp + 2)+ b(yp + 3/2)+ c
NE = dnew – dold
dnew = dold + a + b
NE = a + b = dy – dx
Thus, incrementally,
dnew = dold + NE = dold + dy – dx
If NE was chosen:
It then updates decision variable by adding either E or NE to old value depending on choice of pixel. Simple additions only!
First pixel is first endpoint (x0, y0), so we can directly calculate initial value of d for choosing between E and NE.
Summary (1/2)
(x0 + 1, y0 + ½)
f(x0 + 1, y0 + ½)
= a(x0 + 1) + b(y0 + ½) + c
= a * x0 + b * y0 + c + a + b/2
= f(x0, y0) + a + b/2
But (x0, y0) is point on line and f(x0, y0) = 0
Therefore, dstart = a + b/2 = dy – dx/2
use dstart to choose second pixel, etc.
To eliminate fraction in dstart :
redefine f by multiplying it by 2; f(x,y) = 2(ax + by + c)
this multiplies each constant and decision variable by 2, but does not change sign
Summary (2/2)
void Bresenham(int x0, int y0, int x1, int y1) {
int dx = x1  x0;
int dy = y1  y0;
int d = 2 * dy  dx;
int incrE = 2 * dy;
int incrNE = 2 * (dy  dx);
int x = x0;
int y = y0;
writePixel(x, y);
while (x < x1) {
if (d <= 0) { // East Case
d = d + incrE;
} else { // Northeast Case
d = d + incrNE;
y++;
}
x++;
writePixel(x, y);
} /* while */
} /* MidpointLine */
(0, 17)
(0, 17)
(17, 0)
(17, 0)
Let D(x, y) = (xxc)2+(yyc)2–R2
If point(x,y) is outside the circle, D(x,y)>0。
If point(x,y) is inside the circle, D(x,y)<0。
(xc, yc)
(xi+1, yi)
(xi+1, yi1)
(xi, yi1)
(xi, yi)
(xi+1, yi)
(xi+1, yi1)
(xi, yi1)
Bresenham’s Circle AlgorithmTwo choice: (xi+1, yi) or (xi+1, yi1)
(x0 + a, y0 + b)
R
(x0, y0)
(xx0)2 + (yy0)2 = R2
Circle starts at (x0, y0 + R)
Let’s use another incremental algorithm with decision variable evaluated at midpoint
Using the Symmetry(x0, y0)
for (x = x0+1; (x – x0) < (y – y0); x++) {
if (decision_var < 0) {
/* move east */
update decision_var;
}
else {
/* move south east */
update decision_var;
y;
}
Pixel(x, y);
}
Sketch of Incremental AlgorithmE
SE
negative if we move E, positive if we move SE (or vice versa).
Follow line strategy: Use implicit equation of circle
f(x,y) = x2 + y2 – R2 = 0
f(x,y) is zero on circle, negative inside, positive outside
If we are at pixel (x, y)
examine (x + 1, y) and (x + 1, y – 1)
Compute f at the midpoint
What we need for Incremental AlgorithmEvaluate f(x,y) = x2 + y2 – R2
at the point
We are asking: “Is
positive or negative?” (it is zero on circle)
If negative, midpoint inside circle, choose E
vertical distance to the circle is less at
(x + 1, y) than at (x + 1, y–1).
If positive, opposite is true, choose SE
æ
ö
1
+

ç
÷
x
1
,
y
2
è
ø
2
æ
ö
æ
ö
1
1
+

=
+
+


2
2
ç
÷
ç
÷
f
x
1
,
y
(
x
1
)
y
R
2
ø
è
2
ø
è
E
P = (xp, yp)
M
ME
SE
MSE
Ok for lines, since d and dvertare proportional
For circles, not true:
Which d is closer to zero? (i.e. which of the two values below is closer to R):
The right decision variable?+
=
+
+

2
2
d
((
x
1
,
y
),
Circ
)
(
x
1
)
y
R
+

=
+
+


2
2
d
((
x
1
,
y
1
),
Circ
)
(
x
1
)
(
y
1
)
R
+
+
+
+

2
2
2
2
(
x
1
)
y
or
(
x
1
)
(
y
1
)
“Is (x + 1)2 + y2 or (x + 1)2 + (y – 1)2 closer to R2?”
The two values in equation above differ by
Alternate Phrasing (1/3)+
+

+
+

=

2
2
2
2
[(
x
1
)
y
]
[(
x
1
)
(
y
1
)
]
2
y
1
(0, 17)
fE = 12 + 172 = 290
(1, 17)
E
fSE = 12 + 162 = 257
(1, 16)
SE
fE – fSE = 290 – 257 = 33
2y – 1 = 2(17) – 1 = 33
is closer if its difference from R2 is less than
i.e., if
then
so
so
so
Alternate Phrasing (2/3)æ
ö
1

ç
÷
(
2
y
1
)
2
è
ø

+
+

2
2
2
R
[(
x
1
)
(
y
1
)
]
1

y
(
2
1
)
<
2
1
2
2
2
<

+
+
+


0
y
(
x
1
)
(
y
1
)
R
2
1
2
2
2
<
+
+

+
+


0
(
x
1
)
y
2
y
1
y
R
2
1
2
2
2
<
+
+

+

0
(
x
1
)
y
y
R
2
2
æ
ö
1
1
<
+
+

+

2
2
ç
÷
0
(
x
1
)
y
R
è
2
ø
4
is positive or negative
And the vertical distance decision is whether
is positive or negative; d1 and d2 are apart.
The integer d1 is positive only if d2 + is
positive (except special case where d2 = 0).
Alternate Phrasing (3/3)2
æ
ö
1
1
=
+
+

+

2
2
ç
÷
d
1
(
x
1
)
y
R
2
4
è
ø
2
æ
ö
1
=
+
+


2
2
ç
÷
d
2
(
x
1
)
y
R
2
è
ø
at successive points?
Answer: Note that
is just
and that
is just
Incremental Computation, Again2
æ
ö
1
=
+
+


2
2
ç
÷
f
(
x
,
y
)
(
x
1
)
y
R
2
è
ø
+

f
(
x
1
,
y
)
f
(
x
,
y
)
D
=
+
(
x
,
y
)
2
x
3
E
+


f
x
y
f
x
y
(
1
,
1
)
(
,
)
D
=
+

+
(
x
,
y
)
2
x
3
2
y
2
SE
(1/2)
If we move SE, update by adding 2x + 3 – 2y + 2.
Forward differences of a 1st degree polynomial are constants and those of a 2nd degree polynomial are 1st degree polynomials
this “first order forward difference,” like a partial derivative, is one degree lower
Incremental Computation(2/2)
F
F’
F’’
Similarly
D
=
+
(
x
,
y
)
2
x
3
E
D
+

D
=
(
x
1
,
y
)
(
x
,
y
)
2
E
E
D
+


D
=
(
x
1
,
y
1
)
(
x
,
y
)
2
E
E
D
+

D
=
(
x
1
,
y
)
(
x
,
y
)
2
SE
SE
D
+


D
=
(
x
1
,
y
1
)
(
x
,
y
)
4
SE
SE
Second Differences(1/2)
This is also true of ΔSE(x, y)
Having drawn pixel (a,b), decide location of new pixel at (a + 1, b) or (a + 1, b – 1), using previously computed d(a, b).
Having drawn new pixel, must update d(a, b) for next iteration; need to find either d(a + 1, b) or d(a + 1, b – 1) depending on pixel choice
Must add ΔE(a, b)or ΔSE(a, b) to d(a, b)
So we…
Look at d(i) to decide which to draw next, update x and y
Update d using ΔE(a,b) or ΔSE(a,b)
Update each of ΔE(a,b) and ΔSE(a,b) for future use
Draw pixel
Second Differences(2/2)
Bresenham’s Eighth Circle Algorithm
MEC (R) /* 1/8th of a circle w/ radius R */
{ int x = 0, y = R;
int delta_E, delta_SE;
float decision;
delta_E = 2*x + 3;
delta_SE = 2(xy) + 5;
decision = (x+1)*(x+1) + (y  0.5)*(y  0.5) –R*R;
Pixel(x, y);
while( y > x ) {
if (decision < 0) {/* Move east */
decision += delta_E;
delta_E += 2; delta_SE += 2; /*Update delta*/
}
else {/* Move SE */
y;
decision += delta_SE;
delta_E += 2; delta_SE += 4; /*Update delta*/}
x++;
Pixel(x, y);
}
}
1 test, 3 or 4 additions per pixel
Initialization can be improved
Multiply everything by 4 No Floats!
Makes the components even, but sign of decision variable remains same
Questions
Are we getting all pixels whose distance from the circle is less than ½?
Why is y > x the right stopping criterion?
What if it were an ellipse?
Analysis
i.e,
Computation of and is similar
Only 4fold symmetry
When do we stop stepping horizontally and switch to vertical?
2
2
x
y
+
=
1
2
2
a
b
+
=
2
2
2
2
2
2
b
x
a
y
a
b
D
D
SE
E
Aligned Ellipses
How do you check this? At a point (x,y) for which f(x,y) = 0, a vector perpendicular to the level set is f(x,y) which is
This vector points more right than up when
Ñ
é
ù
¶
¶
f
f
(
x
,
y
),
(
x
,
y
)
ê
ú
¶
¶
x
y
ë
û
¶
¶
f
f

>
(
x
,
y
)
(
x
,
y
)
0
¶
¶
x
y
Direction Changing Criterion (1/2)
and
so we check for
i.e.
This, too, can be computed incrementally
¶
f
=
2
(
x
,
y
)
2
a
x
¶
x
¶
f
=
2
(
x
,
y
)
2
b
y
¶
y

>
2
2
2
a
x
2
b
y
0

>
2
2
a
x
b
y
0
Direction Changing Criterion (2/2)
Patterns can be geometric or cosmetic
Cosmetic: Texture applied after transformations
Geometric: Pattern subject to transformations
Cosmetic patterned line
Geometric patterned line
Patterned Lines
Q
P
Q
P