Ch ả

ươ i thu t

ng 10:  ậ nâng cao

Các gi

Scan conversion

ª

ể ộ ố ượ

ơ

ª

ồ ọ

ọ ạ ễ Scan conversion: quá trình bi u di n m t đ i t ng hình h c (đo n  ẳ ủ ệ ộ ệ ả th ng, vòng tròn,...) trong b  đ m  nh đ n (frame buffer) c a h   ố th ng đ  h a quét raster. ủ ụ ậ v n hành (drive) the frame buffer thông qua các th  t c – SetPixel((cid:0) ) – GetPixel((cid:0) )

ế ị ể

Frame buffer và thi

t b  hi n th

ª Mô hình ch c năng c a frame buffer

ủ ứ

B C

y R

ươ ả làm t i  nh

x Màn hình

• B=1

•(value=0) => (pixel off) black

•(value=1) => (pixel on) white

Truy c p vào frame buffer

ª Mô hình l p trình

– Mô hình cho frame buffer – Các thao tác lên frame buffer.

const

MaxRow

MaxColumn = 639; {= C ­ 1} = 479; {= R ­ 1} MaxRow = 255; {= soá caùc maøu ­ 1} MaxColor

= 0..MaxColumn;

2 1 0

0

1 2

MaxColumn

{moät ví duï}

type col row = 0..MaxRow; color = 0..MaxColor;

{read frame buffer}

procedure SetPixel(c : col, r : row, value : color); {load frame buffer} function    GetPixel(c : col, r : row) : color; procedure SetPixelWord(c : col, r : row, value : word);    function    GetPixel(c : col, r : row) : word;

Thu t toán v

ẽ đo n th ng

ª Yêu c uầ

ẳ ạ ủ đo n th ng

ơn ộ ố

ậ ặ ạ

ụ ư nhau ộ đ  sáng nh ờ ẳ đư ng th ng) ẽ – Đi qua 2 đi m ể đ u mút c a  ầ – Đ  sáng  đ ng ồ ề ộ đ u, tr – Đư ng th ng có  ẳ ờ – Gi ả ả i thu t ph i có tính l p l – Không ph  thu c vào các ch n  ộ ả đ  d c khác nhau ph i có  ể đ  xóa  ắ đ u vầ i (dùng  ể ọ đi m b t

Gi

i thu t DD_Line

ª Procedure DD_Line(row1,col1,row2,col2,color:integer);      {Giaû söû ñoä doác naèm giöõa [­1,1], col1<= col2}

var

dx, dy, y, m: real; x: integer;

begin

dx:= col2­col1; dy:= row2 – row1; m:= dy/dx; y:= row1; for x:=col1 to col2 do        begin

SetPixel(x, Round(y),color); y:= y + m;

end;

end;

Thu t toán Bresenham

ậ ả ữ i thu t DD_Line ạ ª Nh ng h n ch  c a gi

ữ ớ đi m ể đ u mút l n ầ

ộ ả đ uề

ố ỉ

ộ ị ế ủ – Ch m vì s  d ng hàm Round ử ụ – Không chính xác khi kho ng cách gi a 2  – Đ  sáng không  đ ng ồ ª Thu t toán Bresenham – Ch  dùng s  nguyên – Thu c vào l p gi ả đ nh t a ọ đ  c a ộ ủ đi m ể

ệ ể ớ ự hi n hành d a vào t a ậ i thu t incremental (xác  ư c)ớ ộ ủ đi m tr ọ đ  c a

Bi u di n đo n th ng trong frame buffer

ố ể xa , ya) và (xb , yb),

ẳ ạ ª Cho đo n th ng n i hai đi m ( ọ ộ ề ễ ườ ọ ộ ẳ ng th ng:

(cid:0) (cid:0)

– các t a đ  đ u là s  nguyên (t a đ  trong frame buffer)  ủ ườ ể y = m(x (cid:0)  xa) + ya ng minh c a đ ª Bi u di n t y – Đ  d c:                   , v i ớ ộ ố m (cid:0) x (cid:0) y = yb (cid:0)  ya (cid:0) x = xb (cid:0)  xa ị ể ễ ạ ẳ ố ấ t” nh t

ª Bài toán: Xác đ nh các pixel bi u di n đo n th ng “t ị ª Wlog (without loss of generality), xa < xb và 0 < m < 1

ố ộ – tùy thu c vào cách đ nh nghĩa sai s

a ừ đ n bế

– X tăng t – X tăng nhanh hơn y  – M i l n x t ỗ ầ ăng lên 1, y không tăng ho c tặ ăng lên 1

Sai s  khi ch n pixel

ª

ầ Sinh các pixel b ng ph

ª Đ nh nghĩa

(cid:0) 1  1) (cid:0)  y*

