DHMT - 9 - Cua so va cat hinh - HVHK - Thanh - 2023 - v2

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

ĐỒ HỌA MÁY TÍNH

GV: Hồ Ngọc Thanh

Chương 5. CỬA SỔ VÀ CẮT HÌNH

1. Cắt đoạn thẳng vào hình chữ nhựt


Cắt xén đoạn thẳng F vào hình chữ nhựt D:

Kết quả cắt xén là đoạn màu đỏ, được ký hiệu là: ClipD(F) = CD.
Hình chữ nhựt D và đoạn thẳng F có thể được biểu diễn như sau:
xmin ≤ x ≤ xmax
D = {(x, y) ∈ R2 | }
ymin ≤ y ≤ ymax
x = xA + (xB − xA )t
2
F = {(x, y) ∈ R | y = yA + (yB − yA )t }
0≤t≤1
Trong đó, (xmin, ymin) và (xmax, ymax) là 2 đỉnh xác định nên hình chữ nhựt,
còn (xA,yA) và (xB,yB) là tọa độ hai đầu mút của đoạn thẳng F.
Giải thuật có thể được mô tả như sau:
Bước 1: Tìm nghiệm của hệ bất phương trình
xmin ≤ xA + (xB − xA )t ≤ xmax
{ ymin ≤ yA + (yB − yA )t ≤ ymax (1)
0≤t≤1
Gọi nghiệm của hệ này là N.
Bước 2:
Nếu N = : Thì Giải thuật kết thúc với ClipD(F) = .

Trang 1
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

Ngược lại, N = [t1, t2] (t có giá trị từ t1 đến t2). Gọi C, D là 2 điểm cắt:
xC = xA + (xB - xA)t1 ; yC = yA + (yB - yA)t1
xD = xA + (xB - xA)t2 ; yD = yA + (yB - yA)t2
Giải thuật kết thúc với ClipD(F) = CD
Nhược điểm: Giải thuật trên cần phải tính toán nhiều trên các số thực.

2. Giải thuật Liang-Barsky


Giải thuật:
Bước 1: Tính các giá trị sau
∆x = xB − xA ∆y = yB − yA
P1 = -∆𝑥 Q1 = xA - xmin
P2 = ∆𝑥 Q2 = xmax - xA
P3 = -∆𝑦 Q3 = yA - ymin
P4 = ∆𝑦 Q4 = ymax - yA
Từ đây, hệ bất phương trình (1) có thể được viết lại theo tham số P và Q là:
P t ≤ Q k ; với k = 1,2,3,4
{ k (2)
0≤t≤1
Các bước tiếp giải bất phương trình này:
Bước 2:
+ Nếu k{1, 2, 3, 4} sao cho (Pk =0 và Qk <0, tức là đoạn thẳng song với
trục x hoặc y và nằm ngoài D): Thì hệ bất phương trình (2) vô nghiệm. Giải thuật
kết thúc với ClipD(F) = .
+ Ngược lại, chuyển sang bước 3.
Bước 3: Lúc này, k{1, 2, 3, 4} ta luôn có Pk  0 hoặc Qk  0.
K1 = {k | Pk > 0} K2 = {k | Pk < 0}
Qk Qk
U1 = min ({ | k ∈ K1 } ∪ {1}) U2 = max({ | k ∈ K 2 } ∪ {0})
Pk Pk

+ Nếu U1 < U2: Thì kết thúc với ClipD(F) = .


+ Ngược lại: Thì [U2, U1] chính là nghiệm của hệ bất phương trình (2)
(tương đương với [t1, t2] mà giải thuật ở mục 1 đã nêu). Gọi C và D là 2 điểm cắt:

Trang 2
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

xC = xA + ∆x. U1 ; yC = yA + ∆y. U1
xD = xA + ∆x. U2 ; yD = yA + ∆y. U2
Giải thuật kết thúc với ClipD(F) = CD

Giải thích: Bước 3 đã chuyển bài toán giải hệ bất phương trình (2) thành
quy trình tìm Min và Max để xác định ra 2 giá trị U1 và U2 như sau:
- Khi gọi K1 = {k | Pk > 0} và K2 = {k | Pk < 0} thì hệ bất phương trình (2)
có thể phân tích thành:
Qk
P t ≤ Qk ; ∀k ∈ K1 t≤; ∀k ∈ K1 (Nhóm 1)
{ k { Pk

(2) ⇔ { t≤1 ⇔ t≤1


P t ≤ Qk ; ∀k ∈ K 2 t≥
Qk
; ∀k ∈ K 2
{ k { Pk
(Nhóm 2)
t≥0
{ t≥0
t ≤ Qk/Pk ; ∀k ∈ K1
- Nhóm thứ nhất {
t≤1
Sẽ có nghiệm là: t ≤ min ({Qk/Pk | k ∈ K1 } ∪ {1}) = U1
t ≥ Qk/Pk ; ∀k ∈ K2
- Nhóm thứ hai {
t≥0
Sẽ có nghiệm là: t ≥ max ({Qk/Pk | k ∈ K 2 } ∪ {0}) = U2
Từ đó ta có:
t ≤ U1
(2) ⇔ { (3)
t ≥ U2
Nếu U1 < U2 thì hệ bất phương trình (3) sẽ vô nghiệm. Ngược lại, nghiệm
của nó sẽ là các giá trị t thuộc khoảng [U2, U1].

 Cài đặt giải thuật Liang-Barsky


Đầu vào:
- Thông tin của hình chữ nhựt R được truyền vào tham số R kiểu Crect.
- Tọa độ 2 điểm đầu mút được truyền vào tham số P1 và P2 kiểu CPoint.
- Tọa độ 2 điểm cắt được truyền ra bởi 2 biến trỏ P1_Out và P2_Out.
Đầu ra:

Trang 3
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

- Hàm sẽ trả về kết quả là false nếu kết quả xén là rỗng.
- Ngược lại, hàm trả về true, đồng thời tọa độ 2 điểm cắt được truyền ra
bởi 2 biến trỏ P1_Out và P2_Out.
bool LiangLineClip(CRect R, CPoint P1, Cpoint P2, CPoint* P1_Out,
CPoint* P2_Out)
{
float Dx = P2.x - P1.x, Dy = P2.y - P1.y;
float P[4] = { -Dx, Dx, -Dy, Dy };
float Q[4] = { P1.x - R.left, R.right - P1.x, P1.y - R.top, R.bottom - P1.y};
for (int i = 0; i < 4; i++)
{
if ((P[i] == 0) && (Q[i] < 0)) //Empty
return false;
}
float U1 = 1, U2 = 0;
for (int i = 0; i < 4; i++)
{
if (P[i] > 0)
{
if (U1 > (Q[i] / P[i]))
U1 = (Q[i] / P[i]);
}
else if (P[i] < 0)
{
if (U2 < (Q[i] / P[i]))
U2 = (Q[i] / P[i]);
}
}

Trang 4
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

if (U1 < U2)


return false;
else
{
P1_Out->x = int(P1.x + Dx*U1 + 0.5);
P1_Out->y = int(P1.y + Dy*U1 + 0.5);
P2_Out->x = int(P1.x + Dx*U2 + 0.5);
P2_Out->y = int(P1.y + Dy*U2 + 0.5);
return true;
}
}

3. Giải thuật Cohen-Sutherland

Các tình huống xén một đoạn thẳng vào trong một hình chữ nhựt:
- Đoạn AB: Cả 2 đầu mút của đoạn thẳng đều nằm trong hình chữ nhựt, thì
ClipD(F) sẽ là đoạn thẳng đã cho.
- Đoạn EF: Cả 2 đầu mút của đoạn thẳng đều nằm ở ngoài hình chữ nhựt,
và cùng nằm về một phía so với một cạnh nào đó của hình chữ nhựt, thì không
thể tồn tại phần giao giữa đoạn thẳng với hình chữ nhựt D. Vậy ClipD(F) = .

- Đoạn BC: Có một đầu mút của đoạn thẳng nằm ngoài hình chữ nhựt, thì
ClipD(F) sẽ là một phần đoạn thẳng đã cho, được tạo bởi một giao điểm của đoạn
thẳng với hình chữ nhựt và một đầu của đoạn thẳng nằm trong hình chữ nhựt.

Trang 5
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

- Đoạn CD: Cả 2 đầu mút của đoạn thẳng nằm ở ngoài hình chữ nhựt, song
có một phần của đoạn thẳng nằm trong hình chữ nhựt thì đoạn thẳng cắt hình chữ
nhựt D đúng 2 điểm. Vậy ClipD(F) sẽ là đoạn thẳng tạo bởi 2 điểm đó.

- Cả 2 đầu mút của đoạn thẳng nằm ở ngoài hình chữ nhựt, và không có
phần nào của đoạn thẳng nằm trong hình chữ nhựt thì ClipD(F) = .

Mã vùng gồm 4 bit cho 4 bên xung quanh hình chữ nhựt D như sau:
bit 3 bit 2 bit 1 bit 0
Trên Dưới Phải Trái
Bit nào có giá trị 1 thì đầu mút đoạn thẳng ở bên đó.
Mặt phẳng chứa hình chữ nhựt D được chia làm 9 phần và có mã vùng như
sau:
Hình chữ nhựt D

1001 1000 1010

0001 0000 0010

0101 0100 0110

Giải thuật:
Bước 1: Nếu mãvùng(A) = 0000 và mãvùng(B) = 0000: Thì ClipD(F) =
AB. Kết thúc giải thuật.
Bước 2: Nếu (mãvùng(A) & mãvùng(B))  0000: Thì ClipD(F) = . Kết
thúc giải thuật.
Lưu ý: & là phép AND trên bit, như 1101 & 1011 = 1001.
(mãvùng(A) & mãvùng(B))  0000  mãvùng(A)  0000 và mãvùng(B) 
0000  A và B cùng nằm bên ngoài hình chữ nhựt.
Kết quả phép AND khác 0000  tồn tại ít nhất một bit thứ i nào đó bằng 1
cho cả mãvùng(A) và mãvùng(B)  A và B nằm cùng một phía của hình chữ nhựt.
Bước 3: Nếu mãvùng(A) = 0000: Thì hoán đổi tọa độ A với B.
 A là đầu mút nằm bên ngoài hình chữ nhựt.
Bước 4: Nếu xA = xB: (AB là một đoạn thẳng đứng)

Trang 6
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

B
B

A
- Đặt điểm C là giao điểm của AB với hình D như sau:
xC = xA
Nếu (mãvùng(A) & 1000) = 1000 (A ở vùng trên): Thì yC = ymax.
Ngược lại (A ở vùng dưới): Thì yC = ymin.
- Đặt điểm D (có thể nằm trong hoặc giao điểm) như sau :
xD = xA
Nếu mãvùng(B) = 0000 (B nằm trong) : Thì yD = yB.
Ngược lại:
+ Nếu (mãvùng(B) & 1000) = 1000 (B ở vùng trên): Thì yD =
ymax.
+ Ngược lại (B ở phía dưới): Thì yD = ymin.
ClipD(AB) = CD, kết thúc giải thuật.
Bước 5: Ta có xA  xB và A nằm bên ngoài hình chữ nhựt.
+ Nếu (mãvùng(A) & 0001) = 0001 (A ở vùng trái): Thì thay thế giá trị của
A bởi giao điểm của AB và cạnh trái nối dài của hình chữ nhựt.
+ Nếu (mãvùng(A) & 0010) = 0010 (A ở vùng phải): Thì thay thế giá trị
của A bởi giao điểm của AB và cạnh phải nối dài của hình chữ nhựt.
+ Nếu (mãvùng(A) & 0100) = 0100 (A ở vùng dưới): Thì thay thế giá trị
của A bởi giao điểm của AB và cạnh dưới nối dài của hình chữ nhựt.
+ Nếu (mãvùng(A) & 1000) = 1000 (A ở vùng trên): Thì thay thế giá trị
của A bởi giao điểm của AB và cạnh trên nối dài của hình chữ nhựt.
Tính lại mã vùng của điểm A mới, rồi quay lại thực hiện Bước 1.

 Tìm giao điểm: dựa trên phương trình đoạn thẳng và phương trình biểu
diễn cạnh của hình chữ nhựt.
Chẳng hạn:
y − yA x − xA y − yA x − xA
- Phương trình AB: = hoặc =
yB − yA xB − xA ∆y ∆x

Trang 7
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

- Phương trình cạnh trái: x = xmin


Suy ra, tọa độ giao điểm của AB với cạnh trái nếu có là:
∆𝑦
(xmin, (xmin - xA) + yA )
∆𝑥
Tương tự tính tọa độ giao điểm với các cạnh còn lại của hình chữ nhựt.

 Tính mã vùng của một điểm: Toán tử OR trên bit cho phép bật một bit
trong một chuỗi bit.

 Cài đặt hàm tính mã vùng:


Ta xác định mã vùng của điểm P(xp, yp) như sau:
1 nếu xp < xmin (ở bên trái)
bit 0 = {
0 nếu ngược lại
1 nếu xp > xmax (ở bên phải)
bit 1= {
0 nếu ngược lại
1 nếu yp < ymin (ở bên dưới)
bit 2 = {
0 nếu ngược lại
1 nếu yp > ymax (ở bên trên)
bit 3 = {
0 nếu ngược lại
Đầu vào: x, y chứa giá trị tọa độ của điểm P; xmin, ymin, xmax, ymax biểu
diễn tọa độ của hình chữ nhựt D.
Đầu ra: Một byte có 4 bit đầu chứa mã vùng của P và 4 bit sau bằng 0.
unsigned char mavung(float x, float y)
{
unsigned char m = 0; //m = 00000000
if (x < xmin)
m = m | 1; //tức m or 00000001, đặt bit 0 bằng 1
else
if (x > xmax)
m = m | 2; //tức m or 00000010, đặt bit 1 bằng 1
if (y < ymin)
m = m | 4; //tức m or 00000100, đặt bit 2 bằng 1
else

Trang 8
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

if (y > ymax)
m = m | 8; //tức m or 00001000, đặt bit 3 bằng 1
return m;
}

 Khi cạnh của hình chữ nhựt tạo với trục hoành một góc 
Chúng ta quay đoạn thẳng và hình chữ nhựt để có cạnh hình chữ nhựt song
song với trục tọa độ.
Bước 1: Quay hình chữ nhựt D và đoạn thẳng AB một góc - để được D'
và A'B'.
Bước 2: Tìm ClipD'(A'B')
Nếu ClipD'(A'B') = : Thì kết quả ClipD(AB) = .
Ngược lại: Thì ClipD'(A'B') = C'D'. Tiến hành quay C'D' một góc , chúng
ta được CD. Vậy ClipD(AB) = CD.

Trang 9
ĐỒ HỌA MÁY TÍNH
GV: Hồ Ngọc Thanh

BÀI TẬP
1. Hình chữ nhựt có xmin = 15, ymin = 25, xmax = 215, ymax = 175. Đoạn thẳng có A
(220, 10), B (10, 180). Tìm đoạn cắt theo giải thuật
a) Tổng quát
b) Liang-Barsky
c) Cohen-Sutherland

Trang 10

You might also like