1. Trang chủ
  2. » Luận Văn - Báo Cáo

Ch2-Cac Thuat Toan Co Ban (2).Pdf

39 6 0

Đ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 39
Dung lượng 1,63 MB

Nội dung

Chương 2 Các thuật toán đồ họa cơ bản Hình ảnh của thế giới thực được mô tả ở dạng 2D hoặc 3D khi được hiển thị lên màn hình máy tính đều phải thông qua các tiến trình xử lý Trong đó các hình ảnh này[.]

Chương Các thuật tốn đồ họa Hình ảnh giới thực mô tả dạng 2D 3D hiển thị lên hình máy tính phải thơng qua tiến trình xử lý Trong hình ảnh phân tách làm thực thể sở Các thực thể đồ hoạ sở bao gồm đối tượng hình học điểm đường thẳng, cung tròn hay đường cong bậc hai khác… quét để chuyển thành tập điểm ảnh dùng cho trình hiển thị Chương trình bày thuật tốn sử dụng để quét chuyển hình ảnh thiết bị phần cứng phần mềm 2.1.CÁC ĐỐI TƯỢNG ĐỒ HOẠ CƠ SỞ Các đối tượng đồ hoạ sở điểm, đoạn thẳng, đường gấp khúc… biểu diễn chuyển sang dãy điểm ảnh tương ứng để hiển thị Quá trình chuyển đổi cịn gọi q trình chuyển đổi dịng quét (scan-converting) 2.1.2 Điểm Điểm đối tượng đồ hoạ sở quan trọng hệ toạ độ Trong hệ toạ độ 2D điểm xác định cặp toạ độ (x, y) Với hệ toạ độ giới thực x, y (tập số thực), cịn với hệ toạ độ thiết bị x, y (tập số ngun) Ngồi ra, điểm cịn có thuộc tính khác màu sắc 2.1.1 Đoạn thẳng, đường gấp khúc Một đoạn thẳng xác định biết hai điểm P( x1 , y1 ), Q( x2 , y2 ) thuộc đường thẳng Phương trình đường thẳng qua hai điểm PQ có dạng sau: x  x1 x2  x1  y  y1 y2  y1 Biểu diễn dạng phương trình: y = mx + b đó: m  b  y1  mx y với y  y2  y1 , x  x2  x1 y (2.1) Đây phương trình đoạn chắn đường thẳng Khai triển dạng sau: ( y2  y1 ) x  ( x2  x1 ) y  x1 y2  x2 y1  (2.2) Đặt A  y2  y1 , B  ( x2  x1 ), C  x2 y1  x1 y2 , phương trình (2.2) có dạng: Ax  By  C  dạng phương trình tổng quát đường thẳng Q(x2,y2) P(x1,y1) O m Hình 2.1 Biểu diễn đoạn thẳng Trong khảo sát đường thẳng, ta sử dụng phương trình tham số sau:  x  (1  u ) x1  tx2   y  (1  u ) y1  ty2 (2.3) Nếu u  [0, 1], ta có điểm (x, y) thuộc đoạn thẳng nối hai điểm P Q, u  [, +] ta có tồn đoạn thẳng Một đoạn thẳng đường thẳng bị giới hạn hai điểm đầu mút u=1 u>1 u=0 (x1, y1 ) u 0, dùng màu vẽ hành, thuật toán DDA vẽ đoạn thẳng qua hai điểm (xA, yA) (xB, yB) cài đặt sau void lineDDA(int xA, int yA, int xB, int yB) { int dx = xB - xA; int dy = yB - yA; int steps, k; float xInc, yInc, x=xA, y=yA; if(fabs(dx) > fabs(dy)) steps = fabs(dx); else steps = fabs(dy); xInc = float (dx) / float (steps); yInc = float (dy) / float (steps); setPixel(round (x), round(y)); for(k=0; k 1: Đổi vai trò x y cho nhau, cho y tăng đơn vị từ yA đến yB, dùng cách kiểm tra để xác định x có tăng hay khơng Các đại lượng kiểm tra là: e1  2x  y , enoinc  2x, einc  2x  2y −1 < m < Thay y −y Cho x tăng đơn vị từ xA đến xB, dùng ei để kiểm tra y giảm thay tăng Các đại lượng kiểm tra: e1  2y  x , enodec  2y , edec  2y  2x m < −1: Thay x −x đổi vai trò x y cho Cho y giảm đơn vị từ yA đến yB dùng ei để kiểm tra x có tăng hay khơng Các đại lượng kiểm tra là: e1  2x  y , enoinc  2x, einc  2x  2y Ví dụ 2.2 Cho hai điểm A(1, 1) B(5, 11) x  4, y  10, m   nên sau y tăng 5 đơn vị x tăng Các đại lượng kiểm tra: e1  2y  2x  2, enoinc  2x  8, einc  2x  2y  12 Dãy điểm toạ độ nguyên tính sau: i 10 x 1 2 3 4 5 y ei −2 −6 −10 −2 −6 10 −10 11 −2 12 11 10 1 O Hình 2.9 Các điểm toạ độ nguyên theo thuật tốn Bresenham với m > Ví dụ 2.3 Cho hai điểm A(1, 4) B(10, 1) x  9, y   3, m   nên sau x tăng 3 đơn vị y giảm đơn vị Các đại lượng kiểm tra là: e1  2y  2x  3, enodec  2 y  6, edec  2y  2x  12 Dãy điểm toạ độ nguyên tính sau: i x y ei −3 3 −9 −3 3 −9 −3 8 −9 10 −3 O 10 11 Hình 2.10 Các điểm tính theo thuật tốn Bresenham cho trường hợp −1 < m < Ví dụ 2.4 Cho hai điểm A(1, 10) B(4, 1) Ta có: x  3, y  9, m  3 nên sau y giảm đơn vị x tăng đơn vị Các đại lượng kiểm tra là: e1  2x  y  3, enoinc  2x  einc  2x  2y  12 Dãy điểm toạ độ nguyên tính sau: i x y ei 10 −3 1 2 −9 −3 5 −9 −3 3 −9 −3 11 10 O Hình 2.11 Các điểm tính theo thuật tốn Bresenham cho trường hợp m max.x) if(P.y < min.y) if(P.y > max.y) retur nm; } m|= m|= m|= m|= 1; 2; 4; 8; Giả sử hai điểm A, B gán mã tương ứng code(A), code(B); AND OR phép toán logic Xét vị trí đoạn thẳng AB so với cửa sổ hình chữ nhật, ta có trường hợp sau: Nếu code(A) = code(B) = 0000 (hay (code(A) OR code(B)) = 0000) đoạn AB hồn tồn nằm hình chữ nhật hay ClipD(F) = AB Nếu [code(A) AND code(B)]  0000 đoạn AB nằm hồn tồn bên ngồi hình chữ nhật hay ClipD(F) =  Nếu ((code(A) and code(B)) = 0000) (code(A)  0000 code(B)  0000) thì: 3.1 Giả sử code(A)  0000 (nếu code(A) = 0000, ta đổi vai trị A B), điều tương đương điểm A nằm bên ngồi hình chữ nhật 3.2 Nếu Ax = Bx (ứng với trường hợp đoạn AB thẳng đứng) thì:  Nếu Ay > ymax (A trên) Ay = ymax Ngược lại (A dưới) Ay = ymin  ClipD(F) = AB 3.3.Nếu Ax  Bx thì: Tính hệ số góc đường thẳng AB để tìm giao điểm đoạn AB với biên hình chữ nhật Vì A nằm bên ngồi hình chữ nhật nên:  Nếu Ax < xmin thay A điểm giao AB với cạnh trái (nối dài) cửa sổ hình chữ nhật;  Nếu Ax > xmax thay A điểm giao AB với cạnh phải (nối dài) cửa sổ hình chữ nhật;  Nếu Ay < ymin thay A điểm giao AB với cạnh (nối dài) cửa sổ hình chữ nhật;  Nếu Ay > ymax thay A điểm giao AB với cạnh (nối dài) cửa sổ hình chữ nhật Quá trình lặp lặp lại, sau lần lặp ta phải tính lại mã A Nếu cần thiết ta hốn đổi vai trị A B cho để ln đảm bảo A nằm ngồi hình chữ nhật Quá trình lặp lại dừng xảy hai trường hợp i ii Thuật tốn Cohen-Sutherland mơ tả sau: void CohenClip (PointA, Point B, Pointwmin, Pointwmax) { intescapeLoop, drawLine; double m; escapeLoop = 0; drawLine = 1; while(escapeLoop == 0) { if((code(A)| code(B))== 0) escapeLoop = 1; else if((code(A)&code(B)) != 0) {escapeLoop = 1; drawLine = 0} else { if (code(A)==0)swap(&A, &B);//Hốn đổi vị trí hai điểm A B if(A.x == B.x) { if (A.y > wmax.y) A.y = wmax.y; else A.y = wmin.y; } else { m =(double)(B.y - A.y)/(B.x - A.x); if(A.x < wmin.x){ A.y = A.y+ (wmin.x - A.x)*m; A.x = wmin.x; } else if (A.x > wmax.x){ A.y = A.y +(wmax.x - A.x)*m; A.x = wmax.x; }else if (A.y < wmin.y){ A.x = A.x +(wmin.y - A.y)/m; A.y = wmin.y; } else if (A.y > wmax.y){ A.x = A.x + (wmax.y - A.y)/m; A.y = wmax.y;} } } }//end while if (drawLine) line(A, B);// Vẽ đoạn thẳng AB } Các điểm giao biên cửa sổ với đoạn thẳng tính từ phương trình tham số đường thẳng Tuy nhiên, đòi hỏi phép tính số thực nên thuật tốn bị hạn chế mặt tốc độ Ta thường dùng phương trình tham số đường thẳng để tính giao điểm đường thẳng cửa sổ Phương trình tham số đường thẳng có dạng: x  x1  u ( x2  x1 )  x1  u.x , x  x2  x1  u  y  y1  u ( y2  y1 )  y1  u.y , y  y2  y1  u  x  x1 x y  y1 y Với  u  Nếu giao điểm ứng với u ngồi đoạn [0, 1] điểm khơng thuộc cửa sổ Tại đường biên, phương trình x = const y = const B A’ B B’ A A’ A Hình 2.29 Quá trình thực thuật toán Cohen-Sutherland y= yT Giao điểm với y = yT C(1000) (xR,yT) Giao điểm với x = xR Window A(0000) D(0010) y= yB (xL,yB) x = xL B(0100) Giao điểm với y = yB x = xR Hình 2.30 Tách riêng đường biên window để tính giao điểm Việc xác định tính nhìn thấy đường tính tốn giao để xác định đoạn thẳng nằm vùng cửa sổ tương đối đơn giản Một kỹ thuật khác dùng để xác định giao điểm đường thẳng với biên cửa sổ mà không dùng phương trình đường thẳng nhiều lần kỹ thuật tìm kiếm nhị phân 2.6.2.2 Thuật toán chia nhị phân Ý tưởng thuật tốn dựa việc tìm nghiệm phương trình phương pháp chia nhị phân Bằng cách lấy trung điểm đoạn thẳng kiểm tra mã đoạn thẳng để loại dần đoạn không chứa giao điểm, cuối trung điểm hội tụ giao điểm đoạn thẳng với cửa sổ hình chữ nhật đoạn thu nằm cửa sổ (nếu có) Thuật tốn thực tính trung điểm đoạn thẳng xét Sau với nửa đoạn thẳng, xét xem mã vùng nằm hồn toàn hay nằm hoàn toàn cửa sổ: Nếu có nửa đoạn thẳng nằm hồn tồn hay hồn tồn ngồi ta xét tới nửa đoạn thẳng lại với phương pháp tương tự tìm thấy điểm giao Nếu hai nửa đoạn thẳng khơng thể xác định nằm hồn tồn hay hoàn toàn (trường hợp cần xét điểm giao) lặp lại q trình chia đơi đoạn thẳng để xét hai đoạn tìm điểm giao dừng M M M M Hình 2.31 Thuật tốn sử dụng trung điểm M để tìm điểm giao Cho hai điểm A B có mã vùng tương ứng code(A) code(B) Gọi M trung điểm đoạn thẳng AB M có mã vùng code(M) Khi đó: Nếu code(A)  0000, code(B)  0000 code(M)  0000, ta có: [code(A) AND code(M)]  0000 [code(B) AND code(M)]  0000 Mệnh đề có ý nghĩa hình học sau: Nếu ba điểm A, B M nằm cửa sổ hình chữ nhật có đoạn AM BM hoàn toàn nằm cửa sổ Các bước thuật tốn chia nhị phân mơ tả sau: Nếu code(A) = code(B) = 0000 đoạn AB hồn tồn nằm hình chữ nhật hay ClipD(F) = AB Nếu [code(A) AND code(B)]  0000 đoạn AB nằm hồn tồn bên ngồi hình chữ nhật hay ClipD(F) =  Nếu (code(A)  0000) (code(B) = 0000) đổi vai trị A, B áp dụng 4 Nếu (code(A) = 0000) (code(B)  0000) a Gán P = A Q = B b Trong │xP − xQ│+│yP − yQ│≥ + Lấy trung điểm M PQ + Nếu code(M)  0000 Q = M Ngược lại P =M c ClipD(F) = AP Nếu code(A)  0000, code(B)  0000 ((code(A) && code(B)) = 0000) thì: a Gán P = A, Q = B b Lấy trung điểm M PQ c Chừng (code(M)  0000) (│xP − xQ│+│yP − yQ│ ≥ 2) thì: + Nếu (code(M) AND code(Q))  0000 gán Q = M Ngược lại gán P = M + Lấy M trung điểm PQ d Nếu code(M)  0000 ClipD(F) =  Ngược lại, {lặp lại bước 4} + ClipD(MP) = MA1 + ClipD(MQ) = MB1 + ClipD(F) = A1B1 Thuật toán xén hình theo cách chia nhị phân cài đặt sau: void BinaryClip(Point A, Point B) { Point P, Q, M; if ((code(A) | code (B))== 0) line(A, B); // Vẽ đoạn thẳng AB if ((code (A) & code (B)) != 0) return; if ((code (A) != 0) && (code (B) == 0)) swap(&A, &B); //Hốn đổi vị trí hai điểm A B if ((code (A) == 0) && (code (B) != 0)) { P = A; Q = B; while ((abs(P.x - Q.x) + abs(P.y - Q.y)) > 2) { M.x = (P.x+Q.x)/2; M.y = (P.y + Q.y)/2; if (code (M) == 0)P = M; else Q = M; } line(A, P); } if (((code (A) != 0) && (code (B) != 0)) && ((code (A) & code (B))==0)) { P = A; Q = B; M.x = (P.x + Q.x)/2; M.y = (P.y + Q.y)/2; while ((code (M) != 0) && ((abs(P.x - Q.x) + abs(P.y - Q.y)) > 2)) { if ((code (Q) & code (M))!= 0) Q = M; else P = M; M.x = (P.x + Q.x)/2; M.y = (P.y + Q.y)/2; } if (code (M) == 0) { BinClip(M, P); BinClip(M, Q); } } } 2.6.2.3 Thuật toán Liang - Barsky Thuật toán Liang - Barsky phát triển dựa vào việc phân tích dạng tham số phương trình đường thẳng mô tả Ứng với u, ta có điểm P tương ứng thuộc đường thẳng (Hình 2.32) Các điểm ứng với u  thuộc tia P2x; Các điểm ứng với u  thuộc tia P1x; Các điểm ứng với  u  thuộc đoạn thẳng P1P2 x u=1 u>1 u=0 x’ P2 ( x2 , y ) P1 ( x1 , y1 ) u 0) { if(r < t0) return false; else if(r < t1) t1 = r; // Đường thẳng cắt } } x0clip = x0src + t0*xdelta; y0clip = y0src + t0*ydelta; x1clip = x0src + t1*xdelta; y1clip = y0src + t1*ydelta; return true; } 2.6.3 Phép xén đa giác Thuật toán xén đoạn thẳng cải tiến để áp dụng vào xén đa giác cách xem đa giác tập đoạn thẳng nối tiếp Tuy kết sau xén tập đoạn thẳng rời nhau, ta cần tạo thành đa giác chuyển thành vùng tơ (Hình 2.33) Hình 2.33 Q trình xén đa giác Thuật tốn Sutherland - Hodgemand tiến hành xén đa giác với biên cửa sổ Đầu tiên, đa giác xén dọc theo biên trái cửa sổ, kết sau bước dùng để xén tiếp biên phải Thực trình tương tự cho biên trên, Sau xén hết với bốn biên cửa sổ, ta phần đa giác nằm cửa sổ I Vi+1 I Vi Vi Vi+1 (1) Vi+1 (2) Vi I Vi+1 (3) (4) Hình 2.34 Các trường hợp giao cạnh đa giác với Window Với lần xén đa giác dọc theo biên cửa sổ, gọi Vi, Vi+1 hai đỉnh kề cạnh, ta có bốn trường hợp xảy xét cặp đỉnh đa giác ban đầu với biên cửa sổ sau: Nếu Vi nằm ngoài, Vi+1 nằm trong, thực lưu giao điểm I ViVi+1 với biên cửa sổ Vi+1; Nếu Vi, Vi+1 nằm trong, lưu hai giá trị Vi, Vi+1; Nếu Vi nằm trong, Vi+1 nằm ngoài, lưu giá trị Vi I; Nếu Vi, Vi+1 nằm ngồi, khơng lưu giá trị _ ... &y); FillColor(x-1, boundaryColor); FillColor(x+1, boundaryColor); FillColor(x, boundaryColor); FillColor(x, boundaryColor); } } y, fillColor, y, fillColor, y+1, fillColor, y-1, fillColor, 2.6.CẮT... fillColor, int boundaryColor){ int currentColor = getpixel(x, y); if((currentColor!=boundaryColor) &&(currentColor!=fillColor)){ putpixel(x, y, fillColor); FillTop(x, y+1, fillColor, boundaryColor);... fillColor, int boundaryColor){ int currentColor = getpixel(x, y); if((currentColor!=boundaryColor) &&(currentColor!=fillColor)){ putpixel(x, y, fillColor); FillLeft(x-1, y, fillColor, boundaryColor);

Ngày đăng: 15/03/2023, 19:20

w