ị ằ sai số

ươ ng pháp tăng d n e(Ti) = y* (cid:0)  yi (cid:0) (cid:0) 1 (cid:0) e(Si) = (yi (cid:0)

ạ ưở ẳ Đo n th ng lý t ng

Si

y* yi (cid:0)  1

Ti

xi xi (cid:0)  1

ấ ỉ ố

Quy t c ch n pixel x p x  t

ự ẳ t đo n th ng th c

ª Quy t c ch n pixel

ắ ọ

ế Ch n ọ Ti n u và ch  n u ỉ ế e(Ti) ­ e(Si) < 0

(cid:0) 1) (cid:0)  1

Tính e(Ti) (cid:0)  e(Si) = 2m(xi (cid:0)  xa) + 2(ya (cid:0)  yi (cid:0)

ể ỉ ị

(*) ớ ố ừ T  trên, đ  ch  tính v i s  nguyên, đ nh nghĩa ei = Dx(cid:0) (e(Ti) ­ e(Si))     = 2(Dy)(xi ­ xa) + 2(Dx)(ya ­ yi ­ 1) ­ Dx

ế N u ế ei < 0 thì ch n ọ yi = yi ­ 1 , n u không thì ch n ọ yi = yi ­ 1 + 1

ắ ủ ể ầ ắ C n ki m tra tính đúng đ n c a quy t c trên!

ắ ủ Ki m tra tính đúng đ n c a quy t c ch n pixel

ª Tr

ườ ẳ ợ ưở ạ ng h p đo n th ng lý t ng đi qua gi a ữ Si và Ti

ạ ưở ẳ Đo n th ng lý t ng

Si

y*

yi (cid:0)  1

Ti

xi xi (cid:0)  1

e(Ti) = y* ­ yi ­ 1 e(Si) = (yi ­ 1 + 1) ­ y*

ắ ủ Ki m tra tính đúng đ n c a quy t c ch n pixel  (ti p)ế

ª Các tr

ườ ạ ợ ng h p còn l i

ạ ưở ạ ẳ đo n th ng lý t ng

đi qua phía d ẳ đo n th ng lý t ng đi qua phía trên Si và Ti ưở i ướ Si và Ti

Si Si Ti yi (cid:0)  1 yi (cid:0)  1

Ti xi xi xi (cid:0)  1 xi (cid:0)  1

e(Ti) >= 0 e(Si) <= 0 i: e(Ti) <= 0 e(Si) >= 0

ắ ạ e(Ti) = y* ­ yi ­ 1 Nh c l                  e(Si) = (yi ­ 1 + 1) ­ y*

ố ộ

Tính sai s  m t cách h u hi u

ª T  ừ

(cid:0) 1) (cid:0)  (cid:0) x

suy ra

ừ T  trên, ei = 2((cid:0) y)(xi (cid:0)  xa) + 2((cid:0) x)(ya (cid:0)  yi (cid:0) ei + 1 = 2(Dy)(xi + 1 ­ xa) + 2(Dx)(ya ­ yi ) ­ Dx ei + 1 = ei + 2(Dy)(xi + 1 ­ xi) ­ 2(Dx)(yi ­ yi ­ 1 )

ei + 1 = ei + 2Dy ế – n u không thì ch n

ọ ắ Theo quy t c ch n pixel, – n u ế ei < 0 thì ch n ọ yi = yi ­ 1

ei + 1 = ei + 2Dy ­ 2Dx

ọ yi = yi ­ 1 + 1

ậ ủ

Gi

i thu t c a Bresenham

ẳ ª Bi u di n đo n th ng trong frame buffer

ư ế ễ i thu t b t đ u nh  th  nào? ể – Gi

ừ ạ ậ ắ ầ ả ª x0 = xa, y0 = ya ª T  (*) có e1 = 2(Dy) ­ Dx (dùng x1 ­ xa = 1)

procedure Bresenham(xa, xb : col; ya, yb : row; col_val : color); {veõ ñoaïn thaúng coù maøu laø col_val töø (xa, ya) ñeán (ya, yb)} {wlog, xa < xb vaø 0 < ñoä doác cuûa ñoaïn thaúng < 1} var

{thay ñoåi cuûa sai soá khi y taêng} {thay ñoåi cuûa sai soá khi y khoâng taêng}

x : col; y : row; dx, dy, e_inc, e_noinc, e : integer; {sai soá hieän thôøi}

ậ ủ

ế

Gi

i thu t c a Bresenham (ti p)

begin

{2dx­dy}

y := ya; dx := xb ­ xa; dy := yb ­ ya; e_noinc := dy + dy; {2dy} e := e_noinc ­ dx;    {e1=2dy­dx} e_inc := e ­ dx; for x := xa to xb do {voøng laëp chính} begin

SetPixel(x, y, col_val); if e < 0 then e := e + e_noinc; else begin

y := y + 1; e := e + e_inc

end;

end;

end; {Bresenham}

ườ

Các tr

ợ ng h p khác

ả s ế i quy t các ả ử xa > xb và 0 < m < 1. Gi

ª

ả ườ ạ

ầ đ u mút)

