You are on page 1of 90

Chương 2

Các thuật toán cơ bản

2.1. Thuật toán kẻ đoạn thẳng


2.2. Thuật toán kẻ đường tròn
2.3. Thuật toán tô màu
2.4. Thuật toán xén hình
1
2.1. Thuật toán kẻ đoạn thẳng

2.1.1. Nội dung thuật toán


2.1.2. Thuật toán Bresenham
2.1.3. Thuật toán Midpoint

2
2.1.1. Nội dung
• Thuật toán lấy dữ liệu hai đầu mút của
đoạn thẳng là các giá trị nguyên A(xA, yA)
và B(xB,yB)
• Bật lên tập hợp các điểm tọa độ nguyên
nằm giữa hai đầu mút để xấp xỉ tốt với
đường thẳng thực sự có thể thấy.

3
2.1.1. Nội dung
Các yêu cầu của thuật toán:
• Phải thẳng đến mức có thể được và phải qua
hai đầu mút.
• Phải mượt và cùng một độ đậm dọc theo chiều
dài của nó.
• Việc xử lý phải lặp được, nghĩa là nếu lần sau
áp dụng thuật toán cho cùng dữ liệu hai đầu
mút thì phải bật lên cùng các điểm như trước.
• Không phụ thuộc hướng vẽ.
4
2.1.1. Nội dung

5
2.1.1. Nội dung
Trong trường hợp này khi x tăng từ xA đến
xB, thì y cũng tăng từ yA đến yB, nhưng y tăng
chậm hơn x vì y<x.
Khi x tăng từng đơn vị từ xA đến xB thì giá trị
nguyên y tốt nhất có khi không tăng và có
khi tăng một đơn vị (không bao giờ giảm
hay tăng hơn một đơn vị).

6
2.1.2. Thuật toán Bresenham
Thuật toán Bresenham (1965) chỉ dùng các
giá trị nguyên và tránh mọi phép nhân để xác
định nhanh dãy điểm tọa độ nguyên giữa A
và B.
Tính vị trí mỗi điểm ảnh trên đường thẳng
dựa vào thông tin của điểm ảnh trước, đây
chính là kỹ thuật quy hoạch động.

7
2.1.2. Thuật toán Bresenham

8
2.1.2. Thuật toán Bresenham
Giả sử ở bước i-1 bằng cách nào đó biết
được điểm tọa độ nguyên xấp xỉ tốt nhất là
(xi-1, yi-1) thì ở bước i chỉ có hai điểm tọa độ
nguyên tham gia xấp xỉ là Si(xi, yi-1+1) và
Ti(xi, yi-1).
Gọi y* là điểm trên đường thẳng thực sự ở
bước thứ i thì: y* = yA + m(xi – xA)
Có 3 trường hợp xảy ra cho y* ở bước i như
sau: 9
2.1.2. Thuật toán Bresenham

10
2.1.2. Thuật toán Bresenham

11
2.1.2. Thuật toán Bresenham

12
2.1.2. Thuật toán Bresenham
Bresenham dùng các độ đo sau về sai số
giữa hai điểm có tham gia xấp xỉ tại bước
thứ i:
e(Ti) = y* – yi-1
e(Si) = yi-1+1 – y*

13
2.1.2. Thuật toán Bresenham
Có ba trường hợp xảy ra cho y* như hình vẽ là:
a) Giữa Si và Ti : Cả hai sai số này đều dương. Nếu
e(Ti) < e(Si) thì Ti gần y* hơn nên chọn Ti; ngược lại
chọn Si. Hay nếu e(Ti) – e(Si)<0 thì chọn Ti; ngược lại
chọn Si
b) Dưới Ti một ít : e(Ti), <0, e(Si)>0 nên e(Ti) –
e(Si)<0 và chọn Ti
c) Trên Si một ít : e(Ti)>0, e(Si)<0 nên e(Ti) – e(Si)>0
và chọn Si
Vậy, cả ba trường hợp đều có quyết định chung14là:
nếu e(T ) – e(S )<0 thì chọn T ; ngược lại chọn S
2.1.2. Thuật toán Bresenham

15
2.1.2. Thuật toán Bresenham

