1. Trang chủ
  2. » Công Nghệ Thông Tin

Đồ họa máy tính - Chương 3 pot

18 323 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 18
Dung lượng 641,23 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Ta nhận xét rằng, nếu tại bước thứ i ta xác định được dấu của pi thì sẽ xác định được điểm cần tô ở bước i+1.. Chẳng hạn như ở hình vẽ trên nếu xác định được điểm x,y, lấy đối xứng qua đ

Trang 1

Chương III: Một số thuật toán đồ họa cơ bản

I Vẽ đoạn thẳng

Xét đoạn thẳng y = m.x +b có hệ số góc 0<m<1, ta chọn điểm đầu và điểm cuối sao cho dx

=x2-x1>0 Làm sao để vẽ đoạn thẳng nối (x1,y1) (x2,y2) trong khi ta chỉ có thể ra lệnh cho màn hình vẽ từng điểm ảnh (kiểư như PutPixel của TP)?

Bản chất của quá trình này là sự rời rạc hóa và nguyên hóa một đối tượng thực (ở đây là đoạn thẳng thực - đoạn thẳng toán học) trên màn hình sao cho cuối cùng ta có tập các Pixel trông “giống” đối tượng nhất

Bản chất của các thuật toán vẽ đoạn thẳng là đi tìm tập các pixel liền nhau sao cho trông chúng “giống” với đoạn thẳng thực nhất

Thế nào là giống ?

- Liên tục (không đứt đoạn)

- Gần với đoạn thẳng thực (đoạn thẳng toán học) nhất

Hơn nữa, còn vấn đề tối ưu tốc độ, nghĩa là thuật toán phải tô các pixel trong thời gian nhanh nhất

Bài toán: ta phải vẽ đoạn thẳng y = m.x +b có hệ số góc 0<m<1, dx>0 (các trường hợp

khác đều có thể quy về trường hợp này)

Đầu tiên ta nhận xét, với các đoạn thẳng dạng này, nếu (xi, yi) là điểm ảnh đã vẽ được ở bước thứ i (điểm màu đen) thì

- chắc chắn xi+1 = xi +1

- yi+1 =yi hoặc yi+1 =yi +1

do đó điểm ảnh ở bước (i+1) tiếp theo chỉ có thể là 1 trong 2 trường hợp như hình vẽ Vấn

đề quy về việc chọn điểm nào trong hai điểm đó

x1 x2

y1

y2

Làm sao vẽ đoạn thẳng nối

1

2

xi

yi

xi+1 (xi+1, yi) (xi+1, yi+1)

Trang 2

1 Thuật toán DDA vẽ đoạn thẳng

Việc quyết định chọn yi+1 là yi hay yi+1 dựa vào phương trình của đoạn thẳng thực

Ta sẽ tính tọa độ của điểm y = m (xi +1) + b thuộc về đoạn thẳng thực, sau đó chọn điểm nào gần với nó nhất trong 2 điểm, nghĩa là

yi+1 = round(y) = round(m.xi+1 +b) Như vậy sẽ tốn 1 phép nhân và 1 phép cộng số thực Để cải thiện tốc độ, người ta dùng cách sau để khử phép nhân Nhận xét rằng:

yi = m.xi + b

yi+1 = m.xi+1 +b ⇒ yi+1 = yi + m

Ví dụ: Cho A(12,20) và B(22,27), ta có m=0.7

Begin

x < x 2 ?

Yes

No

End

x:=x+1; y:=y+m;

PutPixel(x,round(y));

m:=dy/dx ; x:=x1; y:=y1;

putpixel(x,round(y));

Lưu đồ thuật toán

DDA

(xi+1, y)

y

(xi+1, round(y))

(xi , yi)

Trang 3

i xi yi y

0 12 20 20

10 22 27 27

Thuật toán DDA vẽ đoạn thẳng

{ Vẽ đoạn thẳng trong trường hợp 0<m<1, dx >0}

uses crt,graph;

var

gd,gm:integer;

i,x1,y1,x2,y2,x:integer;

y,m:real;

Begin

gd:=detect; initgraph(gd,gm,'');

Randomize;

x1:=random(GetMaxX);

x2:=x1+random(GetMaxX-x1);

y1:=random(GetMaxY);

