Bài tập lớn và báo cáo môn học Đồ họa máy tính Đề tài báo cáo: Đồ họa máy tính 1. Vẽ sao năm cánh quay quanh tâm, dùng phím mũi tên di chuyển sao đi khắp màn hình. 2. Vẽ ôtô chạy qua lại trên đường nằm ngang. Vẽ sao năm cánh quay quanh tâm, dùng phím mũi tên di chuyển sao đi khắp màn hình: Vẽ hình ông sao:( Gắn vào hệ toạ độ xO1y) Toạ độ tâm là O1(xc,yc) ; Khoảng cách từ tâm đến đỉnh là r ; Xác định tọa độ các đỉnh: + Chọn A(x,y) với x=xc+r, y=yc. + Toạ độ đỉnh A1 (xo,yo).Ta chọn xo=xcr, yo=yc bằng phép quay điểm A quanh tâm O1theo hướng + một góc = (=3.14). + Theo đặc điểm của ông sao ta có thể xác định các đỉnh còn lại bằng cách sau: Ý tưởng Vẽ ôtô: Như hình vẽ thì ta thấy ôtô được tạo bởi 3 hình chữ nhật và hai hình tròn Ta có thể vẽ được hình chữ nhật khi biết toạ độ của hai đỉnh đối nhau và vẽ được hình tròn khi biết tâm và bán kính. Khi đó ta có ý tưởng vẽ ôtô như sau: Chọn đỉnh O1 đầu tiên từ đó ta xác định toạ độ các điểm A,B,C,E,G,N từ O1. Ta vẽ hình chữ nhật ADCB từ hai đỉnh A và C, hình chữ nhật EFHB từ hai đỉnh E và B, hình chữ nhật CGMN từ hai đỉnh G và N, Đường tròn tâm B từ đỉnh B, đường tròn tâm C từ đỉnh C.
Trang 1Bμi tập lớn môn đồ hoạ máy tính
vẽ hình chuyển động
Nhóm thực hiện:
Đinh Văn Phong
Phạm Đình Thanh
Nguyễn Đình Thọ
Nguyễn Như Vũ
Trần Thị Trang
Đỗ Thị Thanh Vân
Giáo viên hướng dẫn:
Nguyễn Văn Trường
Tên đề tμi
Đề 2:
I Vẽ sao năm cánh quay quanh tâm, dùng phím mũi tên di chuyển sao đi khắp màn hình
II Vẽ ôtô chạy qua lại trên đường nằm ngang
Trang 2I Vẽ sao năm cánh quay quanh tâm, dùng phím mũi tên di chuyển sao
đi khắp màn hình
I.1 ý tưởng:
O
x
y
a Mô tả hình sao 5 cánh:
- Hình sao 5 cánh có dạnh như hình bên:
- Một ngôi sao 5 cánh có đặc điểm :
• Năm đỉnh cách đều tâm O một khoảng r
(OA1=OA2=OA3=OA4=OA5=r)
=> Các đỉnh A1,A2, ,A5 nằm trên đường tròn tâm O bán kính r
• Hai đỉnh kề nhau tạo với nhau một góc 720
(góc A1OA2=góc A2OA3=góc A3OA4=góc A4OA5=góc A5OA1=720)
b ý tưởng vẽ hình sao (trong Mode 19)
* Hệ toạ độ trong mode 19:
Với: O(0,0) ;
Ox có số điểm ảnh tối đa là 200
pixel ;
Oy có số điểm ảnh tối đa là 320
pixel ;
Trang 3* Vẽ hình ông sao:( Gắn vào hệ toạ độ xO 1 y)
- Toạ độ tâm là O1(xc,yc) ;
- Khoảng cách từ tâm đến đỉnh là r ;
- Xác định tọa độ các đỉnh:
+ Chọn A(x,y) với x=xc+r, y=yc
+ Toạ độ đỉnh A1 (xo,yo).Ta chọn xo=xc-r, yo=yc bằng phép quay điểm
A quanh tâm O1theo hướng + một góc α=Π(=3.14)
+ Theo đặc điểm của ông sao ta có thể xác định các đỉnh còn lại bằng cách sau:
Quay A quanh tâm O1 theo
hướng + một góc
180
*
72 Π +
góc A2
Quay A quanh tâm O1 theo
hướng + một góc
180
* 2
*
+
Quay A quanh tâm O1 theo
hướng + một góc
180
* 3
*
+
góc A4
Quay A quanh tâm O1 theo
hướng + một góc
180
* 4
*
+
góc A5
Khi xác định được các đỉnh ta bắt đầu nối các đỉnh với nhau thành hình ông
sao (A1 với A3, A4), (A2 với A4, A5), (A3 với A5)
Kết quả ta được hình cần tìm:
Trang 4c Di chuyển hình sao:
* Sao quay quanh tâm:
Thực hiện phép quay hình sao quanh gốc O1 với góc a= Thực hiện
360 lần quay hình sao ban đầu theo chiều dương (âm) thì quay hình sao được một vòng quanh gốc O
180 / )
* 1 ( Π
1 Mỗi lần quay thực hiện theo nguyên tắc:
• Góc quay tỉ lệ thuận với số lần quay (lần 1: a= , lần 2:
, , lần 360:
180 / )
* 1 ( Π 180
/ )
*
2
( Π ( 360 * Π ) / 180)
• Vẽ hình sao với màu c, sau đó trễ thời gian t, rồi vẽ hình sao với màu trùng với màu nền
* Sao di chuyển ( dùng phím mũi tên để di chuyển):
Ta lập trình trong TC 3 vì vậy dùng hàm kbhit () để xác định một phím khi
nào được ấn Chú ý các phím mũi tên có mã phím là: Phải:77, Trái:75, Xuống:80, Lên:72 Quá trình di chuyển được thực hiện như sau:
- Khi thực hiện di chuyển lên trên ta thực hiện phép tịnh tiến hình sao theo vectơ i có toạ độ (-1,0);
- Khi thực hiện di chuyển xuống trên ta thực hiện phép tịnh tiến hình sao theo vectơ i có toạ độ (1,0);
- Khi thực hiện di chuyển sang trái trên ta thực hiện phép tịnh tiến hình sao theo vectơ i có toạ độ (0,-1);
- Khi thực hiện di chuyển sang phải trên ta thực hiện phép tịnh tiến hình sao theo vectơ i có toạ độ (0,1);
I.2 Thuật giải:
* Vẽ hình sao:
Vẽ hình sao với tâm có toạ độ là (xc,yc), khoảng cách từ tâm đến đỉnh là r, màu c Đỉnh A1(xo,yo) với xo, yo và tạo với trục Ox góc afa, các đỉnh A2 A5 có toạ độ được lưu trữ với hai mảng một chiều Cụ thể: A2(a[1],b[1]), A3(a[2],b[2]), A4(a[3],b[3]), A5(a[4],b[4])
Trang 5void ve_hinhsao(int afa, int xo, int yo,int xc,int yc,int r,int c)
{
double i; int a[5], b[5];
for (i=1;i<5;i+=1)
{
a[i]=ceil(r*cos(afa+(72*3.14*i)/180))+xc;
b[i]=ceil(r*sin(afa+(72*3.14*i)/180))+yc;
}
dt(xo,yo,a[2],b[2],c); // Nối A1 với A3
dt(xo,yo,a[3],b[3],c); // Nối A1 với A4
dt(a[1],b[1],a[3],b[3],c); // Nối A2 với A4
dt(a[1],b[1],a[4],b[4],c); // Nối A2 với A5
dt(a[2],b[2],a[4],b[4],c); // Nối A3 với A5
}
*Sao vừa quay quanh tâm vừa di chuyển:
Vẽ sao quanh tâm một vòng theo chiều dương Vị trí ban đầu của hình sao có tâm (xc,yc), khoảng cách từ tâm đến đỉnh là r, đỉnh A1(xo,yo) tạo với Ox góc a void sao_dichuyen(double a,int xo,int yo,int xc,int yc,int r,int c)
{
ve_hinhsao(a,xo,yo,xc,yc,r,c);
delay(50); // trễ một khoảng thời gian
ve_hinhsao(a,xo,yo,xc,yc,r,0);
char c1;
int i=0;
while (i<=360)
{
xo=ceil(r*cos(a+i*3.14/180))+xc;
yo=ceil(r*sin(a+i*3.14/180))+yc;
ve_hinhsao(a+i*3.14/180,xo,yo,xc,yc,r,c);
delay(50); // trễ một khoảng thời gian ve_hinhsao(a+i*3.14/180,xo,yo,xc,yc,r,0);
if (kbhit()) // Di chuyển hình sao dùng 4 phím mũi tên
{
{
c1 = getch();
if (c1==77) yc++;
else if (c1==75) yc ;
else if (c1==80) xc++;
Trang 6else if (c1==72) xc ;
} else
break;
}
}
}
I 3: Chương trình:
/* Chương trình dùng 4 phím mũi tên để di chuyển sao, phím cách để đổi chiều quay phím ESC để thoát khỏi chương trình */
#include<dos.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>
void mode(int m)
{
union REGS r;
r.h.ah=0;
r.h.al=m;
int86(16,&r,&r);
}
void point(int x, int y,int c)
{
if ((x>=0)&&(x<200)&&(y>=0)&&(y<320))
*((char far*) 0xA0000000 + 320*x+y)=c;
}
int readpoint(int x, int y)
{
if ((x>=0)&&(x<200)&&(y>=0)&&(y<320))
return *((char far*) 0xA0000000 + 320*x+y);
}
void loang(int x,int y, int c, int c1)
{
if (readpoint(x,y)==c)
{
point(x,y,c1);
Trang 7loang(x+1,y,c,c1);
loang(x,y+1,c,c1);
loang(x-1,y,c,c1);
loang(x,y-1,c,c1);
}
}
void maunen()
{
for (int i=1;i<=200;i++)
for (int j=1;j<=320;j++)
point(i,j,39);
}
void dt(int x1, int y1, int x2, int y2, int color) {
int d, ax, ay, sx, sy, dx, dy;
dx = x2-x1;
ax = abs(dx) << 1;
if (dx < 0) sx = -1; else sx = 1;
dy = y2-y1;
ay = abs(dy) << 1;
if (dy < 0) sy = -1; else sy = 1;
point(x1, y1, color);
if (ax > ay)
{
d = ay-(ax >> 1);
while (x1 != x2)
if (d >= 0)
{
y1 = y1 + sy;
d = d - ax;
}
x1 = x1 + sx;
d = d + ay;
point(x1, y1, color);
} //while
}
else
{
d = ax-(ay >> 1);
Trang 8while (y1 != y2)
if (d >= 0)
{
x1 = x1 + sx;
d = d - ay;
}
y1 = y1 + sy;
d = d + ax;
point(x1, y1, color);
} //while
} //if
} //end drawLine
void ve_hinhsao(double afa,int xo,int yo,int xc,int yc,int r,int c) {
int a[5],b[5],h[5],k[5];
double i;
h[5]=ceil((2*r/3)*cos(afa))+xc;
k[5]=ceil((2*r/3)*sin(afa))+yc;
for (i=1;i<5;i+=1)
{
a[i]=ceil(r*cos(afa+(72*M_PI*i)/180))+xc;
h[i]=ceil((2*r/3)*cos(afa+(72*M_PI*i)/180))+xc;
b[i]=ceil(r*sin(afa+(72*M_PI*i)/180))+yc;
k[i]=ceil((2*r/3)*sin(afa+(72*M_PI*i)/180))+yc;
}
dt(xo,yo,a[2],b[2],c);
dt(xo,yo,a[3],b[3],c);
dt(a[1],b[1],a[3],b[3],c);
dt(a[2],b[2],a[4],b[4],c);
dt(a[1],b[1],a[4],b[4],c);
loang(xc,yc,39,c);
for (i=1;i<=5;i+=1)
loang(h[i],k[i],39,c);
}
void sao_dc(double a,int xo,int yo,int xc,int yc,int r,int c)
{
ve_hinhsao(a,xo,yo,xc,yc,r,c);
delay(50);
ve_hinhsao(a,xo,yo,xc,yc,r,0);
Trang 9char c1;
int i=0;int t=1;
while (1)
{
if (i==360) i=0;
else i+=t;
maunen();
xo=ceil(r*cos(a+i*M_PI/180))+xc;
yo=ceil(r*sin(a+i*M_PI/180))+yc;
ve_hinhsao(a+i*M_PI/180,xo,yo,xc,yc,r,c); delay(50);
ve_hinhsao(a+i*M_PI/180,xo,yo,xc,yc,r,0);
if (kbhit())
{
{
c1 = getch();
if (c1==77) {if(yc<320-r) yc++;} else if (c1==75) {if(yc>r) yc ;} else if (c1==80) {if(xc<200-r) xc++;} else if (c1==72) {if(xc>r) xc ;} else if (c1==32) t=-t;
}
else
break;
}
}
}
void main()
{
int lc,xo,yo,xc,yc,c,r;
xc=100;yc=160;c=43;r=50;
xo=xc-r;yo=yc;
mode(19);
double a=M_PI;
sao_dc(a,xo,yo,xc,yc,r,c);
getch();
mode(3);
}
Trang 10KÕt qu¶ ch−¬ng tr×nh:
Trang 11II Vẽ ôtô chạy qua lại trên đường nằm ngang
Hình vẽ minh họa:
II.1 ý tưởng
a Vẽ ôtô:
Như hình vẽ thì ta thấy ôtô được tạo bởi 3 hình chữ nhật và hai hình tròn
O1
E
N
B
Ta có thể vẽ được hình chữ nhật khi biết toạ độ của hai đỉnh đối nhau và vẽ được hình tròn khi biết tâm và bán kính Khi đó ta có ý tưởng vẽ ôtô như sau:
Chọn đỉnh O1 đầu tiên từ đó ta xác định toạ độ các điểm A,B,C,E,G,N từ O1 Ta
vẽ hình chữ nhật ADCB từ hai đỉnh A và C, hình chữ nhật EFHB từ hai đỉnh E và
B, hình chữ nhật CGMN từ hai đỉnh G và N, Đường tròn tâm B từ đỉnh B, đường tròn tâm C từ đỉnh C
b Di chuyển ôtô:
Di chuyển sang trái theo vectơ có toạ độ (0,-1);
Di chuyển sang phải theo vectơ có toạ độ (0,1);
Trang 12II.2 Giải thuật
Vẽ ôtô có màu là c ở vị trí mà toạ độ điểm giữa ôtô là (xc,yc)
void ve_oto(int xc, int yc, int c)
{
ve_hcn(xc-10,yc-30,xc+10,yc+30,c);
ve_hcn(xc-3,yc-50,xc+10,yc-30,c);
ve_hcn(xc-3,yc+30,xc+10,yc+50,c);
ve_dtr(xc+10,yc-30,c);
ve_dtr(xc+10,yc+30,c);
}
II.3 Chương trình
/* Chương trình dùng phím cách để đổi hướng đi của ôtô, phím ESC để thoát khỏi chương trình*/
#include<dos.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>
#include<iostream.h>
void mode(int m)
{
union REGS r;
r.h.ah=0;
r.h.al=m;
int86(16,&r,&r);
}
void point(int x, int y,int c)
{
if ((x>=0)&&(x<200)&&(y>=0)&&(y<320))
*((char far*) 0xA0000000 + 320*x+y)=c;
}
void ve_hcn(int x1,int y1,int x2,int y2,int c)
{
int i;
for (i=y1;i<=y2;i++)
point(x1,i,c);
if (x1==x2) return;
Trang 13for (i=y1;i<=y2;i++)
point(x2,i,c);
for (i=x1+1;i<x2;i++)
point(i,y1,c);
if (y2==y1) return;
for (i=x1+1;i<x2;i++)
point(i,y2,c);
}
void tomau_hcn(int x1,int y1,int x2,int y2,int c) {
int i,j;
for(i=x1;i<=x2;i++)
for(j=y1;j<=y2;j++)
point(i,j,c);
}
void ve_dtr(int xc,int yc,int r, int c)
{
int x,y;
x=xc+r;y=yc;
for (int i=0;i<=360;i++)
{
x=ceil(r*cos(i*3.14/180))+xc;
y=ceil(r*sin(i*3.14/180))+yc;
point(x,y,c);
}
}
void ve_oto(int xc, int yc, int c, int b)
{
ve_hcn(xc-10,yc-30,xc+10,yc+30,c);
tomau_hcn(xc-10,yc-30,xc+10,yc+30,c);
ve_hcn(xc-3,yc-50,xc+10,yc-30,c);
tomau_hcn(xc-3,yc-50,xc+10,yc-30,c);
ve_hcn(xc-3,yc+30,xc+10,yc+50,c);
tomau_hcn(xc-3,yc+30,xc+10,yc+50,c);
for(int i=1; i<=7;i++) ve_dtr(xc+10,yc-30,i,b); for(i=1; i<=7;i++) ve_dtr(xc+10,yc+30,i,b); }
Trang 14void main()
{
int t=0;
mode(19);
for(int i=1;i<=350;i++)
{
t=t+10;
point(100,i,255);
point(99,i,255);
}
int h=1;
i=0;
char c1;
while (1)
{
i=i+h;
if (i==375||i==-55) h=-h;
ve_oto(80,i,12,21);
delay(50);
ve_oto(80,i,0,0);
if (kbhit())
{
if (c1!=27)
{
c1=getch();
if (c1==32) h=-h;
}
else break;
}
}
getch();
mode(3);
}
Trang 15* Chương trinh ứng dụng: (Chương trình cải tiến của đề tài vẽ ôtô)
/* Mô tả: Khi ôtô đến vị trí của khách sẽ dừng lại đợi khách lên xe rồi đi tiếp Khi đi hết đường thì một xe khác sẽ quay về bến và trả khách.*/
#include<dos.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>
#include<iostream.h>
void mode(int m)
{
union REGS r;
r.h.ah=0;
r.h.al=m;
int86(16,&r,&r);
}
void point(int x, int y,int c)
{
if ((x>=0)&&(x<200)&&(y>=0)&&(y<320))
*((char far*) 0xA0000000 + 320*x+y)=c;
}
void ve_hcn(int x1,int y1,int x2,int y2,int c)
{
int i;
for (i=y1;i<=y2;i++)
point(x1,i,c);
if (x1==x2) return;
for (i=y1;i<=y2;i++)
point(x2,i,c);
for (i=x1+1;i<x2;i++)
point(i,y1,c);
if (y2==y1) return;
for (i=x1+1;i<x2;i++)
point(i,y2,c);
}
void tomau_hcn(int x1,int y1,int x2,int y2,int c)
{
int i,j;
for(i=x1;i<=x2;i++)
for(j=y1;j<=y2;j++)
point(i,j,c);
}
Trang 16void dt1(int x1, int y1, int x2, int y2, int color) {
int d, ax, ay, sx, sy, dx, dy;
dx = x2-x1;
ax = abs(dx) << 1;
if (dx < 0) sx = -1; else sx = 1;
dy = y2-y1;
ay = abs(dy) << 1;
if (dy < 0) sy = -1; else sy = 1;
point(x1, y1, color);
if (ax > ay) {
d = ay-(ax >> 1);
while (x1 != x2) {
if (d >= 0) {
y1 = y1 + sy;
d = d - ax;
}
x1 = x1 + sx;
d = d + ay;
point(x1, y1, color);
} //while
} else {
d = ax-(ay >> 1);
while (y1 != y2) {
if (d >= 0) {
x1 = x1 + sx;
d = d - ay;
}
y1 = y1 + sy;
d = d + ax;
point(x1, y1, color);
} //while
} //if
} //end drawLine
void ve_dtr(int xc,int yc,int r, int c)
{
int x,y;
x=xc+r;y=yc;
for (int i=0;i<=360;i++)
Trang 17{
x=ceil(r*cos(i*3.14/180))+xc;
y=ceil(r*sin(i*3.14/180))+yc;
point(x,y,c);
}
}
void ve_oto(int xc, int yc, int c, int b)
{
ve_hcn(xc-10,yc-30,xc+10,yc+30,c);
tomau_hcn(xc-10,yc-30,xc+10,yc+30,c);
ve_hcn(xc-3,yc-50,xc+10,yc-30,c);
tomau_hcn(xc-3,yc-50,xc+10,yc-30,c);
ve_hcn(xc-3,yc+30,xc+10,yc+50,c);
tomau_hcn(xc-3,yc+30,xc+10,yc+50,c);
for(int i=1; i<=7;i++) ve_dtr(xc+10,yc-30,i,b); for(i=1; i<=7;i++) ve_dtr(xc+10,yc+30,i,b); }
void nguoi(int x1, int y1,int cc, int c)
{
ve_dtr(x1,y1,4,c);
for(int i=1; i<=cc;i++)
point(x1+3+i,y1,c);
dt1(x1+3+i,y1,x1+12+i,y1-6,c);
dt1(x1+3+i,y1,x1+12+i,y1+6,c);
int k=y1-10;
for(int j=1;j<=20;j++)
{
point(x1+10,k,c);
k++;
}
}
void benxe()
{
ve_hcn(20,150,50,250,11);
ve_hcn(21,151,49,249,11);
ve_hcn(22,152,48,248,11);
ve_hcn(23,153,47,247,11);
for(int i=50;i<=98;i++)
{
point(i,155,7);
point(i,154,7);
point(i,245,7);
point(i,244,7);
}
Trang 18}
/*void cay(int x,int y,int cc,int cr,int c) {
dt1(x,y-cr,x-cc,y-cr/2,c);
dt1(x,y+cr,x-cc,y+cr/2,c);
for(int i=1; i<=20;i++) ve_dtr(x-cc-7,y,i,c); } */
void cay(int x,int y,int cc,int cr,int c)
{
for(int i=y-cr;i<=y+cr;i++)
dt1(x,i,x-cc,i,8);
for( i=1; i<=20;i++) ve_dtr(x-cc-21,y,i,c); }
void main()
{
int t=0,k=2,m=2;
mode(19);
for(int i=1;i<=350;i++)
{
t=t+10;
point(100,i,255);
point(99,i,255);
}
benxe();
cout<<"\n\n\n\n BUS STOP"; nguoi(65,200,20,k);
cay(98,100,50,2,2);
cay(98,290,70,2,2);
cay(98,20,30,5,2);
int h=1;
i=0;
k=m;
int c=4;
char c1;
while (1)
{
benxe();
cay(98,100,50,2,2);
cay(98,290,70,2,2);
cay(98,20,30,5,2);
nguoi(65,200,20,k);
i=i+h;
if (i==375||i==-55)
{
Trang 19h=-h;
c++;
}
ve_oto(80,i,c,8);
if (i==200)
{ delay(1000);
m=-m;
k=k+m;
}
delay(50);
ve_oto(80,i,0,0);
if (kbhit())
{ if (c1!=27)
{
c1=getch();
if (c1==32) h=-h;
}
else break;
}
}
getch();
mode(3);
}