TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO BÀI TẬP LỚN
MƠN ĐỒ HỌA MÁY TÍNH
Đề tài
CÀI ĐẶT HÀM VẼ ĐƯỜNG THẲNG BẰNG DDA, BRESENHAM,
MIDPOINT ĐI QUA HAI ĐIỂM NHẬP TỪ BÀN PHÍM.
SỬ DỤNG CÁC PHÉP TỊNH TIẾN, PHÉP QUAY, CO DÃN, ĐỐI XỨNG VÀ
PHÉP KẾT HỢP
Nhóm thực hiện: Nhóm 18
Giảng viên: Th.s Nguyễn Thị Cẩm Ngoan.
Hà Nội, ngày 25 tháng 2 năm 2012
1
TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO BÀI TẬP LỚN
MƠN ĐỒ HỌA MÁY TÍNH
Đề tài: Đề tài
CÀI ĐẶT HÀM VẼ ĐƯỜNG THẲNG BẰNG DDA, BRESENHAM,
MIDPOINT ĐI QUA HAI ĐIỂM NHẬP TỪ BÀN PHÍM.
SỬ DỤNG CÁC PHÉP TỊNH TIẾN, PHÉP QUAY, CO DÃN, ĐỐI XỨNG VÀ
PHÉP KẾT HỢP
Nhóm thực hiện: Nhóm 18
Thành viên trong nhóm:
1. Phạm Văn Điệp
2. Lê Đức Nguyên
3. Hồ Viết Trường
Hà Nội, ngày 25 tháng 2 năm 2012
2
MỤC LỤC
IV.PHẦN CODE.................................................................................................................................37
1. Vẽ đường thẳng bằng DDA.........................................................................................................37
2. Vẽ đường thẳng bằng bresenham................................................................................................38
3. Vẽ đường thẳng bằng Midpoint..................................................................................................40
4. Hàm tịnh tiến...............................................................................................................................42
5. Hàm co dãn..................................................................................................................................42
6. Hàm đối xứng qua điểm..............................................................................................................42
7. Hàm đối xứng qua đường thẳng y = ax + b.................................................................................43
8. Hàm quay....................................................................................................................................43
3
LỜI NÓI ĐẦU
Như chúng ta đã biết, việc vẽ một đường thẳng bất ký là phần đơn giản nhất trong quá
trình vẽ một hình cầu kỳ và phức tạp hơn. Nhất là vẽ một đa giác bất kỳ thì việc vẽ một đoạn
thẳng đi qua hai điểm bất kỳ lại càng có ý nghĩa quan trọng hơn. Khi đã vẽ và thực hiện
được các phép biến đổi cho đoạn thẳng thì việc vẽ đa giác sẽ dễ hơn rất nhiều.
Bản báo cáo này gồm có 5 phần chính, trong đó 4 phần đầu nói về q trình khảo sát,
xây dựng và chạy thử cũng như phần code của các hàm. Phần cuối là tài liệu tham khảo.
4
I. KHẢO SÁT.
1. Vẽ đường thẳng.
Có ba cách vẽ, cần phải xác định tất cả các Trường hợp khi vẽ:
• Theo DDA: Cách vẽ này sẽ chia theo hai trường hợp hệ số góc nằm trong
khoảng từ -1 đến 1 và hệ số góc nằm ngồi khoảng đó (ngồi ra cịn trường
hợp hệ số góc khơng xác định nữa, ta sẽ xét sau).
• Theo Bresenham: Cách vẽ này ta chia thành bốn trường hợp tương ứng với các
đường thẳng tăng nhanh, tăng chậm, giảm nhanh và giảm châm. Ngoài ra cũng
như DDA ta sẽ xét trường hợp hệ số góc khơng xác định sau.
• Theo Midpoint: Giống như Bresenham.
trường hợp hệ số góc khơng xác định ta sẽ xét chung cho tất cả các trường hợp.
2. Các phép biến đổi.
Có năm phép biến đổi cần thực hiện:
• Phép tịnh tiến: tịnh tiến theo một vecter cho trước.
• Phép quay: quay quanh một tâm quay bất kỳ với một góc quay nhập từ bàn
phím.
• Phép co dãn: co dãn theo một hệ số bất kỳ nhập từ bàn phím. Ý tường phần
này là thay vì co dãn một đoạn thẳng thì ta nên co dãn một tam giác hoặc hình
đa giác bất kỳ để thấy được sự thay đổi rõ nét.
• Phép đối xưng: ta sẽ chia phép đối xưng thành hai trường hợp là đối xứng qua
tâm và đối xưng qua đường thẳng có phương trình tổng qt là y = ax + b với
a, b nhập từ bàn phím.
• Phép kết hợp: là kết hợp tất cả các phép biến đổi trên lại với nhau, sẽ có 24
trường hợp của phép kết hợp.
5
II.
PHÂN TÍCH.
1. Vẽ đường thẳng.
a) Vẽ đường thẳng theo DDA
Như chúng ta đã biết, tất cả các đường thẳng đề có một hệ số góc “m” riêng của nó. Khi
viết dưới dạng y = ax + b thì hệ số góc của đường thẳng cũng chính là hệ số “a”.
Dựa vào hệ số góc thì ta sẽ có 6 trường hợp để vẽ đường thẳng bao gồm:
•
m <-1
•
-1 <= m < 0
•
m=0
•
0 < m <= 1
•
m>1
•
m khơng xác định
Tuy nhiên, khi vẽ đường thẳng ta có thể chia thành ba cách để vẽ đường thẳng như sau:
• Trường hợp 1: Ta vẽ hệ số góc -1 <= m <=1. sở dĩ có thể gộp ba trường hợp trên lại
với nhau là vì tại vịng lặp ta để tăng theo x (do số điểm x nhiều hơn số điểm y khi vẽ).
Trường hợp này ứng với các đường thẳng tăng chậm, giảm chậm và đường thẳng song song
với chục Ox.
• Trường hợp 2: Ta vẽ hệ số góc m <= -1 || m >=1. Trường hợp này ta không thể tăng
theo x được mà phải tăng theo y vì nếu tăng theo x thì số điểm y cần vẽ sẽ khơng đủ (VD:
khi x tăng từ 10 đến 20 mà y lại cần tăng từ 10 lên 200. như vậy thì số điểm x của vòng lặp
sẽ chỉ là 10 điểm, tương ứng với điểm y cũng chỉ là 10 điểm, trong khi số điểm y ta cần vẽ
thực sự là 200-10=190 điểm, điều đó dẫn đến vẽ đường thẳng sai). Trường hợp này tương
ứng với các đường thẳng tăng nhanh và giảm nhanh.
• Trường hợp 3: Đây là trường hợp với hệ số góc chưa xác định (đường thẳng song
song với chục Oy). Trong trường hợp này, vì x1 = x2 nên ta sẽ cho vòng lặp lặp theo y.
*) Trường hợp 3 ta không chỉ áp dụng cho DDA mà cịn cho cả bresenham và midpoint
nữa. Vì thế chúng ta chỉ cần xây dựng một hàm cho trường hợp này để vẽ cho cả DDA,
bresenham và midpoint.
Sau đây ta sẽ xét từng trường hợp của hàm DDA khi vẽ:
i. Trường hợp 1 (-1 <= m <= 1)
Với thuận toán DDA nói chung, việc quyết định chọn y i+1 là yi hay yi + 1 (ở trường
hợp 2 là xi+1), dựa vào phường trình của đoạn thẳng y = mx + b. Nghĩa là ta sẽ tính tọa độ
của điểm (xi+1,y) thuộc về đoạn thẳng thực. Tiếp đó, yi+1 sẽ là giá trị khi làm tròn giá trị
của tung độ y.
Như vậy ta có thể viết gọn như sau:
y = m(xi + 1) + b
yi+1 = round(y)
6
Nếu tính trực tiếp giá trị thực y ở mỗi bước từ phương trình y = mx + b thì phải cần
một phép toán nhân và một phép toán cộng số thực. để cải thiện tốc độ, ta có thể tính giá
trị thực của ysau theo ytrước.
Lúc đó: ysau = ytrước + m
Lưu đồ của thuật toán theo trường hợp 1
Begin
m = dy/dx;
x = x1;
y = y1;
Putpixel(x,round(y),color);
x <= x2
no
yes
x = x + 1;
y = y + m;
Putpixel(x,y,color);
end
ii. Trường hợp 2 (m < -1 hoặc m > 1)
Trường hợp này cơ bản cũng giống như trường hợp 1 nhưng việc tính tốn có phần
ngược lại (do vịng lặp ta khơng lặp theo x mà lặp theo y).
Do là lặp theo y nên:
yi+1 = yi + 1;
xi+1 = xi + 1/m;
Dựa vào hai đều kiện này t có lưu đồ thuật tốn như sau:
7
Begin
m = dy/dx;
x = x1;
y = y1;
Putpixel(round(x),(y),color);
y < y2
no
yes
y = y + 1;
x = x + 1/m;
Putpixel(x,y,color);
end
Về cơ bản ngoài vịng lặp và việc tăng x, y có phần ngược nhau thì nó cũng khơng
khác so với Trường hợp 1 là bao nhiêu.
iii. Trường hợp 3 (hệ số góc khơng xác định)
*) Như đã nói ở trên, trường hợp này ở ba cách vẽ DDA, bresenham và midpoint đều
giống nhau cả nên ta sẽ không cần phải viết lại mà viết một hàm dùng cho cả ba cách vẽ.
Đây là trường hợp x1 = x2 nên ta chỉ cần vòng lặp theo y từ y1 đến y2 là được (y1 <
y2)
Lưu đồ của trường hợp 3 như sau:
8
Begin
x = x1;
y = y1;
Putpixel(x,y,color);
y < y2
no
yes
y = y + 1;
Putpixel(x,y,color);
end
• Sau khi đã xét xong tất cả các trường hợp của DDA thì hàm chính của DDA ta
chỉ cần gọi lại các hàm con đã viết là được.
b) Vẽ đường thẳng theo Bressenham
Ý tưởng của thuật toán bresenham trong việc chọn y i+1 là yi hay yi + 1 là dựa vào
trung điểm của hai điểm sẽ chọn này (nếu là giảm nhanh và tăng nhanh hoặc hệ số
góc khơng xác định thì sẽ tăng theo y).
Cũng tương tự như DDA, t cũng có 6 Trường hợp để vẽ đường thẳng nhưng cũng
chỉ cần xây dựng 5 hàm để vẽ đường thẳng. Một trong ba hàm là giống với DDA đã
được xây dựng trong “Trường hợp 3” ở trên.
i. Trường hợp 1 (0 <= m <=1)
Gọi (xi + 1, y) là điểm thuộc đoạn thẳng. Ta có y = m(xi + 1) + b.
Đặt:
d1 = y – y1
d2 = (yi + 1) – y
Ta xét tất cả các vị trí tương đối của y so với yi và yi+1, việc chọn yi+1 là yi hay yi + 1 phụ
thuộc vào việc so sánh d1 và d2 (hay nói cách khác dựa vào dấu của d1 – d2).
Nếu d1 – d2 < 0, sẽ chọn điểm yi+1 là yi
•
Nếu d1 – d2 >= 0, chọn điểm yi+1 là yi + 1
•
9
Xét pi = dx(d1 – d2) = dx(2y – 2yi – 1)
pi = dx(2(m(xi + 1) + b) - 2yi – 1)
Thay m = dy/dx vào phương trình trên ta được:
pi = 2dyxi – 2dxyi + c, với c = 2dy + (2b – 1)dx.
Vì dx > 0 nên dấu của biểu thức phụ thuộc hoàn tàn vào dấu của d 1 – d2. Đây cũng chính
là dấu của pi. Nghĩa là tại bước này ta đã xác định được p i tại điểm đầu tiên cần vẽ. Việc tiếp
theo ta chỉ cần tính pi sao cho nhanh nhất.
Ta có:
Pi+1 – pi = (2dyxi+1 – 2dxyi+1 + c) – (2dyxi – 2dxyi + c)
<=> Pi+1 – pi = 2dy(xi+1 - xi) – 2dx(yi+1 - yi)
<=> Pi+1 – pi = 2dy – 2dx(yi+1 – yi), do xi+1 = xi + 1
Từ đây ta có thể suy ra cách tính pi+1 từ pi như sau:
Nếu pi < 0 thì pi+1 = pi + 2dy do ta chọn yi+1 = yi
Ngược lại thì pi+1 = pi + 2(dy – dx) do ta chọn yi+1 = yi + 1
Giá trị của p0 được tính từ điểm đầu tiên (x0, y0) theo cơng thức:
p0 = 2dyx0 – 2dxy0 + c = 2dyx0 – 2dxy0 + 2dy – (2b - 1)dx
Do (x0, y0) là điểm nguyên thuộc về đoạn thẳng nên ta có:
Y0 = mx0 + b = (dy/dx)x0 + b. Thế vào phương trình trên ta suy ra: p0 = 2dy – dx.
Lưu đồ thuật toán bresenham.
10
Begin
p = 2dy-dx;
const1=2dy;
const2=2(dy-dx);
x=x1; y=y1
putpixel(x,y,color);
no
x
yes
p<0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
x = x + 1;
Putpixel(x,y,color);
end
ii. Trường hợp 2 (m >1)
Tương tự như Trường hợp 1. Ta gọi (x, yi + 1) là điểm thuộc đoạn thẳng.
Có x = (yi + 1)/m -b
Đặt:
d1 = x – xi
d2 = (xi + 1) –x
xét pi = dy(d1 – d2) = dy(2x – 2xi – 1) =dy(2((yi + 1)/m – b) -2xi – 1)
thay m = dy/dx vào phương trình trên ta được:
pi = 2dxyi – 2dyxi + c
trong đó c = 2dx – dy(2b + 1)
ta có:
pi+1 – pi = (2dxyi+1 – 2dyxi+1 + c) – (2dxyi – 2dyxi + c)
pi+1 – pi = 2dx + 2dy(xi – xi+1)
11
vì yi+1 = yi + 1
từ đây ta có thể suy ra cách tính pi+1 từ pi như sau:
•
Nếu pi < 0 thì pi+1 = pi + 2dx do ta chọn xi+1 = xi
•
Ngược lại thì pi+1 = pi + 2(dx – dy) do lúc này ta chọn xi+1 = xi + 1
Tiếp theo ta tính giá trị p 0. Giá trị này được tính từ điểm vẽ đầu tiên (x 0, y0) theo công
thức:
P0 = 2dxy0 – 2dyx0 + c
Tương tự như cách tính trong Trường hợp 1, ca sẽ tính được: p0 = 2dx – dy
Lưu đồ thuật toán bresenham trong Trường hợp 2 như sau:
Begin
p = 2dx – dy;
const1=2dx;
const2=2(dx - dy);
x=x1; y=y1
putpixel(x,y,color);
no
y < y2
yes
p<0
no
yes
p=p+const1;
p=p+const2;
x = x + 1;
y = y + 1;
Putpixel(x,y,color);
end
iii.
Trường hợp 3 (-1 <= m <0)
Trường hợp 3 khơng có m = 0 là vì Trường hợp m = 0 ta đã xây dựng trong
Trường hợp 1 rồi nên không cần phải xây dựng lại nữa.
Trường hợp này cũng xây dựng tương tự như trường hợp 1, tuy nhiên vì đây là hệ
12
số góc nhỏ hơn -1 nên ta sẽ thay vì việc ta tăng y++ sẽ là việc ta giảm y--. Cụ thể ta có
q trình xây dựng hàm như sau:
Gọi (xi + 1, y) là điểm thuộc đoạn thẳng. Ta có y = m(xi + 1) + b.
Đặt:
d1 = yi – y
d2 = y – yi – 1
Ta xét tất cả các vị trí tương đối của y so với y i và yi+1, việc chọn yi+1 là yi hay yi - 1 phụ
thuộc vào việc so sánh d1 và d2 (hay nói cách khác dựa vào dấu của d1 – d2).
Nếu d1 – d2 < 0, sẽ chọn điểm yi+1 là yi
•
Nếu d1 – d2 >= 0, chọn điểm yi+1 là yi – 1
•
Xét pi = dx(d1 – d2) = dx(2yi – 2y – 1)
pi = dx(2yi – 2(m(xi + 1) + b) – 1)
Thay m = dy/dx vào phương trình trên ta được:
pi = 2dxyi – 2dyxi + c, với c = dx – (b+1)dy.
vì dx > 0 nên dấu của biểu thức phụ thuộc hoàn tàn vào dấu của d 1 – d2. Đây cũng chính
là dấu của pi. Nghĩa là tại bước này ta đã xác định được p i tại điểm đầu tiên cần vẽ. Việc tiếp
theo ta chỉ cần tính pi sao cho nhanh nhất.
Ta có:
Pi+1 – pi = (2dxyi+1 – 2dyxi+1 + c) – (2dxyi – 2dyxi + c)
<=> Pi+1 – pi = 2dy(xi - xi+1) – 2dx(yi+1 - yi)
<=> Pi+1 – pi = –2dy – 2dx(yi+1 – yi), do xi+1 = xi + 1
Từ đây ta có thể suy ra cách tính pi+1 từ pi như sau:
Nếu pi < 0 thì pi+1 = pi – 2dy do ta chọn yi+1 = yi
Ngược lại thì pi+1 = pi –2(dx + dy) do ta chọn yi+1 = yi – 1
Giá trị của p0 được tính từ điểm đầu tiên (x0, y0) theo cơng thức:
p0 = 2dxy0 – 2dyx0 + c = 2dxy0 – 2dyx0 + dx – (b+1)dy
Do (x0, y0) là điểm nguyên thuộc về đoạn thẳng nên ta có:
y0 = mx0 + b = (dy/dx)x0 + b. Thế vào phương trình trên ta suy ra: p0 = dx – 2dy.
Lưu đồ thuật toán bresenham.
13
Begin
p = dx-2dy;
const1=-2dy;
const2=-2(dy+dx);
x=x1; y=y1
putpixel(x,y,color);
no
x
yes
p<0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
x = x + 1;
Putpixel(x,y,color);
end
iv. Trường hợp 4 (m < -1)
Tương tự như trường hợp 2. Tuy nhiên thay vì ta tăng x++ thì ta sẽ giảm y--.
Ta gọi (x, yi + 1) là điểm thuộc đoạn thẳng.
Có x = (yi + 1)/m -b
Đặt:
d1 = xi – x
d2 = x – xi + 1
xét pi = dy(d1 – d2) = dy(2xi – 2x + 1) =dy(2 xi – 2((yi + 1)/m – b) – 1)
thay m = dy/dx vào phương trình trên ta được:
pi = 2dyxi – 2dxyi + c
trong đó c = dy + 2dx(b - 1)
ta có:
pi+1 – pi = (2dyxi+1 – 2dxyi+1 + c) – (2dyxi – 2dxyi + c)
pi+1 – pi = -2dx + 2dy(xi+1 – xi)
14
vì yi+1 = yi + 1
từ đây ta có thể suy ra cách tính pi+1 từ pi như sau:
•
Nếu pi < 0 thì pi+1 = pi - 2dx do ta chọn xi+1 = xi
•
Ngược lại thì pi+1 = pi - 2(dy + dx) do lúc này ta chọn xi+1 = xi - 1
Tiếp theo ta tính giá trị p 0. Giá trị này được tính từ điểm vẽ đầu tiên (x 0, y0) theo công
thức:
P0 = 2dyx0 – 2dxy0 + c
Tương tự như cách tính trong trường hợp 1, ca sẽ tính được: p0 = -2dx + dy
Lưu đồ thuật toán bresenham trong trường hợp 2 như sau:
Begin
p = -2dx + dy;
const1=-2dx;
const2=-2(dx + dy);
x=x1; y=y1
putpixel(x,y,color);
no
y < y2
yes
p<0
no
yes
p=p+const1;
p=p+const2;
x = x + 1;
y = y + 1;
Putpixel(x,y,color);
end
c) Vẽ đường thẳng theo Midpoint
Cũng tương tự như thuật toán bresenham, thuật toán midpoint cũng dựa trên tính
chất trung điểm để xây dựng thật tốn. Thuật toán midpoint đưa ra cách chọn y i+1 là yi
hay yi+1 bằng cách so sánh điểm thực Q(xi+1, y) với chung điểm midpoint là chung
15
điểm của S(xi+1,yi) và P(xi+1,yi+1).
i.
Trường hợp 1 (0 <= m <=1)
Ta có:
a.
Nếu điểm Q nằm dưới điểm midpoint ta chọn điểm S.
b.
Nếu ngược lại ta chọn điểm P.
Ta có dạng tổng quát của phương trình đường thẳng: Ax + By + C = 0
Với A =y2– y1, B = -(x2 – x1), C = x2y1 – x1y2
Đặt F(x,y) = Ax + By + C, ta có
• Nếu F(x,y) < 0 thì (x,y) nằm phía trên đưởng thẳng
• Nếu F(x,y) = 0 thì (x,y) thuộc đường thẳng
• Nếu F(x,y) > 0 thì (x,y) nằm phía dưới đường thẳng
Lúc này việc xét dấu của pi = 2F(midpiont) = 2F(xi + 1, yi + 1/2) sẽ cho chúng ta biết
điểm pi+1 cần chọn là điểm nào.
Pi < 0, chọn yi+1 là yi
Pi >=0, chọn yi+1 là yi + 1
Mặt khác ta xét:
Pi+1 – pi = 2F(xi+1+1,yi+1+1/2)–2F(xi+1,yi+1/2)=2A+2B(yi+1–yi)=2dy–2dx(yi+1–yi)
Vậy:
o Nếu pi < 0, pi+1 = pi do ta chọn yi+1 = yi
o Nếu pi < 0, pi+1 = pi + 1 do ta chọn yi+1 = yi + 1
Ta tính giá trị p0 ứng với điểm ban đầu (x 0, y0) với nhận xét rằng điểm (x 0, y0) là điểm
thuộc về đoạn thẳng, tức là Ax0 + By0 + C = 0.
p0 = 2F(x0 + 1, y0 + ½) = 2(A(x0 + 1) + B(y0 + ½) + C)
p0 = 2(Ax0 + By0 + C) + 2A + B = 2A + B = 2dy – dx
Dễ nhận thấy rằng thuật toán midpoint cho kết quả cũng giống như thuật toán
bresenham.
Lưu đồ của thuật toán:
16
Begin
p = 2dy-dx;
const1=2dy;
const2=2(dy-dx);
x=x1; y=y1
putpixel(x,y,color);
no
x
yes
p<0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
x = x + 1;
Putpixel(x,y,color);
end
ii.
Trường hợp 2 (m > 1)
Cũng đặt tương tự như trường hợp 1, nhưng ở trường hợp hai ta lựa chọn x chứ không
phải lựa chọn y. Việc lựa chọn xi+1 là xi hay xi + 1 cũng được dựa vào vị trí trung điểm của y i
và yi + 1, nó có phần ngược lại với Trường hợp 1.
Lúc này việc xét dấu của pi = 2F(midpiont) = 2F(xi + 1/2, yi + 1) sẽ cho chúng ta biết
điểm pi+1 cần chọn là điểm nào.
Pi < 0, chọn xi+1 là xi + 1
Pi >=0, chọn xi+1 là xi
Mặt khác ta xét:
pi+1 – pi = 2F(xi+1+1/2,yi+1+1)–2F(xi+1/2,yi+1)=2A(xi+1 - xi)+2B = 2dy(xi+1 - xi)–2dx
Vậy:
o Nếu pi < 0, pi+1 = pi + 1 do ta chọn xi+1 = xi + 1
o Nếu pi < 0, pi+1 = pi do ta chọn xi+1 = xi
17
Ta tính giá trị p0 ứng với điểm ban đầu (x 0, y0) với nhận xét rằng điểm (x 0, y0) là điểm
thuộc về đoạn thẳng, tức là Ax0 + By0 + C = 0.
p0 = 2F(x0 + 1/2, y0 + 1) = 2(A(x0 + 1/2) + B(y0 + 1) + C)
p0 = 2(Ax0 + By0 + C) + A +2 B = A + 2B = dy – 2dx
Ta có lưu đồ của thuật tốn:
Begin
p = dy - 2dx;
const1 = -2dx;
const2 = 2(dy-dx);
x = x1; y = y1
putpixel(x,y,color);
no
y
yes
p>0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
y = y + 1;
Putpixel(x,y,color);
end
iii.
Trường hợp 3 (-1 <= m < 0)
Ta có:
a. Nếu điểm Q nằm dưới điểm midpoint ta chọn điểm S.
b. Nếu ngược lại ta chọn điểm P.
Ta có dạng tổng qt của phương trình đường thẳng: Ax + By + C = 0
Với A =y2– y1, B = -(x2 – x1), C = x2y1 – x1y2
Đặt F(x,y) = Ax + By + C, ta có
• Nếu F(x,y) < 0 thì (x,y) nằm phía trên đưởng thẳng
18
• Nếu F(x,y) = 0 thì (x,y) thuộc đường thẳng
• Nếu F(x,y) > 0 thì (x,y) nằm phía dưới đường thẳng
Lúc này việc xét dấu của pi = 2F(midpiont) = 2F(xi + 1, yi - 1/2) sẽ cho chúng ta biết
điểm pi+1 cần chọn là điểm nào.
Pi < 0, chọn yi+1 là yi
Pi >=0, chọn yi+1 là yi + 1
Mặt khác ta xét:
Pi+1 – pi = 2F(xi+1+1,yi+1-1/2)–2F(xi+1,yi-1/2)=2A+2B(yi+1–yi)=2dy–2dx(yi+1–yi)
Vậy:
o Nếu pi < 0, pi+1 = pi + 2dy do ta chọn yi+1 = yi
o Nếu pi < 0, pi+1 = pi + 2(dy + dx) do ta chọn yi+1 = yi - 1
Ta tính giá trị p0 ứng với điểm ban đầu (x 0, y0) với nhận xét rằng điểm (x 0, y0) là điểm
thuộc về đoạn thẳng, tức là Ax0 + By0 + C = 0.
p0 = 2F(x0 + 1, y0 -+ ½) = 2(A(x0 + 1) + B(y0 - ½) + C)
p0 = 2(Ax0 + By0 + C) + 2A - B = 2A - B = 2dy + dx
Dễ nhận thấy rằng thuật toán midpoint cho kết quả cũng giống như thuật toán
bresenham.
Lưu đồ của thuật toán:
19
Begin
p = 2dy+dx;
const1=2dy;
const2=2(dy+dx);
x=x1; y=y1
putpixel(x,y,color);
no
x
yes
p<0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
x = x + 1;
Putpixel(x,y,color);
end
iv.
Trường hợp 4 (m < -1)
Cũng đặt tương tự như Trường hợp 2. Việc lựa chọn x i+1 là xi hay xi + 1 cũng được dựa
vào vị trí trung điểm của yi và yi + 1, nó có phần ngược lại với Trường hợp 2.
Lúc này việc xét dấu của pi = 2F(midpiont) = 2F(xi - 1/2, yi + 1) sẽ cho chúng ta biết
điểm pi+1 cần chọn là điểm nào.
Pi < 0, chọn xi+1 là xi - 1
Pi >=0, chọn xi+1 là xi
Mặt khác ta xét:
pi+1 – pi = 2F(xi+1-1/2,yi+1+1)–2F(xi-1/2,yi+1)=2A(xi+1 - xi)+2B = 2dy(xi+1 - xi)–2dx
Vậy:
o Nếu pi <= 0, pi+1 = pi – 2dx do ta chọn xi+1 = xi - 1
o Nếu pi > 0, pi+1 = pi – 2dx – 2dx do ta chọn xi+1 = xi
Ta tính giá trị p0 ứng với điểm ban đầu (x 0, y0) với nhận xét rằng điểm (x 0, y0) là điểm
20
thuộc về đoạn thẳng, tức là Ax0 + By0 + C = 0.
p0 = 2F(x0 - 1/2, y0 + 1) = 2(A(x0 - 1/2) + B(y0 + 1) + C)
p0 = 2(Ax0 + By0 + C) - A +2 B = -A + 2B = -dy – 2dx
Ta có lưu đồ của thuật toán:
Begin
p = -dy - 2dx;
const1 = -2dx;
const2 = -2(dy+dx);
x = x1; y = y1
putpixel(x,y,color);
no
y
yes
p>0
no
yes
p=p+const1;
p=p+const2;
y=y+1;
y = y + 1;
Putpixel(x,y,color);
end
2. Các phép biến đổi
a. Phép tịnh tiến
Đây là phép tốn đơn giản nhất trong các phép tốn, vì để tịnh tiến một đường thẳng ta
chỉ việc tịnh tiến hai điểm bất kỳ thuộc đường thẳng là được. Sau đó ta chỉ việc gọi một
hàm vẽ đoạn thẳng bất kỳ từ hai điểm vừa tịnh tiến xong.
Lư đồ của thuật toán:
21
Begin
x1 = x1 + xn;
y1 = y1 + yn;
x2 = x2 + xn;
y2 = y2 + yn;
Bresenham(x1,y1,x2,y2);
end
b. Phép quay
Cung tương tự như phép tịnh tiến, đối với phép quay ta cũng chỉ cần quay hai điểm
thuộc đoạn thẳng sau đó là kẻ đoạn thẳng nối hai điểm đó lại với nhau là được.
Đối với việc quay mà góc quay là tâm O(0,0) thì:
x = x.cosα – y.sinα
y = x.sinα + y.cosα
Tuy nhiên để quay quanh một tâm quay bất kỳ, việc này sẽ có phần khó hơn vì ta phải
tịnh tiến tâm quay về góc tọa độ bẳng cách lấy tọa độ của điểm cần quay trừ đi tọa độ của
tâm quay. Sau khi tịnh tiến xong thì việc tiếp theo ta cũng làm như trên và sau đó tả chỉ
việc tịnh tiến đoạn thẳng đã quay bằng cách lấy điểm quay cộng với tâm quay. Sau đó ta
chỉ việc nối hai điểm vừa tịnh tiến lại với nhau là được.
Lưu đồ của thuật toán là:
22
Begin
x1 = x1 + xt;
y1 = y1 + yt;
x2 = x2 + xt;
y2 = y2 + yt;
x1 = x1.cosα-sinα.y1;
y1 = x1.sinα + cosα.y1;
x2 = x2.cosα – sinα.y2;
y2 = x2.sinα + cosα.y2;
x1 = x1 + xt;
y1 = y1 + yt;
x2 = x2 + xt;
y2 = y2 + yt;
Bresenham(x1,y1,x2,y2);
end
c. Phép co dãn
Để co dãn một đoạn thẳng hay một hình bất kỳ với tâm co là góc tọa độ ta chỉ việc
nhân tọa độ của các đỉnh với các số tỷ lệ sx, sy là được.
Tuy nhiên nếu tâm co là một tâm bất kỳ thì việc co dãn ta sẽ làm tương tự như phép
quay.
B1) ta tịnh tiến tâm quay về góc tọa độ.
B2) tìm tọa độ sau khi co dãn của các đỉnh.
B3) tịnh tiến lại tâm quay
B4) kẻ đường thẳng nối hai điểm sau khi tịnh tiến lại với nhau
Lưu đồ của thuật toán:
23
Begin
x1 = x1 + xt;
y1 = y1 + yt;
x2 = x2 + xt;
y2 = y2 + yt;
x1 = sx.x1;
y1 = sy.y1;
x2 = sx.x2;
y2 = sy.y2;
x1 = x1 + xt;
y1 = y1 + yt;
x2 = x2 + xt;
y2 = y2 + yt;
Bresenham(x1,y1,x2,y2);
end
d. Phép đối xứng qua điểm
Để đối xứng một điểm qua gốc tọa độ ta chỉ việc thêm dấu – vào trước tọa độ của
các điểm là được:
x’ = -x
y’ = -y
Tuy nhiên để đối xưng qua một điểm bất kỳ. ta có thể lợi dụng tính chất điểm đó là
điểm trung trực của điểm đã cho với điểm đối xứng.
x’ = 2.xt – x
y’ = 2.yt – y
Như vậy ta chỉ cần tìm hai điểm đối xứng của hai điểm đã cho, sau đó ta nối hai
điểm vừa tìm được lại với nhau là được.
Lưu đồ thuật toán:
24
Begin
x1 = 2.xt –x1;
y1 = 2.yt – y1;
x2 = 2.xt – x2;
y2 = 2.yt – y2;
Bresenham(x1,y1,x2,y2);
end
e. Phép đối xứng qua đường thẳng y =ax + b
Việc đầu tiên ta cần làm là tìm đối xứng của một điểm qua một đường thẳng cho
trước. Để làm được việc này, đầu tiên ta kẻ một đường thẳng đi qua điểm đã cho và
vng góc với đường thẳng y = ax + b, đường thẳng này sẽ có dạng y = (-1/a)x + c.
Sau khi viết được phương trình tổng quát của đường thẳng này, ta chỉ việc thay tọa
độ điểm ban đầu cần đối xứng vào để tính ra c. Phương trình này sau khi tính ra c sẽ
có dạng: y = (-1/a)x + y0 + (1/a)x0
Việc tiếp theo ta cần làm là tìm giao điểm của đường thẳng ban đầu với đường
thẳng vừa tìm được, giao điểm này chính là điểm trung trực M của điểm ban đầu và
điểm đối xứng mà ta cần tìm. Điểm M này sẽ có tọa độ là:
xm = (ay0 + x0 – ab)/(a2 + 1)
ym = ax + b (y được tính bằng cách thay x vào phương trình đường thẳng đầu tiên).
Vì M là điểm trung trực của hai điểm đối xứng nhau nên điểm đối xứng ta cần tìm
sẽ có tọa độ là:
x’ = 2xm – x0
y’ = 2ym – y0
Sau khi đối xứng điểm A xong, điểm B ta cũng làm tương tự.
Begin
xm = (ay0 + a0 -ab)/(a2 + 1);
ym = ax + b;
x’ = 2xm – x0;
y’ = 2ym – y0;
end
25