ậ i thu t Bresenham gi   Gi ợ i: ng h p còn l tr ổ ị xa > xb (đ i v  trí hai  ủ ổ

ộ ố ằ

m < 0 (thay dy b ng –dy) ằ ủ ổ đ i vai trò c a x và y)

ª m > 1 (đ i vai trò c a x và y) ª Đ  d c âm: ­1 <  ª m < ­1 (thay dx b ng –dx,  ạ ª Đo n th ng đ ng và đo n th ng n m ngang

ứ ằ ẳ ẳ ạ

Bi u di n vòng tròn trong frame buffer

ª Bài toán: Xác đ nh các pixel bi u di n vòng tròn

ể ễ ị y2 = R2 – x2  “t t” ố

ị ố nh tấ – tùy thu c vào cách đ nh nghĩa sai s

ª Gi

(cid:0) ộ ế i quy t ố ứ ỉ ầ ẽ ả – Do đ i x ng, ch  c n kh o sát cách v  khi 0 x sao cho y(x) (cid:0) x

AB. ứ t c là cung

ằ ươ – Sinh các pixel b ng ph ầ ng pháp tăng d n (incremental).

ố ứ

Đ i x ng trên vòng tròn

ả ằ ổ

ª Gi m phí t n tính toán b ng cách dùng phép đ i x ng trên vòng tròn ng  ng v i m t cung là 1/8 vòng

ố ứ ộ ươ ứ ớ – Ch  c n xác đ nh các pixel t

ỉ ầ ở ị ọ  đây ch n cung tròn, AB. y

((cid:0) x, y) (x, y)

A

B

(y, x) ((cid:0) y, x)

x

((cid:0) y, (cid:0) x) (y, (cid:0) x)

((cid:0) x, (cid:0) y) (x, (cid:0) y)

Sai s  khi ch n pixel

ª Gi

ả ử ố s  có pixel t t nh t t ấ ạ ướ i b c th ứ i ­ 1 là Pi ­ 1 = (xi ­ 1, yi ­ 1)

ª Đ nh nghĩa

Pi (cid:0)  1

Si

ª Đ nh nghĩa

Si = (xi ­ 1 + 1, yi ­ 1)   Ti = (xi ­ 1 + 1, yi ­ 1 ­ 1) ị yi (cid:0)  1

Ti

sai số e(P) = (x2 + y2) ­ R2

ª Đ nh nghĩa

ị ế ị hàm s  quy t đ nh

ố di = e(Si) + e(Ti)

xi xi (cid:0)  1

ỉ ố

Qui t c ch n pixel x p x  t

t cung vòng tròn

Pi (cid:0)  1

Si

ế N u ế di < 0 thì ch n ọ Si  còn n u không thì ch n ọ Ti

Ti

yi (cid:0)  1

xi xi (cid:0)  1

ắ ủ ể ầ ắ C n ki m tra tính đúng đ n c a quy t c trên!

ắ ủ Ki m tra tính đúng đ n c a quy t c ch n pixel

ª Nh c l

ª Tr

Si

Si

Si

Ti

Ti

Ti

ắ ạ di = e(Si) + e(Ti) ườ ờ ng h p: ơn) i:  ợ di < 0 (Si g n ầ đư ng tròn h

e(Si) > 0 e(Ti) < 0 e(Si) < 0 e(Ti) < 0

e(Si) > 0 e(Ti) > 0 Không th !ể OK!

(cid:0) ơ ng tròn h n OK, vì di < 0 ầ ườ  Si g n đ

ắ ủ

ế

Ki m tra tính đúng đ n c a quy t c ch n pixel (ti p)

ª Nh c l

ª Tr

Si

Si

Si

Ti

Ti

Ti

ắ ạ di = e(Si) + e(Ti) ườ ờ ng h p: ơn) i:  ợ di (cid:0) 0 (Ti g n ầ đư ng tròn h

e(Si) > 0 e(Ti) > 0

e(Si) < 0 e(Ti) < 0 Không th !ể OK!

(cid:0) e(Si) > 0 e(Ti) < 0  0 ầ ườ ơ ng tròn h n OK, vì di (cid:0)  Ti g n đ

ế ị

Tính hàm s  quy t đ nh m t cách h u hi u

ắ ạ e(P) = (x2 + y2) ­ R2

ª Nh c l i:  ể ứ ª Có th  ch ng minh đ

ượ

2) ­ 2(yi ­ yi ­ 1)

