Nếu gọi xk, xk + Ị lần lượt là các hoành độ giao điềm cùa một cạnh nào đó với các dòng quét y = k và y = k + 1 ,ta có:
Xk+1一x k =ニ((k + 1)- k) = ニ hay X卜,= x k +ニ .
m m m
Như vậy, nếu lưu hoành độ giao điểm ứng với dòng quét trước lại cùng với hệ số góc của cạnh, ta dễ dàng xác định được hoành độ giao điểm ứng VƠI dòng quét Ke tiep một cách đơn giản theo cồng thức trên. Đieu này rút gọn đáng kể thao tác tìm giao ơiem của cạnh ứng với dòng quét. Chính vì vậy thông tin của một cạnh có hai biến la DXperScan Vâ X|ntersecい
3 - CÁC THU AT TOÁN TỒ MẢU
y = k ♦ 1
y = k
Hình 3.8. Cõng thức tìm giao điểm nhanh
3.2.3. Giải quyết trường họp dòng quét đỉ ngang qua đỉnh
Người ta đưa ra quy tắc sau để tính số giao điểm khi dòng quét đi ngang qua đỉnh:
- Tính một giao điểm nếu chiều của hai cạnh kề của đỉnh đó có xu hướng tăng hay giảm.
- Tính hai giao điểm nếu chiều của hai cạnh kề của đỉnh đó có xu hướng thay đổi, nghĩa là tăng - giảm hay giảm - tăng.
(a) (b)
Hình 3.9. Quy tắc tính một giao điểm (a) và hai giao điểm (b)
Khi cài đặt để khỏi phải xét điều kiện này cho phức tạp, khi xây dựng dừ liệu cho mồi cạnh trước khi đưa vào ET, người ta sẽ xử lý các cạnh có đinh tính hai giao điềm bàng cách loại đi một pixel trên cùng của một trong hai cạnh như hình 3.10.
m Đồ HOẠ MÁY TÍNH > Lưu đồ thuật toán tô màu theo dòng quét
;ỉ - CÁC THUAT TOÁN TÔ MÀU m
Cài đặt minh hoạ sau sử dụng chung một danh sách EDGELIST cho cà ET và AET. AET được quản lý nhờ vào hai con trỏ Firstld và Lastld.
> Cai đặt minh hoạ thuật toán tô màu scan - line
# i n c l u d e <cstdlib> ^ i n c l u d e < i o stream> u s i n g n a m e s p a c e s t d; # i n c l u d e < s t d i o .h> # i n c l u d e < s t d l i b .h> # i n c l u d e 〈g r a p h i c s •h> ♦♦include < d o s . h> # d e f i n e M A X V E R T E X 20 # d e f i n e M A X E D G E 20 # d e f i n e T R U E 1 # d e f i n e F ALSE 0 t y p edef struct int X; int y; } POINT2D; Lypedef struct { int N u m V e r t e x; P〇I N T 2 D a V e r t e x [ M A X V E R T E X ] ; }POLYGON2D; t y p edef struct { int N u m P t; float xPt [ M A X E D G E ] ; }XINTERSECT;
74 ĐÔ HOẠ MÁY Tìn h
typedef struct
{
int y M i n; // G i a tri y nho nh a t cua 2 di n h float x l n t e r s e c t;
// H o a n h do g i a o d i e m cua c a n h & do n g quet float d x P e r S c a n; // Gia tri 1/m
int D e l t a Y; }E D G E ; type d e f struct { int N u m E d g e; E D G E a E d g e [MAXEDGE] ; } EDGELIST; /★ Đưa một c ạ n h v à o d a n h s a c h cạnh, các c ạ n h được sap theo thứ tự g i a m d ầ n của y M i n (yMin, là gia trị y nhỏ nh ầ t của hai đỉ n h một cạnh) lon n h a t . x ử lý luôn tr ư ờ n g hợp d ò n g quét đi n gang qua đ ỉ n h m à tại đó chỉ t í n h một gi a o điểm) */
v o i d PutEdgelnList (EDGELIST ScEdgeList, POINT2D pl, P O I N T 2 D p 2 /int NextY) { EDGE E d g e T m p ; E d g e T m p .d x P e r S c a n = f l o a t ( p 2 •X - p l •X ) / ( p 2 •y - p l .y ) ; // 1/m ± r ( p l . y < p2.y) {
/* T r ư ờ n g hợp dò n g quét đi n g a n g qua đ ỉ n h la gi a o đ i e m của hai cạnh có h ư ớ n g y cù n g tăng */
i f (p2.y < NextY)
3 - CÁC THUAT TOÁN TÔ MÀU p 2 . x — = (i n t )E d g e T m p .d x P e r S c a n; } E d g e T m p . y M i n = p l . y; E d g e T m p .x l n t e r s e c t = p l . x; E d g e T m p .D e l t a Y = a b s ( p 2 •y - p l .y) + 1; } // if else {
/★ T r ư ờ n g hợ d ò n g quét đi n g a n g qua đ ỉ n h là giao đ i ể m của 2 cạ n h có h ư ớng y cù n g g i ả m */ i f ( p 2 .y > NextY) { p 2 . y + + ; p2 . X + = (i n t ) EdgeTtnp. d x P e r S c a n ; } E d g e T m p . y M i n = p 2 . y; E d g e T m p .x l n t e r s e c t = p 2 . x; E d g e T m p .D e l t a Y = a b s ( p 2 .y - p l .y) + 1; }//else // X á c đ ị n h vị trí chèn int j = E d g e L i s t .N u m E d q e; • w h i l e ( (j > 0) 8c8c ( E d g e L i s t . a E d g e [ j - 1 ] .yMin > E d g e T m p . y M i n ) ) { E d g e L i s t .a E d g e [j ] = E d g e L i s t .a E d g e [j 一 1]; j ---; } // C h è n đ ỉ n h mới v à o cạ n h E d g e L i s t .N u m E d g e ++; E d g e L i s t .a E d g e [j ] = E d g e T m p; } // P u t E d g e l n L i s t
// T ì m đ ỉ n h kế tiep sao cho k h o n q n a m tren
ĐỒ HOẠ MÁY TỈNH
EZI
int FindNextY(POLYGON2D p, int id)
{
int j = (id + 1)% p .NumVertex;
w h i l e ((j < p .NumVertex)&&(p .aVertex [id] .y
= = p .aVertex [ j] .y ) ) j++; i f (j < p .NumVertex) return (P.aVertex[j ] .y) ; return 0; } // FindNextY
// Tạo danh sách các cạnh từ polygon đã cho void MakeSortedEdge(P0LYG0N2D p, EDGELIST
ScEdgeList, int &TopScan, int ỗcBottomScan)
{
TopScan = BottomScan = p.aVertex [0] .y;
EdgeList.NumEdge = 0;
f o r (int i = 0; i < p .NumVertex; i ++)
{
//Trường hợp cạnh không phải là cạnh nằm ngang
i f (p .a Vertex[i] .y ! = p.aVertex [i + 1 ] .y)
PutEdgelnList(EdgeList, p .aVertex[i], p .aVertex [i + 1 ] , FindNextY(P, i + 1)); else //xử lý trường hợp cạnh nằm ngang i f (p.aVertex[i + 1 ] .y > TopScan) TopScan = p .aVertex[i + 1 ] .y; }
BottomScan = EdgeList.a E d g e [0].yMin;
} //MakeSortedEdge
// Cập nhật lại hai con trò Firstld, Lastld cho biết danh sách các cạnh kích hoạt (active)
void UpdateActiveEdgeList(EDGELIST EdgeList, int yScan, int &FirstId, int ScLastld)
, i - CÁC THUAT TOÁN TỒ MÀU w h i l e ( (Firstld < E d g e L i s t .N u m E d g e - 1 ) 8cSc ( E d g e L i s t . a E d g e [Firstld] . D e l t a Y == 0)) F i r s t l d ++; w h i l e ( (Lastld < E d g e L i s t .N u m E d g e - 1 ) ScSc ( E d g e L i s t . a E d g e [Lastld + 1 ] .yMin <= y S c a n ) ) L a s t l d ++; } // U p d a t e A c t i v e E d g e L i s t v o i d S o r t O n X (XINTERSECT ScalntersectPt) { f o r (int i = 0; i < a l n t e r s e c t P t . N u m P t - 1 ; i++) { int M i n = i, t; f o r (int j=i + 1 ; j < a l n t e r s e c t P t .N u m P t ;j + + ) i f ( a l n t e r s e c t P t .xPt [j ] < a l n t e r s e c t P t . x P t [Min]) M i n = j; t = ( i n t ) a I n t e r s e c t P t . x P t [ M i n ] ; a l n t e r s e c t P t •xPt [Min] = a l n t e r s e c t P t . x P t [ i ] ; a l n t e r s e c t P t .xPt [i] = t; } } I I S o r t O n X
/★ T ì m các h o à n h độ giao đ i ể m của các c ạ n h đa giác với d ò n g qu é t y S c a n . Sau khi tìm các h o à n h độ giao điềm, ta sắp x ế p lại t h e o c h i ề u tăng cùa X */
v o i d F i n d X I n t e r s e c t i o n (EDGELIST E d g e L i s t ,
X I N T E R S E C T & a l n t e r s e c t p t , int Firstld, int Lastld)
{
a l n t e r s e c t P t •N u m P t = 0;
ĐỒ HOẠ MÁY TÍNH i f (EdgeList.aEdge[i].DeltaY > 0) { alntersectPt.xPt [alntersectPt.NumPt] = EdgeList.aEdge[i].xlntersect; alntersectPt.NumPt ++; } } SortOnX(alntersectPt) ; } //FindXIntersection
#define Rou n d (X〉 int(x + 0.5)
void FillLine(XINTERSECT alntersectPt, int yScan)
{ for(int i = 0; i < alntersectPt.NumPt; i + = 2) { line(Round(alntersectPt.xPt[i]), yScan, R o u n d (alntersectPt.xPt[i + 1 ] ) , yScan) ; if(Round(aIntersectP t •x P t [i]) < R o u n d (alntersectPt.xPt[i + 1])) f o r (int j = R o u n d (alntersectPt.xPt[i]);j < = R o u n d (alntersectPt.xPt[i + l]);j++) putpixel(j , yScan, 4); else f o r (int j = R o u n d (alntersectPt.xPt[i + 1] ) ; j <= R o u n d (alntersectPt.xPt[i]);j + + ) putpixel(j , yScan, 4); } } // FillLine
void UpdateEdgeList (EDGELIST ScEdgeList,
int Firstld,int Lastld)
{
- CAC THUAT TOÁN TÔ MÀU m i f ( E d g e L i s t .a E d g e [ i ] . D e l t a Y > 0) { E d g e L i s t .a E d g e [ i ] . D e l t a Y - - ; E d g e L i s t .a E d g e [ i ] . x l n t e r s e c t + = E d g e L i s t .a Edge [i] . d x P e r S c a n; } } } / / F i l l L i n e v o i d S c a n L i n e F i l l ( P O L Y G O N 2 D p) { E D G E L I S T EdgeList; X I N T E R S E C T a l n t e r s e c t P t ;
int TopScan, Botto m S c a n , Firstld, Lastld;
MakeSortedEdge(P, E d g e L i s t , t o p S c an,BottomScan) ; F i r s t l d = L a s t l d = 0; f o r ( i n t i = Bottom S c a n ; i <= T o p S c a n; i ++) { // Cập nhật lại d a n h sá c h các c ạ n h a c t i v e 一 túc là các c ạ n h cắt d ò n g quét i U p d a t e A c t i v e E d g e L i s t ( E d g e L i s t , i , Firstld, L a s t l d) ;
/ * T ì m các h o à n h đ ộ g i a o đi e m của d ò n g quét
V Ơ I các cạ n h của đ a gi á c v à sắp xếp lại cac
h o à n h đ ộ giao đ iem trực tiep trên EdgeList */ F i n d x i n t e r s e c t i o n ( E d g e L i s t, a l n t e r s e c t P t , Firstld, L a s t l d) ; F i l l L i n e ( a l n t e r s e c t P t , i) ; U p d a t e E d g e L i s t ( E d g e L i s t , Firstld, L a s t l d ) ; } } / / S c a n L i n e F i l l
ĐỒ HOẠ MÁY TÍNH int g r _ d r i v e = DETECT, g r _ m o d e; int n = 4; i n i t g r a p h (&gr_drive, &gr_niode, " " ) ; P O I N T 2 D a [ M AXVERTEX]; P O L Y G O N 2 D A; A . N u m V e r t e x = n; a [ 0 ] . x = 0; a [ 0 ] . y = 0; A . a v e r t ex[0] = a [ 0] ; a [ l ] . x = 5 0 0; a [ l ] . y = 0; A . a V e r t e x [ l ] = a [ l] ; a [ 3 ] . x = 0; a [ 3 ] . y = 100; A . a V e r t e x [ 3 ] = a[3]; a [2] .X = 1 0 0; a [2] .y = 1 0 0; A . a V e r t e x [2] = a [2] ; S c a n L i n e F i l l ( A) ; c l o s e g r a p h( ) ; s y s t e m (" P A U S E " ); r e t u r n E X I T _ S U C C E S S ;
m
c€ k tứ ftíỹ 4
CÁC PHÉP BIẾN ĐỔI TOONG Đỏ HOẠ HAI CHIỀU
Các thao tác phóng to, thu nhỏ và di chuyển hình ảnh có thể được hỗ trợ một cách dễ dàng nhờ vào các phép biến đổi hình học. Các phép biến đổi hình học sẽ làm thay đổi mô tả về toạ độ của các đổi tượng, từ đó làm cho đối tượng bị thay đổi về hướng, kích thước và hình dạng. Các phép biến đổi hình học cơ sở bao gồm: tịnh tiến (translation), quay (rotation) và biến đổi tỷ lệ (scaling). Ngoài ra một số phép biến đổi khác cũng thường được áp dụng đó là phép đối xứng (reflection) và biến dạng (shearing).
Có hai quan điểm về phép biển đổi hình học đó là: biến đổi đối tượng (object transformation) và biến đổi hệ toạ độ (coordinate transformation). Biến đổi đổi tượng là thay đổi toạ độ của các điềm mô tả nó theo một quy tắc nào đó, còn biến đổi hệ toạ độ là tạo ra một hệ toạ độ mới và tất cả các điểm mô tả đổi tượng sẽ được chuyển về hệ toạ độ mới. Hai cách này có những mối liên hệ chặt chẽ với nhau và mồi cách đều có những lợi thế riêng. Chúng ta sẽ bàn về phép biến dổi đối tượng trước.
4.1. CÁC PHÉP BIÉN ĐÒI HÌNH HỌC C ơ SỚ
Một phép biến đổi hai chiều sẽ biến đổi điểm p trong mặt phẳng thành điểm có toạ độ mới Q theo một quy luật nào đó. về mặt bản chất, một phép biến đổi điểm là một ánh xạ T được định nghĩa:
r a Đ ô HOẠ MÁY TÌNH
T : R 2 -> K2 P(x, y) 1-4 Q(x', y')
Nói cách khác, T là hàm số T(x, y) theo hai biến (x, y): j x ' = f(x ,y )
l y ' = g(x,y)
Phép biến đổi affine là phép biến đổi với f(x, y) và g(x, y ) là các hàm tuyến tính. Phép biến đổi này có dạng:
[ x ' = ax + cy + e Ị y ' = bx + dy + f
trong đó: a, b, c, d, e, f e R ; ad - bc 式 0.
Ta chỉ khảo sát các phép biến đổi affine, nên từ đây về sau ta dùng cụm từ "phép biến đổi" thay cho cụm từ "phép biến đồi affine". 4.1.ỉ. Phép tịnh tiến
Dẻ tịnh tiến một điểm P(x, y) từ vị trí này sang vị trí khác trong mặt phăng, ta cộng thêm các giá trị mô tả độ dời vào các toạ độ của p. Nếu gọi trx và try lần lượt là độ dơi theo trục hoành và trục tung thì toạ độ cùa ơiem mới Q(x', y') sẽ là:
X' = X + trx y' = y + try
(trx, try) còn được gọi là vector tịnh tien hay vector độ dơi.
Chúng ta có thể dịch chuyển toàn bộ một đối tượng bằng cách áp dụng quy tắc trên cho mọi aiem thuộc aoi tượng. Để tịnh tiến một đoạn thẳng, đơn giản chi cần tịnh tiến hai điểm đầu và cuối của nó, rồi sau đó vẽ lại đoạn thẳng nối hai điểm mới. Với đa giác, ta tịnh tiến các đinh của nó, sau đó vẽ lại đa giác với các đinh mới. Một cách tưong tự, để tịnh tiến các đối tượng như đường tròn, ellipse, ta tịnh tiến tâm cùa chúng tơi vị trí mơi roi vẽ lại.
4- CÁC PHÉP BIÊN ĐỔI TRONG ĐÔ HOA HAI CHIÊU BI
try
0
A
(2.3) (4,3)
Hình 4.1. Phép tịnh tiến một điểm (a) và đối tượng với vector tịnh tiến (~4, 2) (b)
4.1.2. Phép biến đổi tỷ lệ
Phép biến đổi tỷ lệ làm thay đổi kích thước đối tượng. Để co hay giãn toạ dộ cùa một điểm P(x, y) theo trục hoành và trục tung lần lượt là sx và Sy, ta nhân sx và Sy lần lượt cho các toạ độ của p:
| x ’ = sx.x
trong đó, sx và Sy được gọi là các hệ số tỷ lệ.
Ncu các giá trị sx và Sy nhỏ hơn 1 thì phép biến đổi sẽ thu nhò đối tượng; ngược lại, Khi các giá trị này lớn hơn 1 thì phép biến đồi sẽ phóng to đối tượng. Nếu sx và Sy bàng nhau, thì gọi đỏ là phép đồng dạng (uniform scaling), phép đồng dạng là phép biến đồi bảo toàn tính cân xứng của đối tượng.
ĐÔ HOẠ MÁY TÍNH
K3
Tâm tỷ lệ là điểm không bị thay đổi qua phép biến đổi tỷ lệ. Phép biến đổi tỳ lệ mô tả như trên còn gọi là phép biến đổi tỷ lệ quanh gốc toạ độ, vì có tâm tỷ lệ là gốc toạ độ. Nhận xét rằng, khi phép biến đổi tỷ lệ thu nhỏ đối tượng, đối tượng sẽ được dời về gần gốc toạ độ hơn, tưcmg tự khi phỏng lớn đối tượng, đối tượng sẽ được dịch chuyển xa gốc toạ độ hơn.
4.1.3. Phép quay
Phép quay làm thay đổi hướng cùa đối tượng. Một phép quay đòi hỏi phải có tâm quay, góc quay. Góc quay dương thường được quy ước theo chiều ngược chiều kim đồng hồ. Ta có công thức biến đổi của phép quay điểm P(x, y) quanh gổc toạ độ một góc a là:
íx ' = c o s a .x - s in a .y [ y ' = sin a.x + cos a.y
Hình 4.3. Phép quay một đối tượng quanh gốc toạ độ một góc 60°
4.1.4. Biểu diễn ma trận của phép biến đổi
Trong nhiều ứng dụng đồ hoạ, người dùng thường xuyên có nhu cầu thực hiện nhiều phép biến đổi hình học khác nhau trên một đối tượng để tạo ra các hiệu quả như mong muốn. Ví dụ, trong các ứng dụng thiết kế, chúng ta cần phải thực hiện nhiều phép tịnh tiến, quay, tỷ lệ để có thể khớp từng phần của đối tượng vào đúng vị trí của chúng, hay sau khi thực hiện các phép biến đổi nhưng không được như ý, người dùng muốn trở lại hiện trạng trước khi biến đổi. Do vậy,
4 - CÁC PHÉP BIỂN ĐỔI TRONG ĐỒ HOA HAI CHIÊU
cần phải có một cách nào đó đề có thể xử lý dãy các phép biến đồi trên được nhanh chóng và hiệu quả.
Nếu biểu diễn toạ độ của điềm P(x, y) và Q(x', y') dưới dạng các vector dòng lần lượt là (x y) và (x* yf) thì các phép biến đồi tịnh tiến, tỷ lệ, quay có thề được biểu diễn dưới dạng ma trận như sau:
- Phép tịnh tiến:
(X- y,) = (X y) + (trx try)
hay Q = p + T với T = (trx try). - Phép biến đổi tỷ lệ: (s 0、 い , y . H x y吹 J s hay fs 0 Q = p .s với s = x
- Phép quay quanh gốc toạ độ:
c o sa s i n a N -since c o s a y / (X’ y ’) = (x y) hay Q = P.R với R = c o sa 、 - s i n a s i n a N c o s a >
Vơi cách biểu dien này, chúng ta sẽ gặp khỏ khăn khi muốn kết hợp các phép bien đoi lại VƠI nhau, vì bieu dien của phép tịnh tien khác với dạng của các phép biến đổi tỷ lệ và phép quay. Chính vì vậy, cần phải có một cách nào đó để biểu diễn ba phép biến đổi này về một dạng duy nhất để có the dễ dàng xử lý sau này.
4.1.5. Hệ toạ độ thuần nhất
Toạ độ thuần nhất cùa một aiem trên mặt phẳng được biểu dien bằng bộ ba số tỷ lệ (xh, yh, h) không đồng thời bàng 0 và liên hệ với các toạ độ (x, y) của điểm đỏ bởi công thức:
n Đ ồ HOẠ MÁY TỈNH
x h ;
y = l f -
Nếu một điểm có toạ độ thuần nhất là (x, y, z) thì nó cũng có toạ độ thuần nhất là (h.x, h.y, h.z), trong đó h là số thực khác 0 bất kỳ. Toạ độ thuần nhất của một điểm trong không gian ba chiều hay có số chiều lớn hơn cũng được xác định một cách tương tự.
Trong hệ toạ độ thuần nhất, các điểm xa vô tận không đóng một vai trò gì đặc biệt so với các điểm khác cùa mặt phẳng. Với các phép biến đổi hình học đang khảo sát, nếu một điểm được biểu diễn dưới dạng toạ độ thuần nhất, cả ba phép biến đổi trên đều được biểu diễn dưới dạng tích các ma trận. Điều này giúp cho việc khảo sát các tính chất và sự kết hợp cùa các phép biến đổi này được thuận tiện do mồi phép biến đổi được đại diện bởi một ma trận duy nhất.
Bộ ba các toạ độ thường biểu diễn các điểm trong không gian ba chiều, nhưng ở đây ta sử dụng chúng để biểu diễn các điểm trong không gian hai chiều. Mối liên hệ ở đây là nếu ta xét tất cả các bộ ba toạ độ thuần nhất biểu diễn cho cùng một điểm, nghĩa là bộ ba số có dạng (h.x, h.y, h), với h ^ 0, ta sẽ nhận được một đường thẳng trong không gian ba chiều. Để đom giản hoá, có thể chọn h = 1 , lúc này mồi điểm P(x, y) sẽ được biểu diễn dưới dạng toạ độ thuần nhất là (x, y , 1).
4.1.6. Biểu diễn các phép biến đỗi dưới dạng toạ độ thuần nhất
> Phép tịnh tiến
'1 0 0、
(x ' y ' l ) = ( x y 1 ) 0 1 0
4 - CÁC PHÉP BIÉN ĐỔI TRONG ĐỔ HOẠ HAI CHIÊU
1 0 0
hay Q = P.M r(trx, try) với MT(trx,try) = 0 1 0
u try l > Phép biến đổi tỷ lệ m (x- y 1 l) = (x y 1) s. 0 0、 0 sy 0 0 0 1
hay Q = P.Ms(sx, Sy) với Ms(sx,s y)
> Phép quay quanh gốc toạ độ
( x 1 y 1 l) = (x y 1) sx 0 0、 0 sy 0 0 0 1 c o s a s in a u - s i n a c o sa 0 0 0 1
hay Q = P.MR(a ) với M R(a )
c o sa sin a 0 - s in a cos a 0
0 0 1
4.2. KÉT HỢP CÁC PHÉP BIÉN ĐỔI
Quá trình áp dụng các phép biến đổi liên tiếp để tạo nên một phép biến đồi tổng thể được gọi là sự kết hợp các phép biến đổi (composing transformation).
4.2.1. Kết họp các phép tịnh tiến
Nếu thực hiện phép tịnh tiến lên P(x, y) được P', rồi lại thực hiện tiếp một phép tịnh tiến khác lên P', ta được điểm Q(x', y'). Như vậy,