Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Procedure Circle (xc, yc, R : integer) ; Var x, y : integer ; Procedure DOIXUNG ; Begin putpixel (xc + x , yc +y, color) ; putpixel (xc - x , yc + y, color) ; putpixel (xc + x , yc - y, color) ; putpixel (xc - x , yc- y, color) ; putpixel (xc + y , yc + x, color) ; putpixel (xc - y , yc + x, color) ; putpixel (xc + y , yc - x, color) ; putpixel (xc - y , yc - x, color) ; End ; Begin For x : = 0 to round(R*Sqrt(2)/2) do Begin y : = round(Sqrt(R*R - x*x)) ; DOIXUNG; End ; End ; 1. Thuật toán xét điểm giữa (MidPoint) Do tính đối xứng của đường tròn nên ta chỉ cần vẽ 1/8 cung tròn, sau đó lấy đối xứng là vẽ được cả đường tròn. Thuật toán MidPoint đưa ra cách chọn yi+1 là yi hay yi-1 bằng cách so sánh điểm thực Q(xi+1,y) với điểm giữa MidPoind là trung điểm của S1 và S2. Chọn điểm bắt đầu để vẽ là (0,R).
Giả sử (xi, yi) là điểm nguyên đã tìm được ở bước thứ i (xem hình 1.8), thì điểm (xi+1, yi+1) ở bước i+1 là sự lựa chọn giữa S1 và S2. xi+1= xi + 1 yi+1= yi - 1 yi Trang 18 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản (xi,yi) S1 Q(xi+1,y) yi yi+1 MidPoint yi - 1 S2 Hình 1.8 : Đường tròn với điểm Q(xi+1, y) và điểm MidPoint. F(x,y) < 0 , nếu điểm (x,y) nằm trong đường tròn. F(x,y) = 0 , nếu điểm (x,y) nằm trên đường tròn.
F(x,y) > 0 , nếu điểm (x,y) nằm ngoài đường tròn. Ta có : - Nếu Pi < 0 : điểm MidPoint nằm trong đường tròn. Khi đó, điểm thực Q gần với điểm S1 hơn nên ta chọn yi+1 = yi. - Nếu Pi >= 0 : điểm MidPoint nằm ngòai đường tròn.
Khi đó, điểm thực Q gần với điểm S2 hơn nên ta chọn yi+1 = yi - 1. Mặt khác : Pi+1 - Pi = F(xi+1 +1, yi+1 - 1/2) - F(xi + 1, yi - 1/2) = [(xi+1 +1)2 + (yi+1 - 1/2)2 - R2 ] - [(xi +1)2 + (yi - 1/2)2 - R2 ] = 2xi + 3 + ((yi+1)2 + (yi)2 ) - (yi+1 - yi) Vậy : - Nếu Pi < 0 : chọn yi+1 = yi. Khi đó Pi+1 = Pi + 2xi +3 - Nếu Pi >= 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + 2xi - 2yi +5.
- Pi ứng với điểm ban đầu ( x0 , y0 ) = (0,R) là: 5 P0 = F(x0 + 1, y0 - 1/2) = F(1, R - 1/2) = -R 4 Trang 19 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Lưu đồ thuật toán MidPoint vẽ đường tròn Begin P = 5/4 - R; x=0 ; y= R; Putpixel(x,y,c); No x<y Yes No P<0 Yes P = P + 2*x + 3 P = P + 2*(x-y)+5 y=y-1 x = x +1 putpixel(x,y,color) End Trang 20 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Minh họa thuật toán MidPoint: Procedure DTR(xc, yc, r, mau : integer); var x, y, p : integer ; begin x:=0 ; y:=r; p:=1 - r; while ( y > x) do begin doi_xung; if (p<0) then p:=p+2*x+3 else begin p:=p+2*(x-y)+5 ; y:=y-1; end; x:=x+1; end; {while} end; 1. Vẽ đường tròn bằng thuật toán Bresenham Tương tự thuật toán vẽ đường thẳng Bresenham, các vị trí ứng với các tọa độ nguyên nằm trên đường tròn có thể tính được bằng cách xác định một trong hai pixel gần nhất với đường tròn thực hơn trong mỗi bước ( xem hình 1. (xi,yi) S1 yi d1 yi+1 = y d2 yi - 1 S2 Hình 1.9 : Đường tròn với khoảng cách d1 và d2. Trang 21 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Ta có : d1 = (yi)2 - y2 = (yi)2 - (R2- (xi + 1)2 ) d2 = y2 - (yi - 1)2 = (R2- (xi + 1)2 ) - (yi - 1)2 Pi = d1 - d2 Tính Pi+1 - Pi ⇒ Pi+1 = Pi + 4xi + 6 + 2((yi+1)2 - (yi)2 ) - 2(yi+1 - yi) - Nếu Pi < 0 : chọn yi+1 = yi.
Khi đó Pi+1 = Pi + 4xi +6 - Nếu Pi >= 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + 4(xi - yi ) + 10. - P0 ứng với điểm ban đầu ( x0 , y0 ) = (0,R) là: P0= 3 - 2R. Minh họa thuật toán vẽ đường tròn bằng Bresenham Procedure DTR_BRES(xc,yc,r,mau : integer); var x,y,p:integer; begin x:=0 ; y:=r; p:= 3 – 2*r ; while ( x<y ) do begin doi_xung; if (p<0) then p:= p + 4*x + 6 else begin p:= p + 4*(x-y) + 10 ; y:=y-1; end; x:=x+1; end;{while} end; 1.
Thuật toán vẽ Ellipse Tương tự thuật toán vẽ đường tròn, sử dụng thuật toán Bresenham để vẽ, ta chỉ cần vẽ 1/4 ellipse, sau đó lấy đối xứng qua các trục tọa độ sẽ vẽ được toàn bộ ellipse. x2 y2 Xét ellipse có tâm O, các bán kính là a và b, phương trình là : + =1 a2 b2 Trang 22 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Chọn tọa độ pixel đầu tiên cần hiển thị là (xi ,yi) = (0,b). Cần xác định pixel tiếp theo là (xi+1 ,yi+1). Ta có : xi+1= xi + 1 yi+1= yi - 1 yi d1 = (yi)2 - y2 d2 = y2 - (yi - 1)2 Pi = d1 - d2 Tính Pi+1 - Pi 2b 2 ⇒ Pi+1 = Pi + 2((yi+1)2 - (yi)2 ) - 2(yi+1 - yi) + (2xi + 3) a2 2b 2 - Nếu Pi < 0 : chọn yi+1 = yi.
Khi đó Pi+1 = Pi + (2xi +3) a2 2b 2 - Nếu Pi >= 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + (2xi +3) +4(1- yi) a2 2b 2 - Pi ứng với điểm ban đầu ( x0 , y0 ) = (0,b) là: P0 = - 2b + 1 a2 Minh họa thuật toán vẽ Ellipse Procedure Ellipse(xc,yc,a,b : integer); var x,y : integer; z1, z2, P : real; procedure dx; begin putpixel (xc + x , yc +y, color) ; putpixel (xc - x , yc + y, color) ; putpixel (xc + x , yc - y, color) ; putpixel (xc - x , yc- y, color) ; end; begin x:=0 y:=b; Trang 23 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản z1:= (b*b)/(a*a); z2:= 1/ z1; P:= 2*z1 - 2*b +1; while (z1* (x/y) ≤ 1) do begin dx; if P < 0 then P:= P + 2*z1*(2*x+3) else begin P:= P + 2*z1*(2*x+3) + 4*(1-y); y:= y -1; end; x:= x+1; end; x:=a ; y:= 0; P:= 2*z2 - 2*a +1; while (z2* (y/x) < 1) do begin dx; if P < 0 then P:= P + 2*z2*(2*y+3) else begin P:= P + 2*z2*(2*y+3) + 4*(1-x); x:= x -1; end; y:= y +1; end; end; 1. Vẽ đường conics và một số đường cong khác Phương trình tổng quát của các đường conics có dạng : Ax2 + Bxy + Cy2 + Dx + Ey + F = 0 Trang 24 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Giá trị của các hằng số A, B, C, D, E, F sẽ quyết định dạng của đường conics, cụ thể là nếu: B2 - 4AC < 0 : dạng đường tròn (nếu A=C và B=0) hay ellipse. B2 - 4AC = 0 : dạng parabol.
B2 - 4AC > 0 : dạng hyperbol. Áp dụng ý tưởng của thuật toán Midpoint để vẽ các đường conics và một số đường cong khác theo các bước theo các bước tuần tự sau: - Bước 1: Dựa vào dáng điệu và phương trình đường cong, để xem thử có thể rút gọn phần đường cong cần vẽ hay không. - Bước 2: Tính đạo hàm, từ đó phân thành các vùng vẽ. Nếu f '(x) < -1 : yi+1 = yi + 1; xi+1 = xi (hoặc = xi +1) - Bước 3 : Tính Pi cho từng trường hợp để quyết định f '(x) dựa trên dấu của Pi.
Pi thường là hàm được xây dựng từ phương trình đường cong. Cho Pi=0 nếu (xi , yi) thuộc về đường cong. Việc chọn Pi cần chú ý sao cho các thao tác tínn Pi sau này hạn chế phép toán trên số thực. - Bước 4 : Tìm mối liên quan của Pi+1 và Pi bằng cách xét hiệu Pi+1 - Pi - Bước 5 : Tính P0 và hoàn chỉnh thuật toán.
Vẽ đa giác Đường gấp khúc hở Đường gấp khúc kín Hình 1.10 : Hai dạng của đường gấp khúc. Trang 25 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản • Định nghĩa đa giác (Polygone): Đa giác là một đường gấp khúc kín có đỉnh đầu và đỉnh cuối trùng nhau (xem hình 1.10) • Xây dựng cấu trúc dữ liệu để vẽ đa giác Type d_dinh = record x,y: longint; end; dinh = array[0.10] of d_dinh; var d: dinh; Với cách xây dựng cấu trúc dữ liệu như thế này thì chúng ta chỉ cần nhập vào tọa độ các đỉnh và sau đó gọi thủ tục vẽ đường thẳng lần lượt qua 2 đỉnh như (0, 1), (1,2), ., (n-1, n), trong đó đỉnh n trùng với đỉnh 0 thì ta sẽ vẽ được toàn bộ đa giác. • Đa giác được gọi là lồi nếu bất kỳ đường thẳng nào đi qua một cạnh của đa giác thì toàn bộ đa giác nằm về một phía của đường thẳng đó. Ngược lại, nếu tồn tại ít nhất một cạnh của đa giác chia đa giác làm 2 phần thì gọi là đa giác lõm (xem hình 1.11 : Đa giác lồi và đa giác lõm • Thuật toán kiểm tra một đa giác là lồi hay lõm Thuật toán 1: Lần lượt thiết lập phương trình đường thẳng đi qua các cạnh của đa giác.
Ứng với từng phương trình đường thẳng, xét xem các đỉnh còn lại có nằm về một Trang 26 Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản phía đối với đường thẳng đó hay không ? Nếu đúng thì kết luận đa giác lồi, ngược lại là đa giác lõm. Nhận xét : Phương trình đường thẳng y = ax + b chia mặt phẳng ra làm 2 phần. Các điểm nằm C(xc,yc) trên đường thẳng sẽ có yc > axc + b và các điểm D(xd,yd) nằm phía dưới đường thẳng sẽ có yd < axd + b. 1 Ví dụ : Cho đường thẳng AB có phương trình y = x + 1 và hai điểm C, D có tọa 2 độ là C(0,4), D(2,0) ( xem hình 1.12 : Đường thẳng AB và 2 điểm C, D.
1 Ta có : Yc = 4 > axc + b = .0 + 1 2 1 và Yd = 0 < axd + b = .2 + 1 2 Vậy hai điểm C, D nằm về hai phía đối với đường thẳng AB.