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