y2:=y1+random(x2-x1);

x:=x1; y:=y1;

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

putpixel(x,round(y),white);

for i:=x1 to x2 do

begin

x:=x+1;

putpixel(x,round(y),white);

end;

delay(1000);

Until Keypressed;

closegraph;

End

Trang 4

2 Thuật toán Bresenham vẽ đoạn thẳng

Trong hình vẽ (xi+1,y) là điểm thuộc đoạn thẳng thực, ta có: y = m(xi+1) + b Giả sử ở bước

i ta đã xác định được điểm (xi,yi)

Đặt

d1 = y – y1 ;

d2 = (yi +1) - y ;

Việc chọn điểm tiếp theo (xi+1, yi+1) là S hay P tùy thuộc vào việc d1 lớn hơn hay nhỏ hơn d2, nói cách khác là phụ thuộc vào dấu của (d1 – d2)

• Nếu d1 – d2 <0, ta sẽ chọn S, tức là yi+1 = yi

• Trường hợp còn lại: d1 – d2 >0, ta sẽ chọn P, tức là yi+1 = yi+1

Đặt

pi = dx (d1 – d2)

Thay d1 = y – y1 ; d2 = (yi +1) – y vào ta có

pi = dx (2y - 2yi -1)

Thay y = mxi+b = dy(xi+1)/dx + b vào ta có

pi = 2dx [dy(xi+1)/dx +b] – 2yidx –dx

= 2xidy – 2yidx +C

với C = 2dy + (2b-1)dx là hằng số

Ta nhận xét rằng, nếu tại bước thứ i ta xác định được dấu của pi thì sẽ xác định được điểm cần tô ở bước i+1

Làm sao để tính giá trị của pi ? ta dùng phương pháp “lũy tiến” như sau

Ta có:

pi+1 –pi = (2xi+1dy – 2yi+1dx +C) - (2xidy – 2yidx +C) = 2dy -2dx(yi+1 – yi)

• Nếu pi<0 thì điểm được chọn là S, tức là yi+1 = yi ⇒ pi+1 = pi +2dy

• Nếu pi>0 thì điểm được chọn là P, tức là yi+1 = yi+1 ⇒ pi+1 = pi +2dy -2dx

Cuối cùng, giá trị p0 được tính từ điểm ảnh đầu tiên (x0, y0) theo công thức sau

p0 = 2x0dy – 2y0dx + c

Thay giá trị của c vào, chú ý rằng điểm đầu (x0, y0) cũng thuộc đoạn thẳng thực nên y0 =

mx0 + b = x0dy/dx + b, suy ra

p 0 = 2dy -dx

tóm lại là:

xi+1

S

y

xi

yi+1

yi

d1

d2

(xi+1,y)

P

Trang 5

Ví dụ:

Cho A(12,20) và B(22,27), ta có

dx = 22 – 12 = 10 ; dy = 27 – 20 = 7;

c1 = 2dy = 14 ; c2 = 2(dy-dx) = -6;

p0 = 2Dy – dx = 4

i xi yi pi

0 12 20 4

1 13 21 -2

2 14 21 12

3 15 22 6

4 16 23 0

5 17 24 -6

6 18 24 8

7 19 25 2

8 20 26 -4

9 21 26 10

10 22 27 4

p2

Trang 6

Thuật toán Bresenham vẽ đoạn thẳng

{ Vẽ đoạn thẳng trong trường hợp 0<m<1, dx >0}

uses crt,graph;

var

gd,gm:integer;

i,x1,y1,x2,y2,dx,dy,p,c1,c2,x,y:integer;

Begin

gd:=detect; initgraph(gd,gm,'');

Randomize;

Repeat

x1:=random(GetMaxX);

x2:=x1+random(GetMaxX-x1);

y1:=random(GetMaxY);

y2:=y1+random(x2-x1);

{vẽ đoạn thẳng (x1,y1) (x2,y2) }

Begin

x < x2 ? Yes

No

End

x:=x+1;

PutPixel(x,y);

p:=2dy - dx ; c1=2dy;

c2=2(dy-dx);

x:=x1; y:=y1 ; putpixel(x,y);

p < 0 ?

Yes

p:=p+c1; p:=p + c2; y:=y+1;

No