16
2.1.2. Thuật toán Bresenham
Vậy, nếu ei<0 thì chọn Ti (yi = yi-1) và cập
nhật sai số ei+1 = ei + 2y ; ngược lại chọn Si
(yi = yi-1 +1) và cập nhật sai số
ei+1 = ei + 2y − 2x
Để có giá trị đầu e1, thay i=1 vào (2.1) với
x0=xA và y0=yA có
e1= 2y − x

17
2.1.2. Thuật toán Bresenham

18
2.1.2. Thuật toán Bresenham
Dãy điểm tọa độ nguyên tính được như sau
xi 4 5 6 7 8 9 10 11 12 13 14 15 16
yi 1 1 2 2 2 2 3 3 3 3 4 4 4
ei -6 0 -18 -12 -6 0 -18 -12 -6 0 -18 -12 -6

4 ●●●
3 ●●●●
2 ●●●●
1 ●●
o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
x 19
2.1.2. Thuật toán Bresenham
Thuật toán được cài đặt bằng giả lệnh như sau:

BresLine(xA, yA, xB, yB)


{
dx = xB – xA; dy = yB – yA;
e_noinc = dy + dy; e = e_noinc – dx;
e_inc = e – dx; c = getcolor() ;
for (x = xA, y = yA; x <= xB; x++){
putpixel(x, y, c);
if (e<0) e+=e_noinc;
else { y++ ; e+=e_inc;}
} 20
2.1.2. Thuật toán Bresenham
Các trường hợp khác được suy ra từ trường
hợp trên như sau:
a) Với các đường thẳng ngang, đứng và hệ
số góc m = ±1: Các trường hợp này cần
kiểm tra ở đầu thuật toán để chỉ dùng một
vòng lặp for cho nhanh
b) xA>xB: Hoán đổi hai điểm A và B cho
nhau để x luôn tăng từ giá trị thấp đến giá trị
cao 21
2.1.2. Thuật toán Bresenham
c) m >1 : Đổi vai trò của x và y cho nhau,
cho y tăng từng đơn vị từ yA đến yB, và dùng
cùng cách kiểm tra để xác định x có tăng hay
không. Các đại lượng kiểm tra là:
e1 = 2x − y
enoinc= 2x
einc = 2x − 2y

22
2.1.2. Thuật toán Bresenham
Ví dụ A(2, 1), B(6, 11)
x = 4
y = 10
Hệ số góc m = 5/2 >1
e1 = 2x − y = − 2
enoinc= 2x =8
einc = 2x − 2y = −12
23
2.1.2. Thuật toán Bresenham
Dãy điểm tọa độ nguyên tính được như sau

xi 2 2 3 3 4 4 4 5 5 6 6

yi 1 2 3 4 5 6 7 8 9 10 11

ei -2 6 -6 2 -10 -2 6 -6 2 -10 -2

24
2.1.2. Thuật toán Bresenham
Đồ thị
y


11


10
9
8 ●
7

6 ●
5 ●
4 ●
3 ●
2 ●
1 ●
o 1 2 3 4 5 6
x 25
2.1.2. Thuật toán Bresenham
d) -1<m<0 : Thay y bởi −y, cho x tăng
từng đơn vị từ xA đến xB, và dùng cùng cách
kiểm tra để xác định y có giảm hay không.
Các đại lượng kiểm tra là:
e1 = − 2y − x
enodec= − 2y
edec = − 2y − 2x

26
2.1.2. Thuật toán Bresenham
Ví dụ A(0, 3), B(12, 0)
x = 12
y = −3
Hệ số góc m = −1/4 <0 và m> −1
e1 = − 2y − x = −6
enodec= − 2y =6
edec = − 2y − 2x= −18
27
2.1.2. Thuật toán Bresenham
Dãy điểm tọa độ nguyên tính được như sau
xi 0 1 2 3 4 5 6 7 8 9 10 11 12
yi 3 3 2 2 2 2 1 1 1 1 0 0 0
ei -6 0 -18 -12 -6 0 -18 -12 -6 0 -18 -12 -6

●●
3

