Transcript Document

Graphics Primitives: line
Pixel Position
0
1
2
3 4
5
6
0
1
2
3
4
5
6
Line-Scan Conversion Algorithms
 Line scan conversion: determine the nearest pixel
position (integer) along the line between the two
endpoints and store the color for each position in the
frame buffer.
 Three common algorithms
 DDA
 Midpoint
 Bresenham
Line Equations
 The Cartesian slope-intercept equation
((x0,y0)(xend,yend))
 Y=mx+b
yend  y0
m
xend  x0
b  y0  m * x0
 y  m x
Naive Idea
void NaiveLine(int x0,int y0,int xend,int yend,int color)

int x;
float y, m, b;
m=(yend-y0)/(xend-x0);
b = y0 – m*x0;
for (x=x0; xxend; x++)
 drawpixel (x, int(y+0.5), color);
Costly floating point
y=m*x+b;
computations !!

Multiplications,

additions, roundings
DDA (Digital Differential Analyzer
) ALGORITHM
 The digital differential analyzer (DDA) samples the line at
unit intervals in one coordinate corresponding integer
values nearest the line path of the other coordinate.
 The following is the basic scan-conversion(DDA) algorithm
for line drawing (sample at unit x intervals )
for x from x0 to xend
Compute y=mx+b
Draw_fn(x, round(y))
 How to improve???
Reuse Previous Value
 Increment yi 1  m xi 1  b
 m xi  b  mx
 yi  mx
 For x  1 yi 1  yi  m
 Start from x=x0 and y=y0, every position (x,y) can
be computed by incrementation, x by 1 and y by m.
void DDALine(int x0,int y0,int xend,int yend,int color)

int x;
float dx, dy, y, m;
dx = xend-x0, dy=yend-y0;
m=dy/dx;
y=y0+m
No more
drawpixel (x0, y0, color);
multiplications, but
for (x=x0+1; xxend; x++)
still have fp
 drawpixel (x, int(y+0.5), color);
additions,
y=y+m;
roundings


Example:draw segment
P0 (0, 0)  Pend (5, 2)
x
0
1
2
3
4
5
y
0
0+0.4
0.4+0.4
0.8+0.4
1.2+0.4
1.6+0.4
int(y+0.5)
0
0
1
1
2
2
round
Line: P0(0, 0)-- P1(5, 2)
3
2
1
0
1
2
3
4
5
DDA Illustration
Desired Line
(xi+1, Round(yj+m))
(xi, yj)
(xi+1, yj+m)
(xi, Round(yj))
y2
y1
x1
x2
 The above DDALine only suit the condition
