Graphics Primitives: line
Mar 27, 2015
Graphics Primitives: line
Pixel Position
0 1 2 3 4 5 6 0 1 2 3 4 5 6
Line-Scan Conversion AlgorithmsLine 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 algorithmsDDAMidpointBresenham
Line EquationsThe Cartesian slope-intercept
equation ((x0,y0)(xend,yend))Y=mx+b
0
0
end
end
y ym
x x
0 0*b y m x
y m x
Naive Ideavoid 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; xxend; x++)
drawpixel (x, int(y+0.5), color); y=m*x+b;
Costly floating point
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 ValueIncrement
ForStart from x=x0 and y=y0, every position
(x,y) can be computed by incrementation, x by 1 and y by m.
xmy
xmbmx
bmxy
i
i
ii
11
myy ii 11x
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;
for (x=x0; xxend; x++)
drawpixel (x, int(y+0.5), color);
y=y+m;
No more multiplications, but still have fp
additions, roundings
Example : draw segment
x y int(y+0.5) 0 0 01 0+0.4 02 0.4+0.4 13 0.8+0.4 14 1.2+0.4 25 1.6+0.4 2
0 1 2 3 4 5
3
2
1
Li ne: P0( 0, 0) - - P1( 5, 2)
0 (0,0) (5,2)endP P
round
(xi, Round(yj))
(xi+1, yj+m) (xi, yj)
(xi+1, Round(yj+m))
Desired Line
x1 x2
y2
y1
The above DDALine only suit the condition that xend>x0 and 0 < m < 1 (octant #1)
How about the other cases? |m| > 1xend < x0?
Octant#2: xend>x0 and 1 < m < ∞
Octant#3: xend<x0 and -∞ < m < -1
Octant#4: xend<x0 and -1 < m < 0
Octant#5: xend<x0 and 0 < m < 1
Octant#6: xend<x0 and 1 < m < ∞
Octant#7: xend>x0 and -∞ < m < -1
Octant#8: xend>x0 and -1 < m < 0
m=1m=-1
m=∞
m=0
#1
#2#3
#4
#5
#6 #7
#8
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#3 Octant#8: Just same DDA algorithm for
octant#1
Major deficiency in the above approach :
Uses floatsHas rounding operationsthe accumulation of error
Midpoint AlgorithmBasic thought( 0 < m < 1)
M
PT
PB
P=(x,y)Q
Pi(xi,yi)
M(xi+1,yi+0.5)
According the position of M and Q, choose the next point Pt or Pb
Line equation ( (x0,y0) , (xend,yend) )( , ) 0F x y ax by c
0 enda y y 0endb x x
0 0 0 0( ) ( )end endc x y y y x x
For any point (x, y):F(x,y) = 0 (x,y) is on the lineF(x,y) > 0 (x,y) is above the lineF(x,y) < 0 (x,y) is beneath the line
Discriminant Function dcybxayxFMFd pppp )5.0()1()5.0,1()(
P2
P1
MP=(x,y)
Q
Pi(xi,yi)
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
The function is made by using the midpoint M:
Is it (computing the d) costly? No! We can use the idea in the DDA: use previous d value to compute next one.
Incrementation thoughtIf d0 , then choose the next point: P1 (xp+1, yp), In
order to judge the next point successively , calculate
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
increment of d is a+b
adcybxayxFd )5.0()2()5.0,2(1
badcybxayxFd )5.1()2()5.1,2(2
Initial value of d
In each of iteration
0 0 0 0 0
0 0
( 1, 0.5) ( 1) ( 0.5)
( , ) 0.5
0.5
d F x y a x b y c
F x y a b
a b
1xx
add
Else if d < 0badd
1,1 yyxx
If d >= 0
Improve again: integer calculations?
Substitute 2d for dInitial value of d
In each of iteration
Implementation issue: the quantities (2a) and (2a+2b) can be precomputed to be two constants.
bad 20
If d >= 0add 2
badd 22
Else if d<0 1,1 yyxx
1xx
ExampleDrawing a line from (0,0) to (5.2)
i xi yi d1 0 0 12 1 0 -33 2 1 34 3 1 -1
5 4 2 50 1 2 3 4 5
3
2
1
5,2 0110 xxbyya
0 1 22 1, _ 2 4, _ 2( ) 6,d a b incre d a incre d a b
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 */