Lưu đồ thuật toán

Bresenham

Trang 7

dx:=x2-x1;

dy:=y2-y1;

p:=2*dy - dx;

c1:=2*dy;

c2:=2*(dy-dx);

x:=x1;

y:=y1;

putpixel(x,y,white);

for i:=x1 to x2 do

begin

if p<0 then p:=p+c1 else

begin

p:=p+c2; y:=y+1;

end;

x:=x+1;

putpixel(x,y,white);

end;

delay(1000);

Until Keypressed;

closegraph;

End

3 Thuật toán MidPoint vẽ đoạn thẳng

Thuật toán này thực chất là 1 cách diễn giải khác của thuật toán Bresenham Ta lựa chọn

yi+1 là yi hay yi+1 bằng cách so sánh trung điểm của O của PS với đường thẳng thực

• Nếu O nằm phía dưới đường thẳng, ta chọn P

• Nếu O nằm phía trên, ta chọn S

Phương trình đường thẳng thực: Ax + By + C = 0

với A = y2 – y1; B = x1 – x2; C = x2y1 – x1y2 ;

Đặt F(x,y) = Ax + By + C, ta biết rằng

• F(x,y) <0 nếu điểm (x,y) nằm phía trên đường thẳng

• F(x,y) =0 nếu điểm (x,y) thuộc đường thẳng

• F(x,y) >0 nếu điểm (x,y) nằm phía dưới đường thẳng

vì vậy, vấn đề quy về việc xét dấu của pi = 2F(O) = 2F(xi +1,yi +1/2)

• Nếu pi <0 tức là O nằm phía trên đường thẳng ⇒ ta chọn S

xi+1

S

xi

yi+1

yi

P

O: điểm giữa

Trang 8

• Nếu pi >0 tức là O nằm phía dưới đường thẳng ⇒ ta chọn P

Làm sao để tính pi ? tương tự như thuật toán Bresenham, ta cũng dùng phương pháp “lũy tiến”, dùng giá trị ở bước trước pi để tính giá trị ở bước tiếp theo pi+1

Ta có: pi+1 – pi =2F(xi+1 +1,yi+1 +1/2) - 2F(xi +1,yi +1/2)

= 2[A(xi+1+1)+B(yi+1+1/2)+C] - 2[A(xi+1)+B(yi+1/2)+C]

= 2dy – 2dx(yi+1 – yi)

Như vậy

• Nếu pi <0 thì ta chọn yi+1 = yi , do đó pi+1 = pi +2dy

• Nếu pi >0 thì ta chọn yi+1 = yi+1 , do đó pi+1 = pi +2dy – 2dx

Cuối cùng, giá trị đầu p0 được tính như sau: nhận xét rằng điểm đầu (x0, y0) thuộc đoạn thẳng thực tức là Ax0 + By0 +C = 0

p0 = 2F(x0+1,y0+1/2) = 2[A(x0+1)+B(y0+1/2)+C]

= 2(Ax0 + By0 +C) + 2A +B = 2A+B

= 2dy –dx

II Vẽ đường tròn

Thuật toán MidPoint

Đầu tiên ta nhận xét rằng, do tính đối xứng của đường tròn nên ta chỉ cần vẽ được cung AB là cung 1/8 đường tròn, sau đó lấy đối xứng qua các trục và các đường phân giác

ta sẽ có cả đường tròn Chẳng hạn như ở hình vẽ trên nếu xác định được điểm (x,y), lấy đối xứng qua đường phân giác của góc phần tư thứ nhất ta thu được điểm (y,x), lấy đối xứng qua trục hoành ta thu được 2 điểm (y,-x) và (x,-y) Nếu ta chia thành 16,32 phần thì việc xác định tọa độ 15,31 điểm đối xứng còn lại sẽ rất khó Còn nếu chia thành 4 hay 2 phần thì số điểm lân cận cần phải loại trừ có thể nhiều hơn 2 điểm

(x,y)

(y,x)

(y, -x)

(x, -y) (-x, -y)

(-y, -x)

(-y, x)

(-x, y)

A

B

Trang 9