2 ●●●●
1 ●●●●
o 1 2 3 4 5 6 7 8 9 ●10 ●11 ●12 28
x
2.1.2. Thuật toán Bresenham
e) m<−1 : Đổi vai trò của x và y cho nhau (lấy
đối xứng qua phân giác I) để trở về trường hợp
m>1, rồi thay y bởi −y (lấy đối xứng qua
trục hoành). Cho y giảm từng đơn vị từ yA đến
yB, và dùng ei để kiểm tra x có tăng hay không.
Các đại lượng kiểm tra là:
e1 = 2x + y
enoinc= 2x
einc = 2x + 2y
29
2.1.2. Thuật toán Bresenham
Ví dụ A(1, 10), B(4, 1)
x = 3
y = − 9
Hệ số góc m = − 3< − 1
e1 = 2x + y = − 3
enoinc= 2x =6
einc = 2x + 2y = −12
30
2.1.2. Thuật toán Bresenham
Dãy điểm tọa độ nguyên tính được như sau

xi 1 1 2 2 2 3 3 3 4 4

yi 10 9 8 7 6 5 4 3 2 1

ei -3 3 -9 -3 3 -9 -3 3 -9 -3

31
2.1.2. Thuật toán Bresenham
Đồ thị
y
10 ●
9 ●
8 ●
7

6 ●
5 ●
4 ●
3 ●
2 ●
1 ●
o 1 2 3 4
x 32
2.1.3. Thuật toán Midpoint
Thuật toán Midpoint (trung điểm) được
Pitteway đưa ra năm 1967 và Van Aken cải
tiến vào năm 1984.
Thuật toán Midpoint cải tiến từ thuật toán
Bresenham bằng cách tổng hợp ba trường
hợp của y* và chỉ cần xét M là trung điểm
của SiTi để so sánh vị trí với y*, từ đó có
quyết định chọn Si hay Ti.
33
2.1.3. Thuật toán Midpoint

34
2.1.3. Thuật toán Midpoint

yi-1+1 Si

M
y*
yi-1 Ti
xi-1 xi
a) 35
2.1.3. Thuật toán Midpoint
Với điểm P(x, y) đặt e(P) = Ax+By+C
Có nhận xét:
•e(P) < 0, nếu P nằm bên trên đường thẳng
•e(P) = 0, nếu P nằm trên đường thẳng
•e(P)> 0, nếu P nằm bên dưới đường thẳng
Đặt pi = e(M). Nếu pi<0 thì M ở bên trên
đường thẳng, do đó y* gần Ti hơn Si và Ti
được chọn. Ta có: Nếu pi<0 thì chọn Ti;
ngược lại, chọn Si. 36
2.1.3. Thuật toán Midpoint

37
2.1.3. Thuật toán Midpoint