that xend>x0 and 0 < m < 1 (octant #1)
 How about the other cases?
 |m| > 1
 xend < x0?
 Octant#2: xend>x0 and 1 < m < ∞
 Octant#3: xend<x0 and -∞ < m < -1
 Octant#5: xend<x0 and 0 < m < 1
m=∞
m=-1 #3 #2 m=1
 Octant#6: xend<x0 and 1 < m < ∞
#4
 Octant#4: xend<x0 and -1 < m < 0
 Octant#7: xend>x0 and -∞ < m < -1
 Octant#8: xend>x0 and -1 < m < 0
#1
m=0
#8
#5
#6
#7
 Octant#2 and #3: reverse the role of x as iterator by y
and increment x by 1/m
 Octant#4: reverse the end points  octant#8
 Octant#5: reverse the end points  octant#1
 Octant#6: reverse the end points  octant#2
 Octant#7: reverse the end points  octant#4
 Octant#8: Just same DDA algorithm for octant#1
 Major deficiency in the above approach :
 Uses floats
 Has rounding operations
 the accumulation of error
Midpoint Algorithm
 Basic thought( 0 < m < 1)
PT
P=(x,y)
Pi(xi,yi)
Q
M
M(xi+1,yi+0.5)
PB
According the position of M and Q, choose the next
point Pt or Pb
 Line equation ( (x0,y0) , (xend,yend) )
F ( x, y )  ax  by  c  0
a  y0  yend
b  xend  x0
c  x0 ( yend  y0 )  y0 ( xend  x0 )
For any point (x, y):
F(x,y) = 0  (x,y) is on the line
F(x,y) > 0  (x,y) is above the line
F(x,y) < 0  (x,y) is beneath the line
Discriminant Function d
The function is made by using the midpoint M:
d  F ( M )  F ( x p  1, y p  0.5)  a ( x p  1)  b( y p  0.5)  c
d < 0, M is beneath Q, P2 is next point;
d > 0, M is above Q, P1 is the next point;
d = 0, P1 or P2 is right, commonly P1
P2
P=(x,y)
Pi(xi,yi)
Q
M
P1
 Is it (computing the d) costly? No! We can use
the idea in the DDA: use previous d value to
compute next one.
 Incrementation thought
 If d0,then choose the next point: P1 (xp+1, yp), In
order to judge the next point successively,calculate
d1  F ( x  2, y  0.5)  a( x  2)  b( y  0.5)  c  d  a
increment of d is a
 If d<0,then choose the next point:P2 (xp+1, yp+1)。In
order to judge the next point successively ,calculate
d 2  F ( x  2, y  1.5)  a( x  2)  b( y  1.5)  c  d  a  b
increment of d is a+b
 Initial value of d
d 0  F ( x0  1, y0  0.5)  a ( x0  1)  b( y0  0.5)  c
 F ( x0 , y0 )  a  0.5b
 a  0.5b
 In each of iteration
If d >= 0 x  x  1
d d a
Else if d < 0 x  x  1, y  y  1
d  d ab
 Improve again: integer calculations?
 Substitute 2d for d
 Initial value of d d 0  2a  b
 In each of iteration
If d >= 0
Else if d<0
x  x 1
d  d  2a
x  x  1, y  y  1
d  d  2a  2b
 Implementation issue: the quantities (2a) and (2a+2b)
can be precomputed to be two constants.
Example
 Drawing a line from (0,0) to (5.2)
a  y0  y1  2, b  x1  x0  5
d 0  2a  b  1, incre _ d1  2a  4, incre _ d 2  2(a  b)  6,
i
1
2
3
4
xi
0
1
2
3
yi
0
0
1
1
d
1
-3
3
-1
5 4
2
5
3
2
1
0
1
2
3
4
5
void MidpointLine (int x0,int y0,int xend, int yend,int color)
{ int a, b, incre_d1, incre_d2, d, x, y;
a=y0-yend, b=xend-x0, d=2*a+b;
incre_d1=2*a, incre_d2=2* (a+b);
x=x0, y=y0;
drawpixel(x, y, color);
while (x<x1)
{ if (d<0)
{x++, y++, d+=incre_d2; }
else
{x++, d+=incre_d1;}
drawpixel (x, y, color);
} /* while */
} /* mid PointLine */
Bresenham’s Line Algorithm
 An accurate, efficient raster line drawing algorithm
developed by Bresenham, scan converts lines using only
incremental integer calculations that can be adapted to
display circles and other curves.
Bresenham Line Algorithm (cont)
the pixel at (xk,yk) is to be displayed, the next
point will be chosen from (xk +1, yk) and (xk+1, yK+1)
dlower = y – yk = m(xk + 1) + b – yk
dupper = (yk + 1) – y = yk + 1- m(xk + 1) – b
 The difference between these 2 separations is
dlower-dupper = 2m(xk + 1) – 2 yk + 2b – 1
Bresenham’s Line Algorithm
 Define discriminant
Pk = Δx ( dlower-dupper) = 2Δyxk-2 Δxyk + c
 The sign of Pk is the same as the sign of dlower-dupper, since Δx > 0.
Parameter c is a constant and has the value 2Δy + Δx(2b-1)
(independent of pixel position)
 If pk<0, the next point is (xk+1,yk);
 Else
the next point is (xk+1,yk+1)
Bresenham’s algorithm (cont)
 Increment thought:
 At step k + 1, the decision parameter can be evaluated as,
pk+1 = 2Δyxk+1 - 2Δxyk+1 + c
 Taking the difference of pk+ 1 and pk we get the following.
pk+1 – pk = 2Δy(xk+1- xk)-2Δx(yk+1 – yk)
 But, xk+1 = xk +1, so that
pk+1 = pk + 2Δy - 2 Δx(yk+1 – yk)
 Where the term yk+1-yk is either 0 or 1, depending on the sign of
parameter pk
If pk<0 ,pk+1=pk+2 Δy
Else pk+1=pk+2(Δy -2 Δx)
Bresenham’s Line Algorithm
 Initial value of p0
 The first parameter p0 is directly computed
p0 = 2 Δyx0 - 2 Δxy0 + c = 2 Δyx0 – 2 Δxy0 + [2Δy + Δx(2b-1)]
 Since (x0,y0) satisfies the line equation , we also have
y0 = Δy/ Δx * x0 + b
 Combining the above 2 equations , we will have
p0 = 2Δy – Δx
Bresenham’s
Line
Algorithm
void BresenhamLine (int x ,int y ,int x , int y ,int color)
0
0
end
end
{ int dx,dy, incre_p1, incre_p2, p, x, y;
dy=yend-y0, dx=xend-x0;
incre_p1=2*dy, incre_p2=2* (dy-dx);
x=x0, y=y0;
p=2*dy-dx;
drawpixel(x, y, color);
while (x<x1)
{ if (p<0)
{x++, p+=incre_d1; }
else
{x++, y++,p+=incre_d2;}
drawpixel (x, y, color);
} /* while */
} /* Bresenham */