Gọi R là bán kính đường tròn, ta xuất phát từ điểm A (0,R) để vẽ cung AB Nhìn hình vẽ ta thấy, nếu (xi, yi) là điểm ảnh đã vẽ được ở bước thứ i thì điểm ảnh (xi+1, yi+1) ở bước tiếp theo chỉ có thể là S hoặc P, tức là

• xi+1 = xi + 1

• yi+1 ∈ {yi, yi-1}

Giống như thuật toán vẽ đoạn thẳng, ý tưởng chính để lựa chọn giữa S và P ở đây là căn cứ vào vị trí tương đối của điểm giữa M của SP với đường tròn Nếu M nằm bên trong đường tròn như hình vẽ thì ta sẽ chọn S vì nó gần điểm thực Q hơn so với P Ngược lại nếu M nằm ngoài đường tròn thì P sẽ được chọn

Đặt F(x,y) = x2 + y2 – R2 , các định lý toán học cho ta biết rằng

• F(x,y) <0 nếu điểm (x,y) nằm trong đường tròn

• F(x,y) =0 nếu điểm (x,y) nằm trên đường tròn

• F(x,y) >0 nếu điểm (x,y) nằm ngoài đường tròn

Đặt pi = F(M) = F(xi+1,yi – ½) ta có

• Nếu pi<0 tức là M nằm trong đường tròn, ta sẽ chọn S, tức là yi+1 = yi

• Nếu pi≥0 ta sẽ chọn P, tức là yi+1 = yi -1

Cách tính giá trị của pi cũng tương tự như ở thuật toán vẽ đoạn thẳng Ta có:

pi+1 – pi = F[xi+1+1,yi+1 – ½] - F[(xi+1,yi – ½)]

= [(xi+1+1)2 +(yi+1 – ½)2 - R2] - [(xi+1)2 +(yi – ½)2 - R2]

= 2xi +3+(yi+12 – yi2) – (yi+1 - yi)

Do đó

• Nếu pi <0 ta chọn yi+1 = yi ⇒ pi+1 = pi + 2xi +3

• Nếu pi ≥0 ta chọn yi+1 = yi-1 ⇒ pi+1 = pi + 2xi -2yi +5

Cuối cùng ta tính giá trị đầu p0 ứng với điểm A(0,R)

p0=F(x0+1,y0-1/2) = F(0,R-1/2) = 5/4 -R

yi

yi-1

xi+1

xi

P S

M: điểm giữa

Q(xi+1,y)

Trang 10

Thuật toán MidPoint vẽ đường tròn

Uses crt,graph;

Var

gd,gm,x,y,R,p,mau:integer;

Procedure PutPixel8(x,y,c:integer);

Begin

putPixel(x,y,c); putPixel(y,x,c); putPixel(y,-x,c); putPixel(x,-y,c);

putPixel(-x,-y,c); putPixel(-y,-x,c); putPixel(-y,x,c); putPixel(-x,y,c);

End;

Begin

gd:=detect; initgraph(gd,gm,'');

SetViewPort(GetMaxX div 2, GetMaxY div 2, GetMaxX,GetMaxY,false);

Randomize;

R :=100 + random(200);

Begin

x < y ? Yes

No

End

x:=x+1;

PutPixel(x,y);

p:=5/4 -R;

x:=0; y:=R ; PutPixel8(x,y);

p < 0 ?

Yes

p:=p+2x+3; p:=p+2(x-y); y:=y-1;

No

Lưu đồ thuật toán

MidPoint vẽ

đường tròn

Trang 11

mau:=random(GetMaxColor); {Vẽ đường tròn MidPoint màu ngẫu nhiên }

x:=0; y:=R;

PutPixel8(x,y,mau);

p:=1-R;

while (x<y) do

begin

if p<0 then p:=p+2*x+3

else

begin

p:=p+2*(x-y)+5;

y:=y-1;

end;

x:=x+1;

PutPixel8(x,y,mau);

end;

readkey;

End

VTại sao phải so sánh pi với 0 trong các thuật toán trên ? bản chất việc so sánh này là gì ?

VTrong thuật toán MidPoint, tại sao phải nhân F() với 2 khi gán cho pi trong công thức pi

= 2 F()

hiện ? (Gợi ý: 2 thuật toán kia cải thiện đáng kể số phép tính cần thực hiện, vì sao? )

thuật toán Bresenham ?

hoặc ít hơn 8 phần ?

