Một vùng tô bao gồm đường biên và vùng bên trong. Đường biên là một đường khép kín, ví dụ như đa giác.
BI ĐỒ HOẠ MÁY TlNH
Các thuộc tính của vùng tô bao gồm:
- Thuộc tính của đường biên chính là các thuộc tính như thuộc tính của đoạn thẳng.
- Thuộc tính của vùng bên trong bao gồm màu tô và mẫu tô. 2.1.7. Ký tự, chuỗi ký tự
Hình 2.9. Vùng tồ với các dạng đường biên và mẫu tô khác nhau
Các chuồi ký tự giúp hiển thị nội dung các thông điệp theo một ngôn ngừ nào đó.
Các thuộc tính của ký tự bao gồm: - Màu sắc của các ký tự.
- Kiểu chừ là bộ ký tự dùng để hiển thị; nó định nghĩa kiểu, kích thước cùa ký tự hiển thị. Hình dạng của mỗi ký tự có thể được xác định bời một tập các đường gấp khúc (trường hợp font vector) hay là mẫu các pixel (font bitmap). Có nhiều loại font khác nhau như font bitmap, font truetype, font CHR (hình 2.10).
1 1 1 1 1 1 0 0 0 1 0 0 1 1 0 ồ 1 1 0 0 1 1 0 0 1 1 1 1 1 0 0 0 1 1 0 a 1 1 0 0 1 1 0 0 1 1 0 ) 1 1 ) 1 1 0 0 0 0 ỡ 0 0 0 0 0
Hình 2.10. Dạng bitmap và vector của font ký tự B
- Kích thước bao gồm chiều cao và chiều rộng của ký tự. Các ký tự được định nghĩa bằng đường gấp khúc, có thề dề dàng thay đổi kích thước hơn là các ký tự định nghĩa băng mẫu các pixel.
CÁC ĐỐI TƯỢNG ĐỒ HOẠ c ơ SỞ
- Cách hiển thị tuần tự của các ký tự có thể là phải sang trái, từ trên xuống dưới, từ trái sang phải, từ dưới lên trên.
- Hướng cùa ký tự.
2.2. CẢC THUẬT TOÁN VẼ ĐƯỜNG THẢNG
Già sử toạ độ các điểm nguyên sau khi xấp xỉ đối tượng thực lần lượt là (Xj, Ỵi), i = 0 , 1,...Đây là các điểm nguyên sẽ được hiển thị trên màn hình.
Bài toán đặt ra là, nếu biết được (Xj, yj)là toạ độ nguyên xác định ở bước thứ i, điểm nguyên tiếp theo (Xj + 1, y; + i)sẽ được xác định như thế nào.
Nhận xét rằng, để đối tượng hiển thị trên lưới nguyên được liền nét, các điểm mà (Xj +1, yj +1) có thể chọn chi là một trong tám điểm được đánh sổ từ 1 đến 8 như hình 2.11 (điểm I I I ---公--备 -_备 -- I I I I I 義 I I I I I I I I I
đen chính là (x„ yO), nói cách khác: Hinh 2.11. Các điém (xi + 1, yìt1)
( \ + 1,义 + 1) = ^ ± l,y ,± 1). cóthể chọn ở bước ( i + 1)
Dáng điệu cùa đường sẽ cho gợi y khi chọn một trong tám aiem trên. Cách chọn các điểm như thế nào tuỳ thuộc vào từng thuật toán trên cơ sở xem xét tới vấn đề tối ưu tốc độ.
2.2.1. Thuật toán vẽ đoạn thang
Xét đoạn thẳng có hệ số góc 0 < m < 1 và Dx > 0. Với các đoạn thẳng dạng này, nếu (Xị, y,)là điểm đã xác định được ở bước thứ i (điểm màu đen) thì điểm cần chọn (Xị +1, yi+ i) ở bước thứ (i + 1 )sẽ là một trong hai trường hợp như hình 2.12.
x i+| = X | + 1
yi+丨e{y,,y丨+1} Như vậy:
tn Đô HOA MÁY TỈNH
Vấn đề còn lại là cách chọn một trong hai điểm trên như thế nào để có thề tối ưu về mặt tốc độ.
Hình 2.12. Các điểm (Xị + f, y/ + ì) chọn ở bước + 1) cho trường hợp đoạn thẳng có hệ số góc 0 < m < 1
2.2.2. Thuật toán DDA (Digital DiíTerentỉal Analyzer)
Với thuật toán DDA, việc quyết định chọn y,+1là y, hay Ỵi + 1 dựa vào phương trình của đoạn thẳng y = mx + b theo (1.2). Nghĩa là, ta sẽ tính toạ độ cùa điểm (Xị + 1 ,y) thuộc về đoạn thẳng thực; tiếp đó, yi+ Ị sẽ là giá trị sau khi làm tròn giá trị tung độy.
Hình 2.13. Mình hoạ thuật toán DDA
Nhu vậy, ta có: jy = m(x. +1) + b Ịy j+I =Round(y)
Nếu tính trực tiếp giá trị thực y ở mỗi bước từ phương trình y = mx + b thì phải cần một phép toán nhân và một phép toán cộng số thực. Đẻ cài thiện tốc độ, người ta tính giá trị thực của y ờ mồi bước theo cách sau để khử phép tính nhân trẽn số thực:
ぬ, CÁC ĐÒI TƯỢNG ĐÔ HOẠ c ơ SỞ ia
ysau = m x i + ! + b = m ( X j + 1); y,ruớc = m X i + b => ysau = ytrước + m
> Lưu đồ thuật toán DDA vẽ đoạn thẳng
Hinh 2.14. Lưu đồ thuật toán DDA vẽ đoạn thẳng qua hai điểm (xh yy;và (x2, yz)
> Chuông trình Ct0201 # i n c lude < c s t d l i b > # i n c lude < i o s t r e a m > ♦^include < c o n i o . h> ^ i n c l u d e < g r a p h i c s .h> # i n c l u d e < m a t h .h>
♦♦define r o u n d (a) int (a + 0.5) u s i n g n a m e s p a c e s t d;
int c o l o r = GREEN;
ĐỒ HOẠ MÁY TÍNH int X = x l; float y = y l; float m = (y2 - y l ) / ( x 2 - x l) ; // Bat d a u ve p u t p i x e l ( x , r o u n d (y),c o l o r) ; for (int i = x l; i < x 2; i ++) X ++; y + = m; p u t p i x e l ( X , r o u n d (y),c o l o r ) ; } }
int m a i n (int argc, c h a r * a r g v [])
{ int m h = 0, mo d e = 0; i n i t g r a p h ( & m h , & m〇d e , "•.\ \ B G I " ); L i n e D D A d O O , 1 0 0 , 6 0 0 , 4 0 0 ) ; l i n e ( 1 0 0 , l 0 0 , 6 0 0 , 4 0 0 ) ; g e t c h O ; c l o s e g r a p h( ) ; s y s t e m (" P A U S E" ) ; r e t u r n E X I T S U C C E S S; Hình 2.15. K ế t q uả c h ư ơ n g trìn h vẽ đ ư ờ n g th ắ n g
CÁC ĐỒI TƯỢNG ĐÔ HOẠ c ơ SỞ B I
Nhận xét:
- Việc sử dụng công thức ysau = ytrước + m để tính giá trị y tại mồi bước đã giúp cho thuật toán DDA nhanh hơn hẳn so với cách tính y từ phương trình y = mx + b do khử được phép nhân trên số thực. Tuy nhiên, việc cộng dồn giá trị thực m vào y cỏ thể sẽ tích luỹ sai số làm cho hàm làm tròn có kết quà sai, dẫn tới việc xác định vị trí cùa điềm vẽ ra bị chệch hướng so với đường thẳng thực. Điều này chi xảy ra khi vẽ đoạn thẳng khá dài.
- Tuy đã khử được phép nhân số thực, nhưng thuật toán DDA vần còn bị hạn chế về mặt tốc độ do vẫn còn phép toán cộng số thực và làm tròn, cỏ thể khắc phục thao tác cộng số thực m và làm tròn trong thuât toán bằng cách nhân xét m = —^ với Dy, Dx là các số nguyên.
Dx
2.2.3. Thuật toán Bresenham
Thuật toán Bresenham đưa ra cách chọn yi +1là yi hay y, + 1 theo một hướng khác, sao cho có thế tối ưu hoá về mặt tốc độ so với thuật toán DDA. vấn đề ở đây là làm thế nào để hạn chế tối đa các phép toán trên số thực trong thuật toán bằng cách chuyển sang các phép toán trên số nguyên.
ĐÔ HOẠ MÁY TÍNH
Gọi (x, + 1,y)là điểm thuộc đoạn thẳng. Ta có y = m ( X j + 1)+ b; Đặt dị = y - yi và d2 = (yi + 1 ) - y. Xét tất cả các vị trí tương đối cùa y so với yi và y; + 1 ,việc chọn điểm (Xị + 1, yi + i)là s hay p phụ thuộc vào việc so sánh d| và d2 hay dấu của d| - d2:
- Nếu d| - d2 < 0, ta sẽ chọn điểm s, tức là yj + I = yj.
- Ngược lại, nếu dị - d2 > 0, ta sẽ chọn điểm p, tức là yj +1= yj + 1. Xét Pi = Dx(di - d2) = Dx(2y - 2yj - 1 )
=> Pi = Dx[2(m(Xj+ 1)+ b) - 2yi - 1 ] Thay m = Dy/Dx vào phương trình trên ta được
Pi = 2DyXj - 2Dxyj + c, với c = 2Dy + (2b - 1 )Dx.
Nhận xét:
Do Dx > 0 nên dấu của biểu thức d| - d2 cùng chính là dấu của Pi; nói cách khác, nếu tại bước thứ i ta xác định được dấu cùa p, thì xem như xác định được điểm cần chọn ở bước (i + 1 ).vấn đề còn lại là làm thế nào để tính được Pi tại mồi bước thật nhanh.
Ta có:
p, + I - p, = (2Dyx, + I - 2Dxyi + I + c) - (2Dyx, - 2Dxyị + c) - 2Dy(Xi + I - Xi) - 2Dx(yj +, - y.)
= 2Dy — 2Dx(yi + 1 — yj), do Xị + 1 = Xi + 1 Từ đây có thể suy ra cách tính Pi +1 từ p, như sau: - Nếu Pi < 0 ta chọn Ỵị + I = Ỵị thì: Pi + 1 = Pi + 2Dy;
- Nếu Pi > 0 ta chọn y, +1= yi + 1 thì: Pi + 1 =: Pi + 2Dy - 2Dx. Giá trị Po được tính từ điểm vẽ đầu tiên (x〇, y〇) theo công thức:
Po = 2Dyx〇 - 2Dxy〇 + c = 2Dyx〇 - 2Dxy〇 + 2Dy - (2b - 1 )Dx Do (x〇, y〇)là điểm nguyên thuộc về đoạn thẳng nên ta có
y〇 = mx〇 + b = — .x〇 + b. Dx
被んか,グ 2 - CÁC ĐÔI TƯỢNG ĐÒ H〇Ạ c ơ SỞ
> Lưu đồ thuật toán Bresenham
ĐỒ HOẠ MÁY TÌNH
> Cai đặt minh hoạ thuật toán Bresenham
v o i d Li n e B r e s (int x l , i n t y l , i n t x 2 , int y2)
{
int Dx, Dy, p, Constl, C o n s t 2;
int X, y;
Dx = x2 - x l;
D y = y2 - y l;
p = 2 * Dy - D x ; I I Dy < < 1 一 Dx C o n s t 1 = 2 * D y; I I Dy << 1
Const2 = 2 * (Dy - D x ) ; // (Dy - Dx) << 1 X = x l; y = yl; p u t p i x e l( x , y , C o l o r ); for (i = x l ; i < x 2; i + + ) { if (p < 0) p + = C o n s t l; else { p + = C o n s t 2; y ++; } X + + ; putpixel(x, y, C o l o r) ; } } // L i n e B r e s > Chưong trình 0202 # i n c l u d e < c s t d l i b > # incl u d e < i o s t r e a m > u s i n g n a m e s p a c e s t d; ^ i n c l u d e < q r a p h i c s .h>
^ A . ^ „ a CÁC ĐỒI TƯỢNG ĐỒ HOẠ c ơ SỞ
# i n c l u d e < c o n i o .h>
v o i d B r e s e n h a m一C i r c l e (int xc, int yc, int Radius, int color) { i n t X, y , d; X = 0 ; y = R a d i u s; d = 3 - 2 * R a d i u s ; w h i l e (x <= y) { p u t p i x e l ( x c + X, yc + y, c o l o r ); p u t p i x e l ( x c - X, yc + y, c o l o r) ; p u t p i x e l ( x c + X, yc - y, c o l o r ); p u t p i x e l ( x c — X, yc - y, c o l o r ); p u t p i x e l ( x c + Yi yc + X, c o l o r ); p u t p i x e l ( x c - y, yc + X, c o l o r ); p u t p i x e l ( x c + y, yc - X, c o l o r ); p u t p i x e l ( x c - y , yc - X, c o l o r) ; if (d < 0) d + = 4 * x + 6 ; else { d + = 4 * (X — y) + 10; y ----; } X + + ; } }
int m a i n (int argc, c h a r * a rqv [])
{
int gr d r i v e = DETECT, gr m o d e;
i n i t g r a p h ( & g r — drive, &gr mode, " " 〉 ;
B r e s e n h a m C i r c l e ( g e t m a x x () / 2,
E3 Đ ồ HOẠ MÁY TÌNH B r e s e n h a m _ C i r c l e ( g e t m a x x () / 2, g e t m a x y () / 2, 150, 5) B r e s e n h a m _ C i r c l e ( g e t m a x x () / 2, g e t m a x y () / 2, 200, 6) g e t c h O ; c l o s e g r a p h( ) ; s y s t e m (" P A U S E " ); r e t u r n E X I T S U C C E S S;
Hình 2.18. Két qua • chương trình thuật toán Bresenham
Nhận xét:
- Thuật toán Bresenham chỉ làm việc trên số nguyên và các thao tác trên số nguyên chỉ là phép cộng và phép dịch bit (phép nhân 2), điều này là một cải tiến làm tăng tốc độ đáng kể so với thuật toán DDA. Ý tường chính cùa thuật toán nằm ờ chỗ là xét dấu pi để quyết định điểm kế tiếp, và sử dụng công thức truy hồi p, + 1 - Pjđể tính pi bàng các phép toán đơn giàn trên số nguyên.
^Aư<fna CÁC ĐÔI TƯỢNG Đô HOẠ c ơ SỞ
2.2.4. Thuật toán MidPoint
rhuật toán MidPoint đưa ra cách chọn yi+ I là y, hay yi + 1 bằng cách so sánh điểm thực Q(Xj + 1 ,y) với điểm MidPoint là trung điểm của s và p.
Ta có:
- Nếu điềm Q nằm dưới điểm MidPoint, ta chọn s;
- Ngược lại, nếu điểm Q nằm trên điểm MidPoint ta chọn p.
Hình 2-19. Minh hoạ thuật toán MidPoint
Xét dạng tổng quát của phương trình đường thẳng dạng (1.3): Ax + By + c = 0
với A = Dy = y2 - y i,tí = - Dx = -(x2 - x ị), c = x2y i - Xiy2. Đặt F(x, y) = Ax + By + c, ta cỏ nhận xét:
<0 nếu (x, y) nằm phía trên đường thẳng F(x,y) < = 0 nếu (x, y) thuộc về đường thẳng
>0 nếu (x, y) nằm phía dưới đường thẳng
Lúc này việc chọn các điểm s, p ở trên được đưa về việc xét dấu của:
Pi = 2F(MidPoint) = 2I; X, +l,y, +
ĐỒ HOẠ MÁY TÍNH
- Nếu p, < 0, điểm MidPoint nằm phía trên đoạn thẳng; lúc này điểm thực Q nằm dưới điểm MidPoint, nên ta chọn s, tức là y, +1 = y,.
- Ngược lại, nếu Pi > 0, điểm MidPoint nằm phía dưới đoạn thẳng; lúc này điểm thực Q nằm trên điểm MidPoint, nên ta chọn p, tức làyj + 1=yi + 1.
Mặt khác, để tính Pi + 1 ở bước tiếp theo theo Pi ta xét biểu thức: Pi +1 - Pi Xi+l _ぃ |+丨+ 士 -2 F x 丨 +I, yi + 士 A-(X,+1+1)+B( n y 丨+1 + c - 2 、 2ソ A.(x, +1) + B( 1 〉 y,+ị + c V 2 ) = 2A + 2B(y1+l-y ,) = 2D y-2D x(y1+1 - y .) Vậy:
- Nếu Pi < 0, ta chọn + I = yi, suy ra: Pi + I = Pi + 2Dy
- Nếu p, > 0, ta chọn yi + 1= yi + 1 ,suy ra: Pi + ! = Pi + 2Dy - 2Dx
Ta tính giá trị Po ứng với điểm ban đầu (x〇, y〇), với nhận xét rằng, (x〇, y〇)là điểm thuộc về đoạn thẳng, tức là:
Ax〇+ By〇+ c = 0 ( 1) _ ( 1〉 Po=2F x0 +い 0 +T K ム) =2 A(x0 + 1)+ B y° +去 \ ム) + c = 2(Ax〇 + By〇 + C) + 2A + B = 2A + B = 2Dy - Dx
Nhận xét: Thuật toán MidPoint cho kết quả tương tự như thuật toán Bresenham.
2 - CÁC ĐỐI TƯỢNG ĐÔ HOA c ơ SỞ m
2.3. THUẬT TOÁN VẼ ĐƯỜNG TRÒN
Phương trình đường tròn có tâm là gốc toạ độ, bán kính R là
X2 + y2 = R2.
Từ phương trình này ta có thể đưa về dạng:
y = 土n/r 2 _ x 2 .
Dẻ vẽ các đường tròn có tâm (xc, yc) bất kỳ, đơn gian chi cần tịnh tiến các aiem sau khi vẽ xong đường tròn có tâm là gốc toạ độ theo vector tịnh tien (x〇 yc).
2.3.1. Một số cách tiếp cận vẽ đường tròn
Do tính đoi xứng nên đề vẽ toàn bọ đường tròn, ta chỉ cần vẽ cung 1/4 đường tròn, sau đó lấy Ơ01 xứng đề xác định các aiem còn lại.
Một trong những cách đơn giản nhất là cho X chạy từ 0 đến R (R là bán kính), sau đỏ tính y từ công thức đã cho (chi lấy giá trị dương), rồi làm tròn để xác định giá trị nguyên tương ứng. Cách làm này không hiệu quả do gặp phai các phép toán nhân và lấy căn làm hạn cne tốc độ, ngoài ra đường tròn vẽ ra theo cách này có tne không liền nét (trừ trường hợp R lớn) khi X gần R (do chỉ có một giá trị y duy nhất cho một gia trị x). Có the khắc phục đieu này bàng cách aieu chinh đoi tượng thay đoi là X (roi tính y theo X),hay y ựoi tính
X theo y) tuỳ thuộc vào giá trị tuyệt đối của hệ số góc đường tròn là lớn hơn hay nhỏ hom 1 ,nhưng cách làm này đòi hỏi thêm các phép tính toán và kiểm tra nên làm cho thuật toán phức tạp thêm.
Một cách tiếp cận khác là vẽ các điểm (Rcos0, Rsin0) với 0 chạy từ 0° đến 90°. Cách này sẽ khắc phục hạn chế đường không liền nét của thuật toán trên, tuy nhiên, điểm hạn chế chính của thuật toán này là chọn bước nhảy cho 0 như thế nào cho phù hợp khi bán kinh thay đổi.
Hình 2.20. Đường tròn vẽ ra không liên nét theo cách vẽ đă nêu
2.3.2. Thuật toán MidPoint
Do tính đối xứng của đường tròn (C) cho nên chỉ cần vẽ cung (C1/8) là cung 1/8 đường tròn, sau đó lấy đối xứng. Cung (Cl/8) được mô tả như sau (cung của phần tô màu hình 2.21).
Như vậy, nếu cỏ (x, y) e (Cl/8) thì các điểm: (y, x), (y, - x), (x, -y), (-X, -y), (-y, -x), (-y, x), ( - X , y) sẽ thuộc (C).
Chọn điểm bắt đầu để vẽ là điểm (0, R). Dựa vào hình vẽ, nếu (x„ Ỵi)là điểm nguyên đã tìm được ờ bước thứ i, thì điểm (xj +1, yj + i) ờ bước thứ (i + 1 ) là sự lựa chọn giữa s và p.
íxi4., = X, + 1
Như vậy: <
ly,+丨 e{y 丨,yi-1}
Tương tự như thuật toán MidPoint vẽ đoạn thẳng, việc quyết định chọn một trong hai điểm s và p sẽ được thực hiện thông qua việc xét dấu của một hàm nào đỏ tại điểm MidPoint là điểm nằm giưa chúng.
Hình 2.21. Các vị trí đối xứng {rén đường tròn (C) tương ứng VỚI (x, y)
欲, CAC ĐÔI TƯƠNG ĐÒ HOA c ơ SỞ ^1
Đặt F(x, y) = X2 + y2 - R2, ta có: <0
F(x,y ) , = 0 >0
nếu (x, y) nằm trong đường tròn nếu (x, y) nằm trên đường tròn nếu (x, y) nằm ngoai đường tròn
Q(Xi+'l,y)
Xét Pi = F(MidPoint) = F Xj +1,yj - — ta có:
- Nếu Pi < 0, diem MidPoint nằm trong đường tròn; lúc này ơiem thực Q gần s hơn, nên ta chọn s, tức là y i + I = y j.
- Ngược lại, nếu p, > 0, điểm MidPoint nằm ngoài đường tròn, lúc này điểm thực Q gần p hơn, nên ta chọn p, tức là yj + ! = y, - 1 . Mặt khác: ( 1) f \ \ Pi + I _ p, = F X_+I+1,y 丨+I_ く 2, - F x.+ly.-T- K ム) (x1+,+1)2 ( x , + 2 ) 2 yi+. y1+i R 2 R 2 ( x , + l ) 2 (X けl)2 y, / ■ —2ノ R R 2 = 2xl +3 + (y;+1- y ^ ) - ( y t+1- y 1) 4-ĐHMTiNH
ĐÔ HOA MẢY TÍNH
Vậy:
- Nếu p, < 0, ta chọn yj + 1= y„ suy ra: Pi + 1= Pi + 2xj + 3.
- Nếu Pi > 0, ta chọn yi+ 1= Ỵj - 1 , suy ra: Pi+I =Pi + 2xj-2yi + 5.
Ta tính giá trị Po ứng với điểm ban đầu (x〇, y〇) = (0, R): Po =F V 1) f n x 0 + Uy〇 -4- Lノ =F 1 , R - - l 2
> Lưu đồ thuật toán MidPoint vẽ đường tròn