Với thuật toán tô màu theo dòng quét Scanline, khi tô màu cho một vùng kín đôi khi cần phải xác định cho được các trường hợp đặc biệt của bài toán để sao cho kết quả trả về sẽ tô được nh
Trang 1TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
- -BÀI TẬP LỚN
ĐỒ HỌA MÁY TÍNH
Giảng viên hướng dẫn: Nguyễn Thị Cẩm Ngoan Nhóm thực hiện: Nhóm 17
Nguyễn Đức Đạt
Bùi Hoàng Nam Nguyễn Bá Trình
Hà Nội, tháng 2 năm 2013
Trang 2Thuật toán Scanline
Trong đồ họa máy tính có khá nhiều thuật toàn tô màu (Scanline, tô loang ) cho 1 vùng kín (đặc) như các đa giác, các đường tròn Xong mỗi thuật toán lại tỏ ra có những ưu việt và hạn chế riêng đối với từng bài toán cụ thể Với thuật toán tô màu theo dòng quét (Scanline), khi tô màu cho một vùng kín đôi khi cần phải xác định cho được các trường hợp đặc biệt của bài toán để sao cho kết quả trả về sẽ tô được những vùng cần thiết như mong muốn.
Song, trong thực tiễn để làm được điều này nhiều lúc cũng gặp phải khá nhiều khó khăn trong việc xử lý các trường hợp đặc biệt đó.Bài viết này nhằm xác định các trường hợp đặc biệt của bài toán tô màu đa giác cũng như cách xử lý chúng để cho kết quả tô chính xác bằng thuật toán Scanline
I Ý Tưởng
-Duyệt qua tất cả các đỉnh của đa giác để xác định XMAX,XMIN.
-Xác định các giao điểmcủa từng dòng quét với tất cả các cạnh của đa giác ( đường viền đa giác ) trong phạm vi XMAX, XMIN đó
-Bật sáng các Pixel bên trong đa giác bằng cách kiểm tra xem chúng có nằm trong đa giác hay không
II Phân tích
1 Hình minh họa các trường hợp đặc biệt
Trang 32 Các trường hợp đặc biệt.
Ta cần xây dựng các thủ tục (TT) mà mỗi TT đó phải xử lý được một trường hợp đặc biệt của bài toán
TH1: Dòng quét L1cắt đa giác một lần ,tạiđỉnhthấpnhấtcủa đa giác .Taphải xây dựng mộtTT bỏ qua dòng L1 ( còn đỉnh của đa giácnày tất nhiên
sẽ được sáng cùng với đường viền của nó)
TH2: DòngL2cắtđa giáctại 2điểm ( trong đó có1 đỉnh) Mọi Pixel nằm giữa B1, B2 sẽ được sáng lên ; giao điểm với đỉnh nàykhông được bỏ qua Do
đó phải xây dựng mộtTT có khả năng xác định được khi nào 1 giao điểm với đỉnh có thể hoặc không thể bỏ qua
TH3: Dòng L3 cắt đa giáctại 3 điểm ; mọi Pixelgiữa C1 và C2 sẽ sáng lên nênTT sẽ bỏ qua điểm C’
TH4: DòngL4trùngvớicạnhnằm ngang S Mọi pixel giữa D1,D2 sẽ sáng lên Phải xây dựng mộtTTcoi cạnh S là không tồn tại ( không bật sáng các Pixel nằm trên S) Đồng thời các pixel giữa D2 và D3 sẽ không sáng lên và các Pixel giữa D3, D4 lại được sáng lên
3 Xét tính tương đối của 1 điểm với 1 đa giác bất kỳ
a. Thuật toán
Để xét tính tương đối của 1 điểm (x, y) với 1 đa giác bất kỳ, ta tính số giao điểm của của tia yT (song song với 0x theo chiều dương) với đa giác
Nếu số giao điểm là chẵn thì (x, y) nằm ngoài đa giác điểm này sẽ được giữ nguyên, ngược lại nếu số giao điểm là lẻ thì (x, y) nằm trong đa giác, điểm này
sẽ được bật sang
b. Kiểm tra tính chất các giao điểm
Trang 4Để kiểm tra tính chất của một đường quét có cắt 1 cạnh không? Ta thực hiện việc so sánh tung độ của dòng quét (yscan) với tung độ y của các điểm mút của mỗi cạnh
i. Nếu tung độ của 2 điểm mút đều lớn hơn hay nhỏ hơn YSCAN thì không cógiao điểm nào
ii. Nếu tung độ y của mỗi điểm mút bằng YSCAN thì giao điểm tại đỉnh đó
iii Nếu tung độ của cả 2 điểm mút đều bằng YSCAN thì đó là cạnh nằm ngang.
iv Cuối cùng , nếu 1 tung độ bé hơn YSCANcòn tung độ kia lớn hơn
YSCANthì dòng quét cắt cạnh đó.
4 Xử lý các trường hợp đặc biệt
Trang 5a. Nếu cạnh bị cắt là nằm ngang thì tồn tại 2 giao điểm của yT với cạnh này
b. Nếu giao điểmtrùng với 1 đỉnh thì kiểm tra các tung độ ngay trước và ngay sau đỉnh đó Nếu cả 2 tung độ đều lớn hơn/nhỏ hơn yT thì tồn tại 2 giao điểm với đỉnh này
c Trường hợp còn lại được tính là tồn tại 1 giao điểm
d Nếu trường hợp dòng quét cắt 1 cạnh thì ta phải xác định tọađộ giao điểm( xgd =?, yT)
Nếu x>xgd thì không tồn tại giao điểm, ngược lại yT cắt cạnh tại 1 giao điểm.
III.Chương trình
1 Hàm vẽ hệ trục tọa độ
void truc()
Trang 6{ setcolor(14);
//0y
line(320,0,320,480);
moveto(318,2);lineto(320,0);lineto(322,2);
outtextxy(300,10,"y");
//0x
line(0,240,640,240);
moveto(638,238);lineto(640,240);lineto(638,242); outtextxy(620,250,"x");
//0
outtextxy(307,245,"O");
//chiakhoang
int i;
i=320-6*tile;
while(i<320+6*tile)
{line(i,238,i,242);
i+=tile;}
int j;
j=240-6*tile;
while(j<240+6*tile)
{line(318,j,322,j);
j+=tile;}
}
Trang 7Kết quả của hàm:
2 Tính giá trị lớn nhất và nhỏ nhất của tung độ và hoành độ //min, max x
for (i=2;i<=n;i++)if (max<x[i]) max=x[i];
mx=x[1];
for (i=2;i<=n;i++)if (x[i]<mx) mx=x[i];
//min, max y
my=y[1];
for (i=2;i<=n;i++)
Trang 8{if (my>y[i]) my=y[i];
if (may<y[i]) may=y[i];
}
3 Hàm kiểm tra tính tương đối của điểm với đa giác
Hàm trả về kết quả là true nếu điểm đó nằm trong đa giác và false nếu điểm đó nằm ngoài đa giác
bool namtrong(int a, int b)
{int dem=0;
for (int i=1;i<n+1;i++)
if ((b==y[i]) &&(a<=x[i]))
{if (((y[i-1]<b)&&(y[i+1]>b))||((y[i-1]>b)&&(y[i+1]<b))) dem=dem+1;
else
{if (((y[i-1]<b)&&(y[i+1]<b))||((y[i-1]>b)&&(y[i+1]>b))) dem=dem+2;} }
else
if ((min2so(y[i],y[i+1])<b)&&(max2so(y[i],y[i+1])>b))
{ if (x[i]==x[i+1])
{if (a<=x[i]) {dem=dem+1;}
}
else
if (y[i]==y[i+1])
Trang 9
{if (a<=max2so(x[i],x[i+1])) {dem=dem+2;}}
else
{
k=float (y[i+1]-y[i])/(x[i+1]-x[i]);
m = float (y[i]-float (y[i+1]-y[i])/(x[i+1]-x[i])*x[i]);
gd=float (b-float (y[i]-float (y[i+1]-y[i])/(x[i+1]-x[i])*x[i]))/(float (y[i+1]-y[i])/ (x[i+1]-x[i]));
if (a<=gd) {dem=dem+1;}
}
}
if (dem%2==1) return true; else return false;
}
4 Kết quả tô màu
Trang 105 Chương trình cài đặt
#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <graphics.h>
#include <math.h>
int n,i,j,color=15;
int x[100],y[100];
int mx, max=x[1];
int my, may=y[1];
Trang 11float k,m,gd;
int tile=40;
void truc()
{ setcolor(14);
//0y
line(320,0,320,480);
moveto(318,2);lineto(320,0);lineto(322,2);
outtextxy(300,10,"y");
//0x
line(0,240,640,240);
moveto(638,238);lineto(640,240);lineto(638,242); outtextxy(620,250,"x");
//0
outtextxy(307,245,"O");
//chiakhoang
int i;
i=320-6*tile;
while(i<320+6*tile)
{line(i,238,i,242);
i+=tile;}
int j;
j=240-6*tile;
while(j<240+6*tile)
Trang 12{line(318,j,322,j);
j+=tile;}
}
int max2so(int a, int b)
{if (a>b) return a; else return b;
}
int min2so(int a, int b)
{if (a<b) return a; else return b;
}
bool namtrong(int a, int b)
{int dem=0;
for (int i=1;i<n+1;i++)
if ((b==y[i]) &&(a<=x[i]))
{if (((y[i-1]<b)&&(y[i+1]>b))||((y[i-1]>b)&&(y[i+1]<b))) dem=dem+1; else
{if (((y[i-1]<b)&&(y[i+1]<b))||((y[i-1]>b)&&(y[i+1]>b))) dem=dem+2;} }
else
if ((min2so(y[i],y[i+1])<b)&&(max2so(y[i],y[i+1])>b))
{ if (x[i]==x[i+1])
Trang 13{if (a<=x[i]) {dem=dem+1;}
}
else
if (y[i]==y[i+1])
{if (a<=max2so(x[i],x[i+1])) {dem=dem+2;}}
else
{
k=float (y[i+1]-y[i])/(x[i+1]-x[i]);
m = float (y[i]-float (y[i+1]-y[i])/(x[i+1]-x[i])*x[i]);
gd=float (b-float (y[i]-float (y[i+1]-y[i])/(x[i+1]-x[i])*x[i]))/(float (y[i+1]-y[i])/ (x[i+1]-x[i]));
if (a<=gd) {dem=dem+1;}
}
}
if (dem%2==1) return true; else return false;
}
main()
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"");
truc();
//nhap
Trang 14while (n<3)
{ cout<<"Nhap so canh: "; cin >> n; } cout<<"Nhap toa do cac dinh: \n"; for (i=1;i<=n;i++) cin>> x[i]>>y[i]; for (i=1;i<=n;i++)
{x[i]=320+x[i]*tile;
y[i]=240-y[i]*tile;
}
x[n+1]=x[1];y[n+1]=y[1];
Trang 15// ve da giac
setcolor(15);
moveto(x[1],y[1]);
for (i=2;i<=n+1;i++) lineto(x[i],y[i]); //min, max x
for (i=2;i<=n;i++)if (max<x[i]) max=x[i]; mx=x[1];
for (i=2;i<=n;i++)if (x[i]<mx) mx=x[i]; //min, max y
my=y[1];
for (i=2;i<=n;i++)
{if (my>y[i]) my=y[i];
if (may<y[i]) may=y[i];
}
//quet
for (i=mx+1;i<max;i++)
{
for (j=my+1;j<may;j++)
if (namtrong(i,j)) putpixel(i,j,14); }
getch(); closegraph();}
Trang 16Kết Luận
Em xin bày tỏ lòng cảm ơn đến cô Nguyễn Thị Cẩm Ngoan người đã trực tiếp hướng dẫn em trong quá trính học tập Em cũng xin chân thành cảm ơn cô và các bạn trong lớp đã giúp đỡ em hoàn thành bài tập lớn này
Em Xin Chân Thành Cảm Ơn!
Hà nội, tháng 2 năm 2012 Sinh Viên thực hiện:
Nguyễn Đức Đạt