lý thuyết là: p0 := 5/4 –R mà sửa thành p0:= 1- R ?

III Cắt xén (Clipping)

1 Thuật toán Cohen-Sutherland

Bài toán: giả thiết rằng cửa sổ hiển thị là một hình chữ nhật với các cạnh song song với các

trục tọa độ như hình vẽ Cho một đoạn thẳng bất kỳ, hãy xác định phần nào của nó nằm trong cửa sổ (tức là được hiển thị), phần nào nằm ngoài (bị che khuất)

Trang 12

Cách làm: đầu tiên ta nhận xét rằng một điểm P(x,y) nằm trong cửa sổ (được nhìn thấy) khi

và chỉ khi thỏa mãn đồng thời 2 điều kiện

xmax ≥ x ≥ xmin

ymax ≥ y ≥ ymin Ngược lại, nếu một trong 2 điều kiện bị vi phạm thì P nằm ngoài cửa sổ và sẽ không được hiển thị

Các đoạn thẳng chỉ có thể thuộc một trong những trường hợp sau:

• Hoàn toàn nằm trong cửa sổ, ví dụ như AB, khi đó cả 2 đầu mút đều nằm bên trong cửa sổ

• Hoàn toàn nằm ngoài cửa sổ (bị che toàn phần), ví dụ như CD, EF

• Chỉ một phần nằm trong cửa sổ và được hiển thị, ví dụ như KL và IJ

Đầu tiên, thuật toán Cohen – Sutherland dùng 4 đường thẳng chứa cạnh cửa sổ

chia mặt phẳng thành 9 phần Mỗi điểm A(x,y) thuộc mặt phẳng sẽ được gán mã 4 bit abcd theo cách sau:

• a=1 ⇔ y > ymax : A nằm phía trên cửa sổ

• b=1 ⇔ y < ymin: A nằm phía dưới cửa sổ

• c=1 ⇔ x > xmax: A nằm phía phải cửa sổ

• d=1 ⇔ x < xmin: A nằm phía trái cửa sổ

Khi đó, ta nhận xét rằng:

• đoạn thẳng sẽ hoàn toàn nằm trong cửa sổ nếu cả 2 đầu mút đều bằng 0000

• đoạn thẳng sẽ hoàn toàn nằm ngoài cửa sổ nếu kết quả phép AND của 2 đầu mút khác 0000

Thực vậy, nhận xét đầu là hiển nhiên Để minh họa cho nhận xét 2, xét đoạn thẳng EF:

E = 1010, F = 0010 ⇒ (E) AND (F) = (1010) and (0010) = 0010 ≠ 0

bit thứ 3 của cả 2 đầu mút E và F đều bằng 1, chứng tỏ chúng đều nằm bên phải cửa sổ, do

đó cả đoạn thẳng dĩ nhiên cũng nằm bên phải cửa sổ và sẽ không được hiển thị

Vấn đề còn lại là, nếu kết quả phép AND hai đầu mút bằng 0000, khi đó thuật toán sẽ tìm giao của đoạn thẳng với các biên của cửa sổ và xét từng phần của nó Ta ký hiệu 4 đường thẳng chứa cạnh cửa sổ là:

ymin

ymax

1001

0001

0101 0100

0000

0010

0110

J

I

J’

I’

A

B

F K

L K’

Trang 13

• đường 1: y = ymax

• đường 2: y = ymin

• đường 3: x = xmax

• đường 4: x = xmin

Khi đó nhìn vào mã của 2 đầu mút ta sẽ biết ngay đoạn thẳng đó cắt cạnh nào của cửa sổ Ví dụ:

Xét đoạn IJ

• Mã của I = 0100, bít thứ 2 =1 nên chắc chắn nó sẽ cắt đường 2

• Mã của J = 0001, bít thứ 4 =1 nên chắc chắn nó sẽ cắt đường 4

Xét đoạn KL

• Mã của L = 0100, bít thứ 3 =1 nên chắc chắn nó sẽ cắt đường 3

Việc xác định tọa độ giao điểm là rất đơn giản vì ta đã biết rõ 2 đầu mút Sau khi chia đoạn thẳng thành các đoạn, ta lặp lại thuật toán với mỗi đoạn chia cho đến khi kết thúc Ví dụ ta xét đoạn IJ