ậ c (bài t p): 2 ­ yi ­ 1

di + 1 = di + 4 xi ­ 1 + 6 ế

di + 1 = di + 4 xi ­ 1 + 6 + 2(yi ọ ắ Theo quy t c ch n pixel – n u ế di < 0 thì ta có yi = yi ­ 1 , do đó ch n ọ Ti

di + 1 = di + 4(xi ­ 1 ­ yi ­ 1) + 10

– n u không thì yi = yi ­ 1 ­ 1, do đó ch n ọ Si

ª Gi

ư ế i thu t b t đ u nh  th  nào?

ả ậ ắ ầ   x0 = 0, y0 = R do đó S1 = (1, R) và T1 = (1, R ­ 1), v yậ d1=e(S1) + e(T1) =(12+R2­R2)+(12+(R­1)2­R2)=3 ­ 2R

ậ ủ

Gi

i thu t c a Michener

ª Bi u di n vòng tròn trong frame buffer

ễ ể

procedure MichCirc(xc : col; yc : row; Rad : integer; value : color); {Veõ voøng troøn coù taâm (xc, yc), baùn kính Rad, vaø maøu value} var

x : col; y : row; d : integer;

begin

x := 0; y := Rad; d := 3 ­ 2*Rad;

ậ ủ

ế

Gi

i thu t c a Michener (ti p)

while x <= y do begin

{update error term}

SetPixel(xc + x, yc + y, value); {draw 8 points } SetPixel(xc ­ x, yc + y, value); {based on (x, y)} SetPixel(xc + x, yc ­ y, value);  SetPixel(xc ­ x, yc ­ y, value); SetPixel(xc + y, yc + x, value); SetPixel(xc ­ y, yc + x, value); SetPixel(xc + y, yc ­ x, value); SetPixel(xc ­ y, yc ­ x, value); if d < 0 then d := d + 4*x + 6 else begin

d := d + 4*(x ­ y) + 10; y := y ­ 1

end; x := x + 1

end

end; {MichCirc}

Đ nh nghĩa vùng

ằ ằ

ị ị

ª Đ nh nghĩa vùng b ng pixel ª Đ nh nghĩa vùng b ng

đa giác

Đ nh nghĩa vùng b ng pixel

ế ố

ể ả

ế ố ế

ể ả

ế ố ế

– 8­connected: 2 đi m  nh đ

c xem là k t n i n u  ọ chúng n m k  nhau theo chi u ngang hay chi u d c c xem là k t n i n u

ủ ª D a trên màu c a các pixel ª Hai cách đ nh nghĩa tính k t n i: – 4­connected: 2 đi m  nh đ ượ ề ượ ề

chúng n m k  nhau theo chi u ngang, chi u d c hay  ườ đ

ằ ng chéo ị ª Hai cách xác đ nh vùng b i:

ể ả

– T t c  các đi m  nh trong vùng có cùng 1 màu, có

ỗ ố ượ

ể ả

ỗ ố

ấ ả ể th  có l – Vùng đ ủ ườ c a đ có màu bao, có th  có l

tr ng (hole) bên trong. c xác đ nh b i các đi m  nh có cùng màu  ể ả ng bao quanh, các đi m  nh bên trong không   tr ng bên trong

Ví dụ

Gi

i thu t tô màu tràn đ  qui

ắ ầ

ồ ọ ầ ª Dùng trong các ph n m m đ  h a ở ª Vùng xác đ nh b i 1 màu và 4­connected ạ ở ª B t đ u b ng b i 1 đi m h t gi ng (seed) n m bên trong

ắ ầ ừ ể

ổ ừ

}

màu int_color sang new_color

đi m (x,y), đ i t