38
2.1.3. Thuật toán Midpoint
Các đại lượng được chỉ bằng một nửa các
đại lượng của thuật toán Bresenham.
Thuật toán được cài đặt bằng giả lệnh như sau
MLine(xA, yA, xB, yB){
dx = xB – xA; dy = yB – yA; p = dy-dx/2;
for (x = xA, y = yA; x <= xB; x++){
putpixel(x, y, c);
if (p<0) p+=dx; else { y++ ; p+=dy-dx;}
} 39
2.1.3. Thuật toán Midpoint
Ví dụ A(4, 1), B(16, 4)
x = 12
y = 3
Hệ số góc m = 1/4 >0 và m<1
p1 = y − x/2 = −3
pnoinc= y =3
pinc = y −x = −9
40
2.1.3. Thuật toán Midpoint
Dãy điểm tọa độ nguyên tính được như sau
xi 4 5 6 7 8 9 10 11 12 13 14 15 16
yi 1 1 2 2 2 2 3 3 3 3 4 4 4
pi -3 0 -9 -6 -3 0 -9 -6 -3 0 -9 -6 -3

4 ●●●
3 ●●●●
2 ●●●●
1 ●●
o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
x 41
2.1.3. Thuật toán Midpoint
Ví dụ A(1, 1), B(4, 10)
x = 3
y = 9
Hệ số góc m = 3 >1
p1 = x − y/2 = −1
pnoinc= x =3
pinc = x − y = −6
42
2.1.3. Thuật toán Midpoint
Dãy điểm tọa độ nguyên tính được như sau

xi 1 1 2 2 2 3 3 3 4 4

yi 1 2 3 4 5 6 7 8 9 10

pi -1 2 -4 -1 2 -4 -1 2 -4 -1

43
2.1.3. Thuật toán Midpoint
Đồ thị
y
10 ●
9 ●
8 ●
7

6 ●
5 ●
4 ●
3 ●
2 ●
1 ●
o 1 2 3 4
x 44
2.1.3. Thuật toán Midpoint
Ví dụ A(1, 4), B(10, 1)
x = 9
y = −3
Hệ số góc m = −1/3 <0 và m> − 1
p1 = − y − x/2 = −1
pnodec= − y =3
pdec = − y − x = −6
45
2.1.3. Thuật toán Midpoint
Dãy điểm tọa độ nguyên tính được như sau
xi 1 2 3 4 5 6 7 8 9 10

yi 4 4 3 3 3 2 2 2 1 1

pi -1 2 -4 -1 2 -4 -1 2 -4 -1

4 ●●
3 ●●●
2 ●●●
1 ●●
o 1 2 3 4 5 6 7 8 9 10
x 46
2.1.3. Thuật toán Midpoint
Ví dụ A(1, 10), B(4, 1)
x = 3
y = − 9
Hệ số góc m = −3< −1
p1 = x + y/2 = −1
pnoinc= x =3
pinc = x + y = −6
47
2.1.3. Thuật toán Midpoint
Dãy điểm tọa độ nguyên tính được như sau

xi 1 1 2 2 2 3 3 3 4 4

yi 10 9 8 7 6 5 4 3 2 1

pi -1 2 -4 -1 2 -4 -1 2 -4 -1

48
2.1.3. Thuật toán Midpoint
Đồ thị
y
10 ●
9 ●
8 ●
7

6 ●
5 ●
4 ●
3 ●
2 ●
1 ●
o 1 2 3 4
x 49
2.2. Thuật toán kẻ đường tròn

2.2.1. Nội dung thuật toán


2.2.2. Thuật toán Michener
2.2.3. Thuật toán Midpoint

50
2.2.1. Nội dung

51
2.2.1. Nội dung

(-x,y) A (x,y)
B

(-y,x) (y,x)
x
O R
2
(-y,-x) (y,-x)

(-x,-y) (x,-y)
52
2.2.2. Thuật toán Michener
Chỉ cần xét cung AB ở nửa trên của góc
phần tư thứ nhất
Với điểm toạ độ nguyên xấp xỉ trên cung là
(x, y), thì có được 7 điểm tương ứng trên
đường tròn
Trên cung AB, hệ số góc tiếp tuyến m của
đường tròn thoả mãn: ̶ 1 ≤ m ≤ 0. Nên khi
cho x tăng từng đơn vị từ xA đến xB thì y
giảm một đơn vị hoặc không giảm 53
2.2.2. Thuật toán Michener
Phương trình đường tròn (O, R) :
x2 + y2 = R2
với một điểm P(x, y), đặt e(P)=x2 + y2 ̶ R2
Có:
e(P) < 0: nếu P nằm bên trong đường tròn
e(P) = 0: nếu P nằm trên đường tròn
e(P) > 0: nếu P nằm bên ngoài đường tròn
54
2.1.3. Thuật toán Michener
Giả sử ở bước i-1 bằng cách nào đó biết
được điểm tọa độ nguyên xấp xỉ tốt nhất là
(xi-1, yi-1) thì ở bước i chỉ có hai điểm tọa độ
nguyên tham gia xấp xỉ là Si(xi, yi-1) và
Ti(xi, yi-1 – 1)

e(Si) = xi2 + yi-12 ̶ R2


e(Ti) = xi2 + (yi-1 ̶ 1)2 ̶ R2
55
2.2.2. Thuật toán Michener
Gọi y* là điểm trên đường tròn thực sự ở
bước thứ i thì có 3 trường hợp xảy ra cho y*
ở bước i như sau

y*
Si Si Si
y*

Ti Ti Ti
y*

56
2.2.2. Thuật toán Michener
Xét ba trường hợp cho y* như hình vẽ là:
a) Giữa Si và Ti: e(Ti) < 0 và e(Si)>0.
Nếu |e(Ti)| > e(Si) thì chọn Si; ngược lại
chọn Ti. Hay nếu e(Ti) + e(Si)<0 thì chọn Si;
ngược lại chọn Ti
b) Trên Si: e(Ti)<0 và e(Si)<0 nên
e(Ti) + e(Si)<0 và chọn Si
c) Dưới Ti: e(Ti)>0, e(Si)>0 nên
e(Ti) + e(Si)>0 và chọn Ti 57
2.2.2. Thuật toán Michener
Vậy, cả ba trường hợp đều có quyết định
chung là: nếu e(Ti) + e(Si)<0 thì chọn Si;
ngược lại chọn Ti
Đặt di= e(Ti) + e(Si)
Có quyết định chung là:
Nếu di < 0 thì chọn Si (y không giảm); ngược
lại, chọn Ti (y giảm)

