Giáo trình Lập trình nâng cao trên ngôn ngữ Pascal - Chương 6: Đồ họa
ðồhoạtrong Pascal không phải là công cụchuyên dùng ñểthiết kếhình ảnh. Tuy nhiên
nếu biết tận dụng các công cụsẵn có trong Unit Graph chúng ta có thểlàm ñược nhiều việc,
ñặc biệt là vẽ ñồthịcác hàm số. Trong chương này bạn ñọc tiếp cận các khái niệm sau:
Các thủtục vẽhình ñơn giản
Các thủtục viết chữtrong chế ñộ ñồhoạ
Các thủtục tô màu
Các phương pháp xửlý ảnh Bitmap
Phương pháp vẽ ñồthịhàm số
bước 1 Chú ý: khi vẽ hình chuyển ñộng cần phải tạo các các ñiểm dừng ñể khi không muốn chuyển ñộng có thể ngắt ngay chương trình. Dưới ñây là chương trình vẽ một bầu trời sao, số ngôi sao trên bầu trời là 100 trong ñó có 40 ngôi sao nhấp nháy, 20 ngôi sao nhấp nháy nhanh và 20 sao nhấp nháy chậm, các ngôi sao ñược phân bổ ngẫu nhiên. Trong chương trình còn thiết kế một ñĩa bay, ñĩa bay có 25 kích thước khác nhau, mỗi hình vẽ ñĩa bay ñược cất vào một biến con trỏ P, các biến con trỏ này nằm trong một mảng con trỏ. Các ñĩa bay xuất hiện ngẫu nhiên trên bầu trời, chuyển ñộng nhỏ dần và biến mất, sau ñó lại hiện lên tại một toạ ñộ nào ñó. Chương trình dừng lại khi bấm một phím bất kỳ. Với các máy tính có dung lượng bộ nhớ lớn (128 hoặc 256 Mb) chúng ta có thể tăng số hình ñĩa bay lên 50 hình khi ñó ñĩa bay sẽ chuyển ñộng mịn màng hơn. Ví dụ 6.9 Program Bautroi_diabay; Uses graph,crt; Var i,j,gd,gm:integer; a,x,y,xx,yy:word; p: array[1..30] of pointer; m,n :array[1..40] of word; Procedure bautroi(a:word); var i,j:word; m,n :array[1..40] of word; ch:char; Begin for j:= 1 to 5 do Begin for i:= 1 to a do begin Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 159 x:=random(639); y:=random(479); if i<=40 then (*chon 40 ngoi sao nhap nhay*) begin m[i]:=x; n[i]:=y; (*ghi toa do sao nhap nhay vao mang*) end; putpixel(x,y,random(15));(*hien sao *) end; end; end; Procedure nhapnhay; var i,j:word; k:byte; Begin for i:= 1 to 40 do (*chon 40 ngoi sao nhap nhay*) begin m[i]:=random(639); n[i]:=random(479); (*ghi toa do sao nhap nhay vao mang*) end; setcolor(random(15)); for j:=0 to 3 do For i:=1 to 20 do (*20 sao nhap nhay nhanh*) begin circle(m[i+j],n[i+j],1); delay(5); end; for j:=0 to 3 do For i:=21 to 40 do (*20 sao nhap nhay cham*) begin setcolor(random(4)); circle(m[i+j],n[i+j],1); delay(10); end; End; procedure vedia; Var xx,yy,x,y,x1,y1,x2,y2:integer; p: array[1..30] of pointer; r,i,r1,r2,r3,r4,r5:word; Begin setcolor(14);setbkcolor(0); i:=1; x:= 50; y:= 50; {diem dau tien dia bay xuat hien} Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 160 for r:= 25 downto 1 do {chọn 25 ñĩa với các kích thước giảm dần} Begin r1:=round(r/2); r2:=round(r/3); r3:=round(r/5); r4:=2*r2; r5:=round(r/10); Ellipse(x,y,0,360,r,r1); Ellipse(x,y-r3,194,346,r,r2); Line(x+r2,y-r2,x+r4,y-r4); circle(x+r4,y-r4,r5); line(x-r2,y-r2,x-r4,y-r4); circle(x-r4,y-r4,r5); x1:=x-r; y1:=y-r4-r5; x2:=x+r; y2:=y+r1; Getmem(p[i], imagesize(x1,y1,x2,y2));(*xac dinh kich thuoc anh*) getimage(x1,y1,x2,y2,p[i]^); (*cat anh vao bien con tro*) putimage(x1,y1,p[i]^,xorput); (*xoa anh*) i:=i+1; End; i:=1; While not keypressed do Begin (*hien dia bay voi cac kich thuoc khac nhau*) putimage(x,y,p[i]^,xorput); delay(100); xx:=x; yy:=y; x:=x+random(25); y:=y+random(25); putimage(xx,yy,p[i]^,xorput); (*xoa dia bay*) for j:= 1 to 40 do (*tao su nhap nhay cua ngoi sao*) begin setcolor(random(15)); circle(m[j],n[j],1); end; i:=i+1; if i>25 then {da hien het cac hinh dia bay} begin x:=random(500); Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 161 y:=random(400); i:=1; end; end; end; BEGIN {than chuong trinh chinh} gd:=detect; a:=100; {a la so ngoi sao tren bau troi} initgraph(gd,gm,'C:\tp\bgi'); if graphresultgrok then halt; bautroi(a); {hien bau troi sao} while not keypressed do begin nhapnhay; {thiet ke cac ngoi sao nhap nhay} vedia; {goi dia bay} end; closegraph; END. 7. ðồ thị hàm số Giả thiết hàm y = f(x) xác ñịnh và liên tục trên ñoạn [a,b], cần vẽ ñồ thị hàm trong một khu vực nào ñó trên màn hình. Hệ toạ ñộ quen thuộc mà chúng ta sử dụng là hệ xoy với gốc toạ ñộ nằm ở góc dưới bên trái, trục x hướng sang phải, trục y hướng lên trên. Màn hình máy vi tính tuỳ theo kích thước và chế ñộ làm việc có thể là ma trận ñiểm từ 640x480 ñến 1024x720. Gốc toạ ñộ của màn hình lại ở góc trên bên trái và trục x hướng theo chiều từ trên xuống dưới. ðể thuận tiện cho việc vẽ và quan sát ñồ thị chúng ta cần phải chuyển ñổi từ toạ thực (như trong toán học) sang toạ ñộ màn hình. Ký hiệu toạ ñộ thực của miền vẽ ñồ thị ñiểm góc dưới trái là xmin, ymin và góc trên phải là xmax, ymax. Toạ ñộ màn hình góc trên trái là cmin , dmin, góc dưới phải là cmax, dmax. Một ñiểm bất kỳ trên ñồ thị có toạ ñộ thực là x, y và toạ ñộ màn hình là c, d. Có thể chứng minh rằng: c = m*(x - xmin) + cmin d = n*(y - ymin) + dmin xmax, ymax xmin, ymin Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 162 Trong ñó: p = (cmax - cmin)/(xmax - xmin) q = (dmin - dmax)/(ymax- ymin) Hiệu số (dmin - dmax) mang dấu âm cho biết chiều biến thiên của trục thẳng ñứng giữa toạ ñộ màn hình và toạ ñộ thực là ngược nhau. Khi vẽ ñồ thị trên màn hình chúng ta sẽ dùng các công thức trên ñể chuyển ñổi toạ ñộ tính ñược từ thực tế sang toạ ñộ màn hình. Phương pháp vẽ ñồ thị là xác ñịnh toạ ñộ từng ñiểm sau ñó nối các ñiểm với nhau bằng các ñoạn thẳng. ðể ñồ thị trơn tru thì số ñiểm phải thật nhiều, tuy nhiên chúng ta không thể tăng vô hạn số ñiểm. Giả sử chia ñoạn [a,b] thành n ñoạn nhỏ, chúng ta sẽ có n+1 ñiểm ñánh số từ 0 ñến n. Khi ñó chiều rộng mỗi ñoạn sẽ là h = (b - a)/n. Hoành ñộ của một ñiểm bất kỳ trong toạ ñộ thực: xi = a + h*i, và tung ñộ tương ứng sẽ là f(xi). ðiều cần chú ý khi chọn các toạ ñộ thực và toạ ñộ màn hình là miền trên màn hình phải bao kín miền toạ ñộ thực. Muốn vậy chúng ta chọn: xmin = a, xmax = b, ymin = min(yi), ymax = max(yi). Việc khảo sát hàm số f(x) ñể tìm max và min theo kiểu toán học là không thực tế trong Pascal, do vậy có thể thay thế việc tìm min(yi) và max(yi) bằng việc lưu các giá trị f(xi) vào một mảng, sau ñó tìm cực trị trong mảng. ðể chương trình có thể ứng dụng cho tất cả các hàm số chúng ta sẽ xây dựng một chương trình con lấy tên là HAM khai báo hàm và tính giá trị của hàm tại các toạ ñộ xi. Một chương trình con lấy tên là TOADO ñể tính các hệ số m, n, và tung ñộ các ñiểm chia (tức là giá trị của hàm f(x) tại các toạ ñộ xi). Ví dụ 6.10 Program vedothi; Uses graph; Const n=200; cmin=3; dmin=3;cmax=200; dmax=140;{ve o goc phan tu thu nhat} xmin=-5; xmax=5; Var gd,gm:integer; ymin,ymax,h,m,p,q:real; y:Array[0..n] of real; Function F(x:real) : real; Begin {f:=x*x;} F:=x*x*x-2*x; End; Procedure Toado; Var i:integer; xi,yi:real; Begin h:=(xmax-xmin)/n; For i:= 0 to n do Begin Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 163 xi:=xmin+i*h; yi:=f(xi); y[i]:=f(xi); End; ymin:=y[0]; ymax:=-ymin; For i:=1 to n do Begin If ymin>y[i] then ymin:=y[i]; If ymax<y[i] then ymax:=y[i]; End; p:= (cmax-cmin)/(xmax-xmin); q:= (dmin-dmax)/(ymax-ymin); End; Procedure Ve; Var i,c,d:integer; xi:real; Begin c:=cmin; d:= round(q*(y[0]-ymin)+dmax); Moveto(c,d); For i:=1 to n do Begin xi:=xmin+i*h; c:=Round(p*(xi-xmin)+cmin); d:=Round(q*(y[i]-ymin)+dmax); setcolor(red); Lineto(c,d) {noi cac diem do thi} End; setcolor(14); moveto(cmin,dmin); Lineto(cmax,dmin);{ve khung do thi} moveto(cmax,dmin); Lineto(cmax,dmax); moveto(cmax,dmax); Lineto(cmin,dmax); moveto(cmin,dmax); Lineto(cmin,dmin); d:=Round(q*(-ymin)+dmax); if (d>=dmin) and (d<=dmax) then Begin line(cmin,d,cmax,d);{truc hoanh} line(cmax,d,cmax-6,d-3); {dau mui ten} line(cmax,d,cmax-6,d+3); end; c:=Round(p*(-xmin)+cmin); if (c>=cmin) and (c<=cmax) then begin Line(c,dmin,c,dmax); {truc tung} Line(c,dmin,c-3,dmin+6); {dau mui ten} Line(c,dmin,c+3,dmin+6); end; End; Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 164 BEGIN gd:=detect; Initgraph(gd,gm,'c:\tp70\bgi'); if graphresultgrok then halt; toado; ve; readln; closegraph; END. Với các hàm số cho theo tham số x = x(t), y = y(t), hoặc cho trong toạ ñộ cực r = f(ϕ) phương pháp vẽ cũng tương tự, chúng tôi xin dành cho bạn ñọc như là những bài tập ứng dụng. Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 165 Bài tập ứng dụng chương 6 1. Nhập và cho chạy thử chương trình trong ví dụ 6.9 sau ñó thiết kế thêm một tên lửa. Cho tên lửa phóng từ góc dưới bên phải màn hình lên góc trên bên trái. Luồng khói phía ñuôi dài bằng 3 lần chiều dài tên lửa. 2. Cho các ký tự của dòng chữ "Happy Birth Day" hiện ngẫu nhiên và nhấp nháy trên màn hình, tiếp ñó cho chúng chuyển ñộng ñan xen và thu dần về tâm (320,240). Cuối cùng các ký tự lại từ tâm chạy ra trên một quỹ ñạo tròn và ñã sắp xếp thành dòng chữ hoàn chỉnh. 3. Chọn kích thước và thiết kế các hình ñơn giản 1, 2, 3, 4 (xem hình vẽ), mỗi hình cất vào một biến con trỏ. Cho hiện các hình tại các vị trí tuỳ ý sao cho hình vừa chuyển ñộng vừa tự quay, cuối cùng các hình tự ghép với nhau thành một hình vuông ở giữa màn hình 4. Lập chương trình vè ñồ thị hàm số cho dưới dạng tham số x = x(t), y =y(t) 5. Lập chương trình vè ñồ thị hàm số cho dưới dạng toạ ñộ cực r = f(ϕ) 6. Cho hàm y = f(x) xác ñịnh và liên tục trong khoảng (a,b). Lập chương trình nhập dạng một hàm cụ thể. Vẽ ñồ thị hàm sau ñó tính tích phân xác ñịnh ∫ b a dxxf )(
File đính kèm:
- Giáo trình Lập trình nâng cao trên ngôn ngữ Pascal - Chương 6_Đồ họa.pdf