ị ằ vùng c n tôầ procedure FloodFill(x : col; y : row; int_color, new_color : color); {b t đ u t begin

if GetPixel(x, y) = int_color then begin

SetPixel(x, y, new_color); FloodFill(x – 1, y, int_color, new_color); FloodFill(x + 1, y, int_color, new_color); FloodFill(x, y + 1, int_color, new_color); FloodFill(x, y – 1, int_color, new_color);

end end;

Gi

i thu t tô màu tràn đ  qui (

tt.)

ắ ầ

ở ở

ª Vùng xác đ nh b i 1 màu và 8­connected ạ ª B t đ u b ng b i 1 đi m h t gi ng (seed) n m bên trong

ị ằ vùng c n tôầ

ª Thêm:

. Nh

ề ầ i nhi u l n

FloodFill(x – 1, y – 1, int_color, new_color); FloodFill(x – 1, y + 1, int_color, new_color); FloodFill(x + 1, y + 1, int_color, new_color); FloodFill(x + 1, y – 1, int_color, new_color); ể ượ c đi m: ị ặ ạ ­ b  l p l ễ ị ­ d  b  tràn stack

Gi

i thu t tô màu tràn đ  qui (

tt.)

ắ ầ

ở ở

ª Vùng xác đ nh b i màu bao và 4­connected ạ ª B t đ u b ng b i 1 đi m h t gi ng (seed) n m bên trong

ị ằ vùng c n tôầ

ắ ầ ừ ể

ổ ừ

}

màu int_color sang new_color

đi m (x,y), đ i t

procedure FloodFill(x : col; y : row; int_color, new_color : color); {b t đ u t begin

if (GetPixel(x, y) >< bound_color) and (GetPixel(x, y) >< new_color) then begin

SetPixel(x, y, new_color); FloodFill(x – 1, y, int_color, new_color); FloodFill(x + 1, y, int_color, new_color); FloodFill(x, y + 1, int_color, new_color); FloodFill(x, y – 1, int_color, new_color);

end end;

Run of Pixels

ả ả

ª Gi ª Gi

ế  thi t các pixel là 4­connected ậ i thu t

Push address of seed pixel on the stack; while stack not empty do

Pop the stack to provide the next seed;    Fill in the run defined by the seed;    Examine the row above for runs reachable from this run;    Push the address of the rightmost pixels of each such run;    Do the same for the row below the current run; end;

Ví dụ

Ví dụ

D

C

Ví dụ

J I

G F C

Tô màu vùng đa giác

ừ ộ ệ

ớ ấ ả ạ t c  các c nh c a đa giác

ế ắ ầ ị

ª Xét t ng dòng ngang trên b  đ m màn hình: – Tìm các giao đi m c a dòng v i t ủ ể ủ – S p x p các giao đi m theo chi u tăng d n giá tr  x ề ể – Tô các đi m  nh n m gi a các c p giao đi m ữ ằ

ể ả ể ặ

Tô màu vùng đa giác

ạ ầ ả ử

ự ả không còn đúng khi ị  đi m mút không ph i là c c tr

ươ

ị ộ ạ ủ ế ể ầ ố i quy t: d ch đi m đ u mút c a m t c nh xu ng 1

ằ ª C nh n m ngang không c n ph i x  lý ở ể ẵ ẻ ª Tính ch n l ị ng. đ a ph – Cách gi ả pixel

Tô màu vùng đa giác

ª Active Edge List (AEL) l

ợ ụ ậ ủ ạ

i d ng tính lân c n c a c nh ẽ ắ ở ữ ắ ở

ª

ể ự ố ạ ủ ướ ể ị c

– nh ng c nh c t b i scanline y s  c t b i scanline y+1 – giá tr  x c a giao đi m cĩ th  d  đ n tr type

edge_ptr = ^edge_info edge_info = record

y_upper      : row; x_int      : real; recip_slope : real; next : egde_ptr;

end;

Tô màu vùng đa giác

ª update AEL cho scanline y+1 ấ ả ữ

ạ ằ

ạ ể

ả ắ

ể ị

– xĩa t t c  nh ng c nh cĩ y_upper < new_y – thay đ i x_value b ng cách c ng thêm recip_slope ổ – cĩ th  thêm vào c nh m i cĩ y_lower = new_y ớ ể – th  t ứ ự ủ  c a giao đi m cĩ th  b  xáo tr n, nên ph i s p  ế ạ i x p l

Tô màu vùng đa giác

ª Xây d ng b ng c nh: edge_table:

array [row] of

ự edge_ptr