58
2.2.2. Thuật toán Michener
di = e(Ti) + e(Si)
di = 2xi2 + yi-12 +(yi-1 ̶ 1)2 ̶ 2R2
di = 2xi2 + 2yi-12 ̶ 2yi-1+1 ̶ 2R2
di = 2xi-12 +2yi-12 +4xi-1 ̶ 2yi-1+ 3 ̶ 2R2 (2.5)
di +1= 2xi2 +2yi2 +4xi ̶ 2yi+ 3 ̶ 2R2 (2.6)
di+1= di +2(xi2 ̶ xi-12)+2(yi2 ̶ yi-12) ̶ 2(yi ̶ yi-1) + 4
di+1= di + 4xi-1 + 2(yi2 ̶ yi-12) ̶ 2(yi ̶ yi-1) + 6

59
2.2.2. Thuật toán Michener
Nếu di < 0 thì chọn Si (yi = yi-1) và cập nhật
sai số:
di+1= di + 4xi-1 + 6
ngược lại, chọn Ti (yi = yi-1 ̶ 1) và cập nhật
sai số:
di+1= di + 4xi-1 ̶ 4yi-1 + 10
Để có giá trị đầu cho di, thay i = 1 vào (2.5)
với x0 = 0 và y0 = R, ta được:
d1= 3 ̶ 2R 60
2.2.2. Thuật toán Michener
Về cơ bản, ý tưởng của thuật toán
Michener tương tự thuật toán
Bresenham kẻ đoạn thẳng nên còn được
gọi là thuật toán Bresenham kẻ đường
tròn.
Thuật toán Michener vẽ đường tròn tâm
O bán kính R được cài đặt như sau:
61
2.2.2. Thuật toán Michener
Thuật toán được cài đặt bằng giả lệnh như sau
MichenerCircle( R)
{
d= 3-2*R; c = getcolor();
x = 0; y = R;
while (x <= y) {
putpixel(x, y, c); putpixel(-x, y, c); putpixel(x, -y, c); putpixel(-x, -y, c);
putpixel(y, x, c); putpixel(y, -x, c); putpixel(-y, x, c); putpixel(-y, -x, c);
if (d<0) d += 4*x+6;
else {
d += 4*x-4*y+10;
y--;
}
x++; 62
}
2.2.3. Thuật toán Midpoint
Tương tự thuật toán Midpoint kẻ đoạn thẳng.
Tổng hợp 3 trường hợp của y* và chỉ cần xét M
là trung điểm của SiTi để so sánh vị trí với y*, từ
đó có quyết định chọn Si hay Ti.
yi-1
i
Si
y*
M
yi-1-1
Ti

63
xi-1 90
xi
2.2.3. Thuật toán Midpoint

64
2.2.3. Thuật toán Midpoint

65
2.2.3. Thuật toán Midpoint

66
2.2.3. Thuật toán Midpoint
Thuật toán được cài đặt bằng giả lệnh như sau
MidpointCircle( R)
{
p= 1- R; c = getcolor();
x = 0; y = R;
while (x <= y) {
putpixel(x, y, c); putpixel(-x, y, c); putpixel(x, -y, c); putpixel(-x, -y, c);
putpixel(y, x, c); putpixel(y, -x, c); putpixel(-y, x, c); putpixel(-y, -x, c);
if (p<0) p += 2*x + 3;
else {
p += 2*x - 2*y + 5;
y--;
}
x++; 67
}
2.3. Thuật toán tô màu

2.3.1. Thuật toán tô tràn


2.3.2. Thuật toán đa giác

68
2.3.1. Thuật toán tô tràn
Xét thuật toán tô đặc một vùng khép kín với
điểm bên trong (x, y) và màu biên bc. Thuật
toán nhận tọa độ điểm (x, y) và màu biên bc,
công việc của thuật toán là bật các điểm bên
trong vùng với màu tô c.
Thuật toán được gọi để tô điểm (x, y) với màu c.
Khi một điểm được tô thì gọi đệ quy tiếp để tô
cho tất cả các điểm lân cận nó. Có thể gọi 4
điểm hoặc 8 điểm lân cận.
69
2.3.1. Thuật toán tô tràn
Chỉ gọi 4 điểm lân cận, thuật toán được cài đặt
như sau:
void Fill(int x, int y, int bc, int c)
{
int cc=getpixel(x,y);
if((cc!=bc) &&(cc!=c)){
putpixel(x,y,c);
Fill(x-1,y,bc,c); Fill(x+1,y,bc,c);
Fill(x,y-1,bc,c); Fill(x,y+1,bc,c);
} 70
}
2.3.1. Thuật toán tô tràn
Nhận xét:
• Một điểm bị gọi lặp nhiều lần bởi
tất cả các điểm lân cận nó nên tô
chậm.
• Hơn nữa vì gọi đệ quy nên dễ
tràn ngăn xếp.
Vì vậy chỉ tô được vùng khá nhỏ.71
2.3.1. Thuật toán tô tràn
Điều này có thể cải tiến bằng cách tô theo dòng
quét với việc tạo ngăn xếp S riêng và thực hiện
các bước sau:
- Khởi đầu ngăn xếp S={(x, y)}
- Lặp cho đến khi S rỗng:
• Lấy ra khỏi S một điểm P
• Tô đoạn thẳng nằm ngang chứa điểm P
• Quét dòng trên P để đẩy vào S các điểm bên phải của
các đoạn cần tô
• Thực hiện tương tự cho dòng dưới P 72
2.3.2. Thuật toán tô đa giác
Đa giác là vùng đặc biệt nên được cài đặt thuật
toán riêng để tô cho nhanh.
Giả sử đa giác P cần tô nội tiếp trong dải băng
[ymin, ymax]. Thuật toán cho dòng quét y chạy từ
ymin đến ymax, ứng với mỗi dòng quét y thực hiện
các bước sau:
- Tìm dãy giao điểm của y với các cạnh
- Sắp xếp dãy giao điểm theo thứ tự hoành độ tăng dần.
- Với các đoạn giữa các giao điểm thực hiện xen kẻ việc tô
rồi không tô. 73
2.3.2. Thuật toán tô đa giác
Nhận xét:
• Thuật toán tô được tất cả các đa giác lồi,
lõm và có lổ hổng.
• Tuy nhiên, khi dòng quét qua điểm
không là cực trị địa phương thì thuật
toán sai.
Điều này có thể cải tiến bằng cách hạ đầu
mút cạnh dưới một đơn vị. 74
2.4. Thuật toán xén hình

2.4.1. Nội dung


2.4.2. Thuật toán Cohen-
Sutherland

75
2.4.1. Nội dung thuật toán
Xét thuật toán xén đoạn thẳng vào cửa sổ chữ
nhật có các cạnh song song hệ trục tọa độ.

76
2.4.1. Nội dung thuật toán
Các trường hợp thuật toán phải thực hiện:
• Không làm gì cả nếu cả hai đầu mút đều ở bên
trong cửa sổ. Như đoạn AB.
• Xén một đầu mút nếu một ở bên trong và một ở
bên ngoài cửa sổ. Như đoạn GH.
• Xén cả hai đầu mút nếu cả hai ở bên ngoài nhưng
một phần của đoạn thẳng ở bên trong. Như đoạn IJ.
• Hủy đoạn thẳng nếu toàn bộ đoạn thẳng ở bên
ngoài. Như đoạn CD, KL, …
77
2.4.1. Nội dung thuật toán
Các trường hợp tầm thường:
• Nếu cả hai đầu mút đều ở bên trong cửa sổ
thì toàn bộ đoạn thẳng ở bên trong.
• Nếu cả hai đầu mút đều ở cùng một trong
bốn phía đối với cửa sổ thì toàn bộ đoạn
thẳng ở bên ngoài.
Thuật toán lặp việc xén một đầu mút về lề cửa
sổ cho đến khi rơi vào một trong hai trường hợp
tầm thường trên. 78
2.4.2. Thuật toán Cohen-Sutherland
Giả sử cửa sổ W được xác định bởi các lề: minx,
maxx, miny, maxy.
Để xác định vị trí tương đối của một điểm P so
với W cần mã hóa điểm P thành mã C gồm 4 bit
như sau:

79
2.4.2. Thuật toán Cohen-Sutherland
Các macro giá trị bit đánh dấu lề được khai báo
như sau:

#define LEFT_EDGE 0x1


#define RIGHT_EDGE 0x2
#define TOP_EDGE 0x4
#define BOTTOM_EDGE 0x8

80
2.4.2. Thuật toán Cohen-Sutherland
Hàm mã hóa điểm P(x, y) thành mã C:
int Encode(int x, int y )
{
int code = 0x00;

if (x < minx) code = LEFT_EDGE;


if (x > maxx) code = RIGHT_EDGE;
if (y < miny) code = code | BOTTOM_EDGE;
if (y > maxy) code = code | TOP_EDGE;
return code; 81
}
2.4.2. Thuật toán Cohen-Sutherland
Thuật toán được cài đặt với hàm
int Clip(int &x1, int &y1, int &x2, int &y2)
Để xén đoạn thẳng AB vào W, với A(x1, y1),
B(x2, y2).
Thuật toán đưa A, B về lề cửa sổ W nếu cần
xén.
Sau khi xén, hàm trả về 1 nếu AB còn thấy được
trong W.
82
2.4.2. Thuật toán Cohen-Sutherland
Giả sử hai điểm A, B có mã là a, b tương ứng.
Các macro hàm như sau:
• Điểm A ở bên trong W nếu 4 bit đều 0
#define INSIDE(a) (!a)
• Cả hai điểm đều ở bên trong W
#define ACCEPT(a,b) (!(a|b))
• Cả hai điểm đều ở về cùng một phía W
#define REJECT(a,b) (a&b) 83
2.4.2. Thuật toán Cohen-Sutherland
Khi cần xén phải có điểm ở bên ngoài W. Để chỉ
xén điểm A về lề W, đầu bước lặp cần kiểm tra
nếu điểm A ở bên trong thì đổi 2 điểm A, B cho
nhau và đổi cả mã của chúng.

void Swap(int &a, int &b)


{
int tmp;
tmp = a; a = b; b = tmp;
84
}
2.4.2. Thuật toán Cohen-Sutherland
Khi xén cần lưu ý các đoạn thẳng đứng
if (x2 == x1)
if (c1 & TOP_EDGE) y1 = maxy;
else y1 = miny;

Khi xén cần tính đến hệ số góc m


m = float(y2 - y1) / (x2 - x1);

85
2.4.2. Thuật toán Cohen-Sutherland
Rút điểm A về lề trái W:
if (c1 & LEFT_EDGE){
y1 += int( (minx - x1) * m );
x1 = minx;
}
Rút điểm A về lề phải W:
if (c1 & RIGHT_EDGE){
y1 += int( (maxx - x1) * m );
x1 = maxx; 86
2.4.2. Thuật toán Cohen-Sutherland
Rút điểm A về lề trên W:
if (c1 & TOP_EDGE){
x1 += int( (maxy - y1) / m );
y1 = maxy;
}
Rút điểm A về lề dưới W:
if (c1 & BOTTOM_EDGE){
x1 += int( (miny - y1) / m );
y1 = miny; 87
2.4.2. Thuật toán Cohen-Sutherland
Thuật toán được cài đặt như sau:
int Clip(int &x1, int &y1, int &x2, int &y2)
{
int c1, c2; float m;
while (1){
c1 = Encode(x1, y1);
c2 = Encode(x2, y2);
if (ACCEPT(c1, c2)) return 1;
if (REJECT(c1, c2)) return 0;
if (INSIDE(c1)){
Swap(x1, x2); Swap(y1, y2);
Swap(c1, c2); 88
}
2.4.2. Thuật toán Cohen-Sutherland
if (x2 == x1)
if (c1 & TOP_EDGE) y1 = maxy;
else y1 = miny;
else {
m = float(y2 - y1) / (x2 - x1);
if (c1 & LEFT_EDGE){
y1 += int( (minx - x1) * m );
x1 = minx;
}
else
if (c1 & RIGHT_EDGE){
y1 += int( (maxx - x1) * m ); 89
x1 = maxx;
2.4.2. Thuật toán Cohen-Sutherland
else
if (c1 & TOP_EDGE){
x1 += int( (maxy - y1) / m );
y1 = maxy;
}
else
if (c1 & BOTTOM_EDGE){
x1 += int( (miny - y1) / m );
y1 = miny;
}
}
} 90
}

You might also like