You are on page 1of 42

Đồ họa máy tính

Các thuật toán mành hóa

1 01/11/22 Ma Thị Châu - Bùi Thế Duy


Các thuật toán tô phủ
Bài toán tô phủ loang (Flood fill problem):
Với hai màu khác nhau c và c’, một tập các điểm A có cùng màu c được
bao quanh bởi các điểm có màu khác với c và c’, tìm thuật toán thay màu
của tất cả các điểm thuộc A và chỉ các điểm này thành màu c’

2 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán tô phủ cơ bản

procedure BFA (integer x, y)


begin
if Inside (x,y) then
Begin

Set (x,y);
BFA (x,y - 1); BFA (x,y + 1);
BFA (x - 1,y); BFA (x + 1,y);
end
end;

3 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán tô phủ của Smith
int x, y, lx, rx;
/*Một ngăn xếp chứa tọa độ các điểm (x,y);*/
void Fill (int seedx, int seedy){
x = seedx; y = seedy;
if (!(Inside (x,y)) exit(0);
Push (x,y);
while (StackNotEmpty()){
PopXY ();
if (Inside(x,y)){
FillRight (); FillLeft ();
/* Phủ các đoạn có chứa điểm */
ScanHi (); ScanLo ();
/*Quét các đoạn trên và dưới của đoạn hiện tại*/
}
}
4 } 01/11/22 Ma Thị Châu - Bùi Thế Duy
Thuật toán tô phủ của Smith

Bắt đầu: (7,3).


FillRight: đoạn (7,3) đến (8,3) được tô.
FillLeft: (6,3) được tô.
ScanHi: điểm (6,4) và (8,4) vào ngăn xếp.
ScanLo:điểm (6,2) vào ngăn xếp.
Lấy(6,2) ra, và coi đây là điểm bắt đầu.
Lệnh FillRight và FillLeft: tô phủ đoạn từ
(2,2) đến (8,2).
ScanHi và ScanLo:cho (2,3) và (6,3) vào
ngăn xếp.
6,3 Lấy (6,3) ra.
6,2
2,3 (6,3) đã được tô lấy ra (2,3) và cứ tiếp tục
như thế cho đến khi ngăn xếp rỗng
8,4
5 6,4 01/11/22 Ma Thị Châu - Bùi Thế Duy
Định lý Jordan.
Số điểm cắt chẵn: Ngoài đa giác
4 3 2 0 Số điểm cắt lẻ: Trong đa giác
1

2 0
4 1
Không đúng đối với đa giác tự cắt
3

6 01/11/22 Ma Thị Châu - Bùi Thế Duy


Định lý Jordan
Kiểm tra đại lượng e
-Sử dụng cả hướng của đường thẳng
-đặt e = 0
-Cắt từ trái qua phải e + +, phải qua trái e - -
-e != 0, nằm trong

1 0 0
2 0 1
0 1

7 01/11/22 Ma Thị Châu - Bùi Thế Duy


Trường hợp đặc biệt
• Có 2 trường hợp đặc biệt trong thuật toán Jordan :
• Cắt trùng lên cạnh

• Cắt trùng lên đỉnh đa giác

8 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán đường quét
 Kiểm tra Jordan tăng dần
 Sắp xếp theo giá trị của y
y

9 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán đường quét
 Kiểm tra Jordan tăng dần
 Sắp xếp theo giá trị của y
 Sử dụng sự liên kết giữa các đường quét – giá trị
cho đường quét trước gần bằng giá trị cho đường
quét sau.
 Lưu trữ danh sách các cạnh đang xét

10 01/11/22 Ma Thị Châu - Bùi Thế Duy


Danh sách các cạnh đang xét
Các đỉnh là các ‘sự kiện’ trong danh sách cạnh – các cạnh có thể được
xét, không được xét hoặc được thay bằng các cạnh khác
- Sắp xếp các giao điểm theo x
- Kết quả chính là phần giữa cạnh bên trái và bên phải
Tạo

y
Thay thế

Xóa

11 01/11/22 Ma Thị Châu - Bùi Thế Duy


Đồ họa máy tính

Vẽ đường thẳng và đường tròn

12 01/11/22 Ma Thị Châu - Bùi Thế Duy


Hướng tới một đường thẳng lý tưởng

 Chúng ta chỉ có thể vẽ xấp xỉ đường thẳng một cách


rời rạc

 Chiếu sáng các điểm gần nhất với đường thẳng thực
tế trong trường hợp chỉ có hai cách thể hiện một
điểm:
– Điểm được thắp sáng hoặc không thắp sáng

13 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thế nào là một đường thẳng lý tưởng

 Trông phải thẳng và liên tục


– Trong máy tính chỉ có thể được như vậy với các đường
thẳng song song với trục tọa độ hoặc có góc 45o với trục
tọa độ
 Phải đi qua hai điểm đầu và cuối
 Phải có mật độ và cường độ sáng đều
– Đều trên một đường thẳng và đều trên tất cả các đường
thẳng
 Thuật toán vẽ phải hiệu quả và có thể thực hiện
nhanh

14 01/11/22 Ma Thị Châu - Bùi Thế Duy


Đường thẳng đơn giản

Dựa trên phương trình đường


thẳng:
y = mx + b
Cách tiếp cận đơn giản:
tăng x, rồi tìm ra y
Cần các tính toán số thực

15 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán đó có tốt không?

Thuật toán có vẻ ổn với những


đường thẳng có hệ số góc nghiêng
(slope) bằng 1 hoặc nhỏ hơn,
tuy nhiên, nó không tốt cho những
đường thẳng với hệ số góc nghiêng
lớn hơn 1 – các đường thẳng trông
rời rạc – phải thêm các điểm vào các
cột thì trông mới ổn.
Giải pháp? - sử dụng phương pháp
đối xứng.
16 01/11/22 Ma Thị Châu - Bùi Thế Duy
Thay đổi thuật toán cho từng góc phần
tám (45°) của hệ tọa độ

Có thể thay đổi tên của trục tọa độ, HOẶC, tăng theo trục x nếu
dy<dx, nếu không thì tăng theo trục y
17 01/11/22 Ma Thị Châu - Bùi Thế Duy
Thuật toán DDA
 DDA = Digital Differential Analyser
(Phân tích vi phân số hóa)
 Xét đường thẳng theo phương trình tham số theo t:

Start point - ( x1 , y1 ) x(t )  x1  t ( x2  x1 )


End point - ( x2 , y2 ) y (t )  y1  t ( y2  y1 )

18 01/11/22 Ma Thị Châu - Bùi Thế Duy


x(t )  x1  t ( x2  x1 )
Thuật toán DDA y (t )  y1  t ( y2  y1 )

 Bắt đầu với t = 0 dx


xmoi  xcu 
 Tại mỗi bước, tăng t một lượng dt
dt dy
ymoi  ycu 
dt
 Chọn giá trị thích hợp cho dt
 Sao cho không bỏ mất điểm nào:
– Nghĩa là: dx  1 và dy
1
dt dt
 Chọn dt là giá trị max của dx và dy

19 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán DDA

line(int x1, int y1, int x2, int y2)

{ n - range of t.
float x,y;
int dx = x2-x1, dy = y2-y1;
int n = max(abs(dx),abs(dy));
float dt = n, dxdt = dx/dt, dydt = dy/dt;
x = x1;
y = y1;
while( n-- ) {
point(round(x),round(y));
x += dxdt;
y += dydt;
}
20 } 01/11/22 Ma Thị Châu - Bùi Thế Duy
Thuật toán DDA

 Vẫn còn sử dụng rất nhiều phép toán số


thực.
– 2 phép làm tròn và hai phép cộng số thực.
 Liệu có cách nào đơn giản hơn không?
 Có cách nào mà chúng ta chỉ cần dùng các
phép toán số nguyên?
– Như vậy sẽ có thể cài đặt dễ dàng trên máy tính
hiện thời và có thể chạy rất nhanh.

21 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán Bresenham

 Lưu ý trong thuật toán DDA, x hoặc y luôn


tăng lên 1
 Giả sử x luôn tăng lên 1, cần tính y cho hiệu
quả

22 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán Bresenham (…)
 Giả thiết đường thẳng chúng ta cần vẽ là từ (0,0)
đến (a,b), với a và b là 2 số nguyên, và 0 ≤ b ≤ a
(vì (a,b) ở góc phần tám thứ nhất)

xi = xi – 1 + 1 = i
yi = yi – 1 + b/a = i*b/a

Cần tính yi và sau đó làm tròn đến số nguyên gần nhất

23 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán Bresenham (…)
 Giá trị của tọa độ y bắt đầu từ 0. Tại điểm
nào, yi sẽ bắt đầu bằng 1?
 Để trả lời câu hỏi này, chúng ta phải tính b/a,
2b/a, 3b/a, …, và xem tại điểm nào các giá trị
này bắt đầu lớn hơn 1/2
 Sau đó, giá trị của y sẽ giữ bằng 1 cho đến
khi lớn hơn 3/2
 Như vậy chúng ta phải so sánh b/a, 2b/a,
3b/a … với các số 1/2, 3/2, 5/2, …

24 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán Bresenham (…)
 Tránh làm các phép tính số thực => thay bằng các
phép so sánh 2b, 4b, 6b, … với a, 3a, 5a, ..
 Việc so sánh một số với 0 nhanh hơn việc so sánh 2
số với nhau, do đó chúng ta sẽ bắt đầu với việc xét
khi nào thì 2b-a, 4b-a, … bắt đầu lớn hơn 0
 Ban đầu, đặt biến quyết định d = 2b – a, mỗi lần cần
cộng thêm 2b vào d
 Đến khi d bắt đầu lớn hơn 0, trừ thêm 2a vào d

25 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán Bresenham (…)
begin
integer d, x, y;
d := 2*b - a;
x := 0;
y := 0;
while true do
begin
Draw (x,y);
if x = a then Exit;
if d ≥ 0 then
begin
y := y + 1;
d := d - 2*a;
end;
x := x + 1;
d := d + 2*b;
end
end

26 01/11/22 Ma Thị Châu - Bùi Thế Duy


Quan sát các đường thẳng

while( n-- )
{
draw(x,y);
move right;
if( below line )
move up;
}`

27 01/11/22 Ma Thị Châu - Bùi Thế Duy


Kiểm tra một điểm nằm ở phía nào của
đường thẳng

 Để cài đặt được thuật toán mới cần kiểm tra xem
một điểm nằm ở phía nào của đường thẳng.
 Viết phương trình đường thẳng:

F ( x, y )  ax  by  c  0
• Dễ nhận thấy nếu F<0, điểm đó nằm trên
đường thẳng, nếu F>0 điểm đó nằm dưới đường
thẳng.

28 01/11/22 Ma Thị Châu - Bùi Thế Duy


Kiểm tra một điểm nằm ở phía nào của
đường thẳng


F ( x, y )  ax  by  c  0
Cần phải tìm các hệ số a,b,c.
 Xét dạng khác của phương trình đường thẳng:

 Do đó:
dy
y  mx  b do đó y  xb
dx

F ( x, y )  dy.x  dx. y  c  0
29 01/11/22 Ma Thị Châu - Bùi Thế Duy
Đại lượng quyết định
Tính F tại điểm M
Coi đây là đại lượng quyết định
1
d  F ( x p  1, y p  )
2
NE

M
E

Điểm trước Các phương án Các phương án cho điểm tiếp theo
(xp,yp) cho điểm
hiện tại

30 01/11/22 Ma Thị Châu - Bùi Thế Duy


Đại lượng quyết định
Tính d cho điểm tiếp theo, Quyết định xem điểm E và NE sẽ được chọn :
Nếu điểm E được chọn :
1 1
d moi  F ( x p  2, y p  )  a ( x p  2)  b( y p  )  c
2 2
Xem lại :
1
d cu  F ( x p  1, y p  )
NE 2
1
M  a ( x p  1)  b( y p  )  c
2
E
Điểm trước Những lựa
Do đó :
d moi  d cu  a
(xp,yp) Những lựa chọn cho
chọn cho điểm tiếp theo  d cu  dy
điểm hiện tại
31 01/11/22 Ma Thị Châu - Bùi Thế Duy
Đại lượng quyết định
Nếu điểm NE được chọn :
3 3
d moi  F ( x p  2, y p  )  a( x p  2)  b( y p  )  c
2 2

M Do đó:
NE
d moi  d cu  a  b
E
 d moi  dy  dx
Điểm trước Những lựa
(xp,yp) Những lựa chọn cho
chọn cho điểm tiếp theo
điểm hiện tại

32 01/11/22 Ma Thị Châu - Bùi Thế Duy


Tóm tắt thuật toán điểm giữa (mid-
point algorithm)

 Chọn một trong hai điểm tiếp theo dựa trên


dấu của đại lượng quyết định.
 Điểm bắt đầu là (x1,y1).
 Cần phải tính giá trị ban đầu của đại lượng
quyết định d.

33 01/11/22 Ma Thị Châu - Bùi Thế Duy


Giá trị ban đầu của d
1 1
Điểm bắt đầu (x1,y1) d batdau  F ( x1  1, y1  )  a( x1  1)  b( y1  )  c
2 2
b
 ax1  by1  c  a 
2
b
 F ( x1 , y1 )  a 
2
Tuy nhiên (x1,y1) là một điểm trên đường thẳng, do đó F(x1,y1) =0

d batdau  dy  dx / 2
Nhân đại lượng này với 2 để loại bỏ mẫu số  không ảnh hưởng đến dấu.

34 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán điểm giữa
void MidpointLine(int while (x < x2) {
x1,y1,x2,y2) if (d<= 0) {
{ d+=incrE;
int dx=x2-x1; x++
} else {
int dy=y2-y1; d+=incrNE;
int d=2*dy-dx; x++;
int increE=2*dy; y++;
}
int incrNE=2*(dy-dx); WritePixel(x,y);
x=x1; }
y=y1; }

WritePixel(x,y);

35 01/11/22 Ma Thị Châu - Bùi Thế Duy


Thuật toán điểm giữa chưa phải là cuối
cùng!

Thuật toán 2 bước (2-step algorithm) bởi


Xiaolin Wu:
Coi việc vẽ đường thẳng như một au-tô-mát, xét
hai điểm tiếp theo của một đường thẳng, dễ
dàng thấy chỉ có một lượng hữu hạn các khả
năng.
Thuật toán này còn tận dụng sự đối xứng của
đường thẳng bằng cách vẽ đường thẳng cùng
một lúc từ hai phía đến điểm giữa (giảm gần
một nửa sự tính toán)
36 01/11/22 Ma Thị Châu - Bùi Thế Duy
Thuật toán hai bước
Các vị trí tiếp theo của hai điểm phụ thuộc vào hệ số nghiêng
của đường thẳng: Hệ số nghiêng từ 0 đến ½

Hệ số nghiêng từ ½ đến 1

Hệ số nghiêng từ 1 và 2

Hệ số nghiêng lớn hơn 2

37 01/11/22 Ma Thị Châu - Bùi Thế Duy


Vẽ đường tròn
 Cũng có thể dùng thuật toán điểm giữa để vẽ đường tròn.

M
SE

Điểm trước Lựa chọn Lựa chọn


cho điểm cho điểm
hiện tại tiếp theo

38 01/11/22 Ma Thị Châu - Bùi Thế Duy


Vẽ đường tròn
 Phương trình đường thẳng đường tròn:

f ( x, y )  ( x  xc ) 2  ( y  yc ) 2  r 2
Neu SE duoc chon d moi  d cu  (2 x p  2 y p  5)
Neu E duoc chon d moi  d cu  (2 x p  3)

39 01/11/22 Ma Thị Châu - Bùi Thế Duy


Những vấn đề với thuật toán Bresenham và
thuật toán điểm giữa

 Các điểm được vẽ trên một đường thẳng


đơn  khi thay đổi góc, độ sáng của đường thẳng
thay đổi.

Mật độ điểm = 2.n pixels/mm


Có thể vẽ bằng những mầu khác
nhau khi thay đổi góc

Mật độ điểm = n pixels/mm

40 01/11/22 Ma Thị Châu - Bùi Thế Duy


Tóm tắt về vẽ đường thẳng
 Sử dụng dạng “hiện” (explicit) của đường thẳng
– Không hiệu quả, khó kiểm soát.
 Sử dụng dạng tham số của đường thẳng.
– Thể hiện đường thẳng dưới dạng tham số t
– Tham số DDA
– Thuật toán Bresenham
 Sử dụng dạng ẩn (implicit) của đường thẳng
– Chỉ cần kiểm tra điểm nằm ở bên nào của đường thẳng.
– Thuật toán điểm giữa.
– Cũng có thể dùng để vẽ đường tròn.

41 01/11/22 Ma Thị Châu - Bùi Thế Duy


Tóm tắt về vẽ đường thẳng

 Cài đặt các thuật toán vẽ đường thẳng.


– Thể hiện đường thẳng dưới dạng tham số t
– Tham số DDA
– Thuật toán Bresenham

 Cài đặt thuật toán điểm giữa vẽ đường tròn

42 01/11/22 Ma Thị Châu - Bùi Thế Duy

You might also like