• Bước 1: kết quả phép and bằng 0 nhưng 2 đầu mút khác 0: tìm giao điểm với biên I’

• Bước 2: loại đoạn II’

• Bước 3: xét đoạn JI’ : tìm giao điểm J’

• Bước 4: loại đoạn JJ’ Kết thúc với đoạn I’J’ được hiển thị

2 Thuật toán Sutherland - Hodgman

Bài toán: ta cần cắt 1 đa giác bất kỳ Y vào trong cửa sổ là một đa giác lồi X

Cách làm: Ta sẽ duyệt lần lượt các cạnh của X, với mỗi cạnh đó ta lại xét lần lượt cạnh của

Y Kết quả sau khi xén với cạnh thứ i (của cửa sổ X) sẽ được dùng để xén với cạnh tiếp theo i+1 của X Quy tắc là:

ymin

2

J

I

J’

I’

3

K

L K’

4

0001

0100

0010

Trang 14

• nếu cạnh đang xét của Y đi từ trong cửa sổ ra ngoài (Pi-1 ở trong, Pi ở ngoài) thì chỉ giữ lại giao điểm I của Pi-1 Pi với cạnh đang xét của X

• nếu cạnh đang xét đi từ ngoài vào trong (tức là Pi-1 ở ngoài, Pi ở trong): giữ lại giao điểm I và Pi

• trường hợp cạnh ở ngoài hoàn toàn: loại bỏ

• trường hợp cạnh ở trong hoàn toàn: giữ lại Pi

Ví dụ

Đầu tiên ta xét cạnh UV của cửa sổ cắt là tam giác UVT

Cạnh đang xét (theo chiều vecto) Hướng đi Quyết định giữ lại

Ta thu được đa giác (theo thứ tự): P,B,Q,R,D,E,M,I,G,J như hình vẽ

Đoạn mã giả (pseudocode) sau minh họa cho thuật toán trên

t:=1

for i:=1 to n do {Đa giác cửa sổ X có n cạnh}

for j:=1 to m do {Đa giác bị cắt Y có m cạnh }

if k>n then k:=1 ;

if (Xj ở trong) then

A

B

P

Q

C

R

D

E

K

F

G

J

H

U

V

M

I

T

Trang 15

begin

if (Xk ở trong) then Yt := Yk

else Yt := giao điểm của XjXk với cạnh i của X t:=t+1;

end

else

if (Xk ở trong ) then

begin

Yt := giao điểm;

t:=t+1;

Yt := Xk ; t:=t+1;

end;

Vấn đề: cho tọa độ 1 điểm, làm sao biết điểm đó ở trong/ngoài đa giác lồi X ?

Bổ đề: nếu điểm đó nằm bên phải 1 cạnh nào đó của đa giác lồi X theo chiều dương thì nó

nằm ngoài X Nếu nó nằm bên trái tất cả các cạnh thì nó nằm bên trong X

Bổ đề: cho vector AB và điểm P(x,y), P nằm bên trái vector AB (như hình vẽ) nếu và chỉ

nếu (x 2 – x 1 )(y – y 1 ) – (y 2 – y 1 )(x – x 1 ) >0

Ta công nhận, không chứng minh bổ đề toán này

Vấn đề: cho tọa độ tập đỉnh của đa giác lồi X dưới dạng 1 danh sách có thứ tự (nghĩa là nếu

biết 1 đỉnh thì ta luôn biết 2 đỉnh kề của nó), làm sao xếp chúng lại “theo chiều dương” ?

Cách làm: Chọn đỉnh có hoành độ nhỏ nhất, ký hiệu là A như hình vẽ Gọi 2 đỉnh kề nó là

B,C trong đó xB < xC Thứ tự theo chiều dương sẽ là BAC Sau đó ta chỉ việc đi tới đỉnh tiếp theo C

Thật vậy, ta có thể thấy rõ khi nhìn hình vẽ Chỉ có 3 trường hợp:

• B,C cùng nằm bên phải đường thẳng đó

• B,C cùng nằm bên trái

chiều dương

bên phải

B(x2,y2) P(x,y)

Ngày đăng: 22/07/2014, 09:20

TỪ KHÓA LIÊN QUAN