Giáo trình Đồ họa máy tính

pdf 160 trang hoanguyen 7260
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Đồ họa máy tính", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfgiao_trinh_do_hoa_may_tinh.pdf

Nội dung text: Giáo trình Đồ họa máy tính

  1. Giáo trình Đồ họa máy tính
  2. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Lời nói đầu Đồ họa máy tính được ra đời bởi sự kết hợp của 2 lĩnh vực thông tin và truyền hình. Đầu tiên kỹ thuật đồ họa được phát triển bởi các nhóm kỹ sư sử dụng máy tính lớn. Trong giai đoạn đầu của sự phát triển người ta phải tốn nhiều tiền cho việc trang bị các thiết bị phần cứng. Ngày nay, nhờ vào sự tiến bộ của vi xử lý, giá thành của máy tính càng lúc càng phù hợp với túi tiền của người sử dụng trong khi các kỹ thuật ứng dụng đồ họa của nó ngày càng cao hơn nên có nhiều người quan tâm nghiên cứu đến lĩnh vực này. Chúng ta có thể vẽ ra những hình ảnh không chỉ là ảnh tĩnh mà còn có thể biến đổi thành những hình ảnh sinh động qua các phép quay, tịnh tiến Do vậy, đồ họa máy tính trở thành một lĩnh vực lý thú và có nhiều ứng dụng trong thực tế. Tuy nhiên, việc dạy và học kỹ thuật đồ họa thì không là đơn giản do chủ đề này có nhiều phức tạp. Kỹ thuật đồ họa liên quan đến tin học và toán học bởi vì hầu hết các giải thuật vẽ, tô cùng các phép biến hình đều được xây dựng dựa trên nền tảng của hình học không gian hai chiều và ba chiều. Hiện nay, Kỹ thuật đồ họa là một môn học được giảng dạy cho sinh viên chuyên ngành Tin học với 45 tiết lý thuyết và 15 tiết thực tập. Nội dung của giáo trình kỹ thuật đồ họa này tập trung vào 2 vấn đề chính như sau : - Trình bày các thuật toán vẽ và tô các đường cơ bản như đường thẳng, đa giác, đường tròn, ellipse và các đường conic. Các thuật toán này giúp cho sinh viên có thể tự mình thiết kế để vẽ và tô một hình nào đó ( chương 1 và 2). - Nội dung thứ hai đề cập đến đồ họa hai chiều và đồ họa ba chiều bao gồm các phép biến đổi Affine, windowing và clipping, quan sát ảnh ba chiều qua các phép chiếu, khử các mặt khuất và đường khuất, thiết kế đường cong và mặt cong (từ chương 3 đến chương 7). Giáo trình kỹ thuật đồ họa này được sửa đổi và cập nhật dựa trên kinh nghiệm giảng dạy đã qua và được xây dựng dựa trên tài liệu tham khảo chính là : Donald Hearn, M. Pauline Baker; Computer Graphics; Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986. Sau cùng, chúng tôi hy vọng rằng giáo trình này sẽ đóng góp tích cực trong việc cải tiến sự hiểu biết của sinh viên về lĩnh vực đồ họa và mong nhận được sự góp ý của các đồng nghiệp và sinh viên để công việc biên soạn ngày càng được tốt hơn. Trang 1
  3. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Mục lục Chương 1: GIỚI THIỆU THUẬT TOÁN VẼ VÀ TÔ 6 CÁC ĐƯỜNG CƠ BẢN 6 1.1 Tổng quan 6 1.2. Hệ tọa độ thế giới thực, hệ tọa độ thiết bị và hệ tọa độ chuẩn 7 1.3. Thuật toán vẽ đoạn thẳng 9 1.3.1. Thuật toán DDA (Digital DifferentialAnalyzer) 10 1.3.2. Thuật toán Bresenham 13 1.4. Thuật toán vẽ đường tròn 17 1.4.1. Thuật toán đơn giản 17 1.4.2. Thuật toán MidPoint 18 1.4.3. Vẽ đường tròn bằng thuật toán Bresenham 21 1.4.4. Thuật toán vẽ Ellipse 22 1.4.5. Vẽ đường conics và một số đường cong khác 24 1.4.6. Vẽ đa giác 25 1.4.7. Tổng kết chương 1 28 1.4.8. Bài tập chương 1 28 Chương 2 : CÁC THUẬT TOÁN TÔ MÀU 31 2.1. Tổng quan 31 2.2. Các không gian màu 31 2.2.1. Không gian màu RGB (Red - Green - Blue) 31 2.2.2. Không gian màu CMY (Cyan - Magenta - Yellow) 32 2.2.3. Không gian màu HSV ( Hue - Saturation - Value ) 32 2.3. Các thuật toán tô màu 33 2.3.1. Tô đơn giản 33 2.3.2. Tô màu theo dòng quét (scan - line) 38 2.3.3. Phương pháp tô màu dựa theo đường biên 42 2.4. Tổng kết chương 2 45 2.5. Bài tập chương 2 46 Chương 3 : PHÉP BIẾN ĐỔI TRONG ĐỒ HỌA HAI CHIỀUU 47 3.1. Tổng quan 47 3.2. Phép tịnh tiến (translation) 47 3.3. Phép biến đổi tỷ lệ 48 3.4. Phép quay 49 3.5. Phép đối xứng 51 3.6. Phép biến dạng 51 3.7. Phép biến đổi Affine ngược ( The inverse of an Affine transformation) 52 3.8. Một số tính chất của phép biến đổi affine 53 3.9. Hệ tọa độ thuần nhất 53 3.10. Kết hợp các phép biến đổi (composing transformation) 54 3.11. Tổng kết chương 3 55 3.12. Bài tập chương 3 55 Chương 4 58 WINDOWING và CLIPPING 58 4.1. Tổng quan 58 4.2. Các khái niệm về Windowing 58 Trang 2
  4. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 4.3. Các thuật toán Clipping 63 4.4. Phép biến đổi từ cửa sổ - đến – vùng quan sát 84 4.5. Tổng kết chương 4 86 4.6. Bài tập chương 4 86 Chương 5 : ĐỒ HỌA BA CHIỀUU 88 5.1. Tổng quan 88 5.2. Giới thiệu đồ họa 3 chiều 88 5.3. Biểu diễn đối tượng 3 chiều 90 5.4. Các phép biến đổi 3 chiều 95 5.4.1. Hệ tọa độ bàn tay phải - bàn tay trái 95 5.4.2. Các phép biến đổi Affine cơ sở 95 5.5. Tổng kết chương 5 97 Chương 6 : QUAN SÁT ẢNH BA CHIỀUU 98 6.1. Tổng quan 98 6.2. Các phép chiếu 98 6.2.1. Các phép chiếu song song 100 6.2.2. Các phép chiếu phối cảnh 105 6.3. Biến đổi hệ tọa độ quan sát (hệ quan sát) 107 6.3.1. Xác định mặt phẳng quan sát 108 6.3.2. Không gian quan sát 112 6.3.3. Clipping 115 6.4. Cài đặt các thao tác quan sát (Implementation of Viewing Operations) 116 6.5. Cài đặt phần cứng 125 6.6. Lập trình xem ảnh ba chiều 126 6.7. Các mở rộng đến Đường ống quan sát (Viewing Pipeline) 130 6.8. Tổng kết chương 6 130 6.9. Bài tập chương 6 131 Chương 7 134 KHỬ CÁC MẶT KHUẤT VÀ ĐƯỜNG KHUẤT 134 7.1. Tổng quan 134 7.2. Khử các mặt nằm sau (Back-Face Removal) 135 7.3. Phương pháp dùng vùng đệm độ sâu (Depth-Buffer Method) 138 7.4. Phương pháp đường quét (Scan-Line Method) 140 7.5. Phương pháp sắp xếp theo độ sâu (Depth- Sorting Method) 143 7.6. Phương pháp phân chia vùng (Area- Subdivision Method) 147 7.7. Các phương pháp Octree (Octree Methods) 150 7.8. Loại bỏ các đường bị che khuất 154 7.9. Tổng kết chương 7 156 7.10. Bài tập chương 7 157 Trang 3
  5. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản PHẦN TỔNG QUAN 1. Mục đích yêu cầu Sau khi học xong môn này, sinh viên cần đạt được các yêu cầu sau: - Hiểu thế nào là đồ họa trên máy tính. - Thiết kế và cài đặt được các thuật toán vẽ các đường cơ bản như đường thẳng, đường tròn, - Thiết kế và cài đặt được các thuật toán tô một hình. - Sử dụng được các phép biến hình trong không gian 2 chiều, 3 chiều để làm thay đổi một hình ảnh đã có sẳn. - Có thể tạo một cửa sổ để cắt - dán một hình. - Hiểu khái niệm về các tiếp cận để mô phỏng được một hình ảnh trong không gian 3 chiều trên máy tính. 2. Đối tượng sử dụng Môn kỹ thuật đồ họa được giảng dạy cho sinh viên năm thứ tư của các khoa sau: - Chuyên ngành công nghệ thông tin. - Chuyên ngành điện tử (viễn thông, tự động hóa, ) - Chuyên ngành sư phạm (Toán tin, Lý tin ) 3. Nội dung cốt lõi Giáo trình Kỹ thuật đồ họa bao gồm 7 chương. - Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản - Chương 2: Các thuật toán tô màu - Chương 3: Phép biến đổi trong đồ họa 2 chiều - Chương 4: Tạo cửa sổ và cắt hình - Chương 5: Đồ họa 3 chiều - Chương 6: Quan sát ảnh 3 chiều - Chương 7: Khử các mặt khuất và đường khuất 4. Kiến thức tiên quyết - Kiến thức về hình học không gian và hình giải tích - Kiến thức lập trình căn bản, lập trình đồ họa - Kiến thức về cấu trúc dữ liệu, lập trình đệ qui Trang 4
  6. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 5. Danh mục tài liệu tham khảo - Donald Hearn, M. Pauline Baker; Computer Graphics; Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986. - F.S.Hill; Computer graphics ; 1990 - Vũ Mạnh Tường, Dương Anh Đức, Trần Đan Thư, Lý Quốc Ngọc. Giáo trình Nhập môn đồ họa & xử lý ảnh.1995. - VERA B.ANAND, người dịch TS Nguyễn Hữu Lộc. Đồ họa máy tính và Mô hình hóa hình học. Nhà xuất bản Thành Phố Hồ Chí Minh - 2000. - Foley, Van Darn, Feiner, Hughes, Phillips. Introduction à L'Infographie. 1995. - Lê Tấn Hùng, Huỳnh Quyết Thắng. Kỹ thuật đồ họa. Nhà xuất bản khoa học và kỹ thuật, Hà nội - 2000. Trang 5
  7. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Chương 1: GIỚI THIỆU THUẬT TOÁN VẼ VÀ TÔ CÁC ĐƯỜNG CƠ BẢN 1.1 Tổng quan • Mục tiêu của chương 1 Học xong chương này, sinh viên phải nắm bắt được các vấn đề sau: - Thế nào là hệ đồ họa - Thiết kế và cài đặt được các thủ tục vẽ và tô các đường cơ bản như đường thẳng, đường tròn, elip, và các đường cong khác. • Kiến thức cơ bản cần thiết Các kiến thức cơ bản cần thiết để học chương này bao gồm : - Các khái niệm toán học về đường thẳng như : đường thẳng là gì : dạng tổng quát phương trình đường thẳng, hệ số góc, tung độ dốc. - Hiểu rõ hình dáng của đường thẳng phụ thuộc vào hệ số góc như thế nào. - Phương trình tổng quát của đường tròn, ellippse ( không có tham số và có tham số). - Kĩ thuật lập trình: thiết lập thủ tục, hàm (lưu ý truyền qui chiếu và truyền giá trị). • Tài liệu tham khảo Donald Hearn, M. Pauline Baker. Computer Graphics . Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986 (chapters 3, 55-76). • Nội dung cốt lõi Thiết lập thủ tục vẽ : - Đường thẳng bằng giải thuật DDA - Đường thẳng bằng giải thuật Bresenham - Đường tròn bằng giải thuật đối xứng - Đường tròn bằng giải thuật Bresenham - Đường tròn bằng giải thuật MidPoint - Ellippse - Đa giác Trang 6
  8. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 1.2. Hệ tọa độ thế giới thực, hệ tọa độ thiết bị và hệ tọa độ chuẩn Một hệ mềm đồ họa được mô tả bao gồm 3 miền như sau : - Miền điều khiển : bao bọc toàn bộ hệ thống. - Miền thực : nằm trong miền điều khiển. Khi một số nào đó thâm nhập vào miền thực, nó sẽ được chuyển thành số thực dấu phẩy động, và khi có một số rời khỏi miền này thì nó sẽ được chuyển thành số nguyên có dấu 16 bits. - Miền hiển thị : nằm trong miền điều khiển nhưng phân biệt với miền thực. Chỉ có số nguyên 16 bits mới nằm trong miền hiển thị. Trong lĩnh vực kỹ thuật đồ họa, chúng ta phải hiểu được rằng thực chất của đồ họa là làm thế nào để có thể mô tả và biến đổi được các đối tượng trong thế giới thực trên máy tính. Bởi vì, các đối tượng trong thế giới thực được mô tả bằng tọa độ thực. Trong khi đó, hệ tọa độ thiết bị lại sử dụng hệ tọa độ nguyên để hiển thị các hình ảnh. Đây chính là vấn đề cơ bản cần giải quyết. Ngoài ra, còn có một khó khăn khác nữa là với các thiết bị khác nhau thì có các định nghĩa khác nhau. Do đó, cần có một phương pháp chuyển đổi tương ứng giữa các hệ tọa độ và đối tượng phải được định nghĩa bởi các thành phần đơn giản như thế nào để có thể mô tả gần đúng với hình ảnh thực bên ngoài. Hai mô hình cơ bản của ứng dụng đồ họa là dựa trên mẫu số hóa và dựa trên đặc trưng hình học. Trong ứng dụng đồ họa dựa trên mẫu số hóa thì các đối tượng đồ họa được tạo ra bởi lưới các pixel rời rạc. Các pixel này có thể đuợc tạo ra bằng các chương trình vẽ, máy quét, Các pixel này mô tả tọa độ xác định vị trí và giá trị mẫu. Thuận lợi của ứng dụng này là dể dàng thay đổi ảnh bằng cách thay đổi màu sắc hay vị trí của các pixel, hoặc di chuyển vùng ảnh từ nơi này sang nơi khác. Tuy nhiên, điều bất lợi là không thể xem xét đối tượng từ các góc nhìn khác nhau. Ứng dụng đồ họa dựa trên đặc trưng hình học bao gồm các đối tượng đồ họa cơ sở như đoạn thẳng, đa giác, Chúng được lưu trữ bằng các mô hình và các thuộc tính. Ví dụ : đoạn thẳng được mô hình bằng hai điểm đầu và cuối, có thuộc tính như màu sắc, độ dày. Người sử dụng không thao tác trực tiếp trên các pixel mà thao tác trên các thành phần hình học của đối tượng. a. Hệ tọa độ thế giới thực: Một trong những hệ tọa độ thực thường được dùng để mô tả các đối tượng trong thế giới thực là hệ tọa độ Descartes. Với hệ tọa độ này, mỗi điểm P được biểu diễn bằng một cặp tọa độ (xp,yp) với xp, yp ∈R (xem hình 1.1). Trang 7
  9. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Y P(xp,yp) yp O xp X Hình 1.1 : Hệ tọa độ thực. . Ox : gọi là trục hoành. . Oy : gọi là trục tung. . xp : hoành độ điểm P. . yp : tung độ điểm P. b. Hệ tọa độ thiết bị Hệ tọa độ thiết bị (device coordinates) được dùng cho một thiết bị xuất cụ thể nào đó, ví dụ như máy in, màn hình, Trong hệ tọa độ thiết bị thì các điểm cũng được mô tả bởi cặp tọa độ (x,y). Tuy nhiên, khác với hệ tọa độ thực là x, y ∈ N. Điều này có nghĩa là các điểm trong hệ tọa độ thực được định nghĩa liên tục, còn các điểm trong hệ tọa độ thiết bị là rời rạc. Ngoài ra, các tọa độ x, y của hệ tọa độ thiết bị chỉ biểu diễn được trong một giới hạn nào đó của N. Ví dụ : Độ phân giải của màn hình trong chế độ đồ họa là 640x480. Khi đó, x∈(0,640) và y∈(0,480) (xem hình 1.2). (0,0) (640,0) (0, 480) (640,480) Hình 1.2 : Hệ tọa độ trên màn hình. Trang 8
  10. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản c. Hệ tọa độ thiết bị chuẩn (Normalized device coordinates) Do cách định nghĩa các hệ tọa độ thiết bị khác nhau nên một hình ảnh hiển thị được trên thiết bị này là chính xác thì chưa chắc hiển thị chính xác trên thíết bị khác. Người ta xây dựng một hệ tọa độ thiết bị chuẩn đại diện chung cho tất cả các thiết bị để có thể mô tả các hình ảnh mà không phụ thuộc vào bất kỳ thiết bị nào. Trong hệ tọa độ chuẩn, các tọa độ x, y sẽ được gán các giá trị trong đoạn từ [0,1]. Như vậy, vùng không gian của hệ tọa độ chuẩn chính là hình vuông đơn vị có góc trái dưới (0, 0) và góc phải trên là (1, 1). Quá trình mô tả các đối tượng thực như sau (xem hình 1.3): màn hình Ảnh định nghĩa trên tọa độ thế Tọa độ chuẩn hóa Tọa độ thiết bị máy in giới thực. thiết bị khác Hình 1.3 : Hệ tọa độ trên màn hình. 1.3. Thuật toán vẽ đoạn thẳng Xét đoạn thẳng có hệ số góc 0 0. Với các đoạn thẳng dạng này, nếu (xi, yi) là điểm đã được xác định ở bước thứ i thì điểm kế tiếp (xi+1, yi+1) ở bước thứ i+1 sẽ là một trong hai điểm sau (xem hình vẽ 1.4) : xi+1= xi + 1 yi+1= yi + 1 yi Trang 9
  11. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản (xi+4,yi+3) (xi+2,yi+2) (xi+3,yi+2) (xi+1,yi+1) (xi,yi) Hình 1.4 : Các điểm vẽ gần với điểm muốn vẽ. Vấn đề đặt ra là chọn điểm vẽ như thế nào để đường thẳng được vẽ gần với đường thẳng muốn vẽ nhất và đạt được tối ưu hóa về mặt tốc độ ? 1.3.1. Thuật toán DDA (Digital DifferentialAnalyzer) Là thuật toán tính toán các điểm vẽ dọc theo đường thẳng dựa vào hệ số góc của phương trình đường thẳng y=mx+b. Δy Trong đó, m= , Δy = yi+1 - yi , Δx = xi+1 - xi Δx Nhận thấy trong hình vẽ 1.4 thì tọa độ của điểm x sẽ tăng 1 đơn vị trên mỗi điểm vẽ, còn việc quyết định chọn yi +1 là yi +1 hay yi sẽ phụ thuộc vào giá trị sau khi làm tròn của tung độ y. Tuy nhiên, nếu tính trực tiếp giá trị thực của y ở mỗi bước từ phương trình y=mx+b thì cần một phép toán nhân và một phép toán cộng số thực. yi +1 = mxi +1 + b = m(xi + 1) + b = mxi + b + m Để cải thiện tốc độ, người ta khử phép nhân trên số thực. Ta có : yi = mxi + b ⇒ yi +1 = yi + m → int(yi +1) • Tóm lại khi 0 1: chọn bước tăng trên trục y một đơn vị. xi +1 = xi + 1/m → int(xi +1) yi +1 = yi + 1 Trang 10
  12. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Hai trường hợp này dùng để vẽ một điểm bắt đầu từ bên trái đến điểm cuối cùng bên phải của đường thẳng (xem hình 1.5). Nếu điểm bắt đầu từ bên phải đến điểm cuối cùng bên trái thì xét ngược lại : • 0 1: xi +1:= xi – 1/m → int(xi+1) yi +1:= yi – 1 Hình 1.5 : Hai dạng đường thẳng có 0 1. Tương tự, có thể tính toán các điểm vẽ cho trường hợp m 1 (sinh viên tự tìm hiểu thêm). Trang 11
  13. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Lưu đồ thuật toán DDA Begin dx=x2-x1 dy=y2-y1 Yes No abs(dx)>abs(dy) step=abs(dx) step=abs(dy) x_inc=dx/step y_inc=dy/step x=x1;y= y1 putpixel(x1,y1,c) No k<=step Yes x = x+x_inc y = y+y_inc putpixel(round(x),round(y),c) End Trang 12
  14. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Cài đặt minh họa thuật toán DDA Procedure DDA ( x1, y1, x2, y2, color : integer ); Var dx, dy, step : integer; X_inc, y_inc , x, y : real ; Begin dx:=x2-x1; dy:=y2-y1; if abs(dx)>abs(dy) then steps:=abs(dx) else steps:=abs(dy); x_inc:=dx/steps; y_inc:=dy/steps; x:=x1; y:=y1; putpixel(round(x),round(y), color); for k:=1 to steps do begin x:=x+x_inc; y:=y+y_inc; putpixel(round(x),round(y), color); end; end; 1.3.2. Thuật toán Bresenham P2 y +1 i d2 yi+1 d1 yi P1 xi xi+1 = xi+1 Hình 1.6 : Dạng đường thẳng có 0<=m<=1. Trang 13
  15. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Gọi (xi +1,yi +1) là điểm thuộc đoạn thẳng (xem hình 1.6). Ta có y:= m(xi +1)+b. Đặt d1 = yi +1 - yi d2 = (yi +1) - yi +1 Việc chọn điểm (xi +1, yi +1) là P1 hay P2 phụ thuộc vào việc so sánh d1 và d2 hay dấu của d1-d2. - Nếu d1-d2<0 : chọn điểm P1, tức là yi +1= yi - Nếu d1-d2 ≥0 : chọn điểm P2, tức là yi +1= yi +1 Xét Pi = Δx (d1 - d2) Ta có : d1 - d2 = 2 yi+1 - 2yi - 1 = 2m(xi+1) + 2b - 2yi - 1 ⇒ Pi = Δx (d1 - d2) = Δx[2m(xi+1) + 2b - 2yi - 1] Δy = Δx[2 (x +1) + 2b - 2y - 1] Δx i i = 2Δy(xi+1) - 2Δx.yi + Δx(2b - 1) = 2Δy.xi - 2Δx.yi + 2Δy + Δx(2b - 1) Vậy C = 2Δy + Δx(2b - 1) = Const ⇒ Pi = 2Δy.xi - 2Δx.yi + C 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ì xem như ta xác định được điểm cần chọn ở bước (i+1). Ta có : Pi +1 - Pi = (2Δy.xi+1 - 2Δx.yi+1 + C) - (2Δy.xi - 2Δx.yi + C ) ⇔ Pi +1 = Pi + 2Δy - 2Δx ( yi+1 - .yi ) - Nếu Pi < 0 : chọn điểm P1, tức là yi +1= yi và Pi +1 = Pi + 2Δy. - Nếu Pi ≥ 0 : chọn điểm P2, tức là yi +1= yi +1 và Pi +1 = Pi + 2Δy - 2Δx - Giá trị P0 được tính từ điểm vẽ đầu tiên (x0 ,y0 ) theo công thức : P0 = 2Δy.x0 - 2Δx.y0 + C Do (x0 ,y0 ) là điểm nguyên thuộc về đoạn thẳng nên ta có : Δy y = m .x + b = .x + b 0 0 Δx 0 Thế vào phương trình trên ta được : P0 = 2Δy - Δx Trang 14
  16. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Lưu đồ thuật toán Bresenham Begin dx = x2-x1; dy = y2 - y1; P = 2dy-dx; c1 = 2dy; c2 = 2(dy-dx); x = x1; y = y1; putpixel (x,y,color); No x < x2 Yes No P < 0 Yes P = P + c1 P = P + c2 y = y + 1 x = x +1 putpixel(x,y,color) End Trang 15
  17. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Cài đặt minh họa thuật toán Bresenham Procedure Bres_Line (x1,y1,x2,y2 : integer); Var dx, dy, x, y, P, const1, const2 : integer; Begin dx : = x2 - x1; dy : = y2 - y1; P : = 2*dy - dx; Const1 : = 2*dy ; const2 : = 2*(dy - dx) ; x:= x1; y:=y1; Putpixel ( x, y, Color); while (x < x-2 ) do begin x : = x +1 ; if (P < 0) then P : = P + const1 else begin y : = y+1 ; P : = P + const2 end ; putpixel (x, y, color) ; end ; End ; Nhận xét : Thuật toán Bresenham chỉ thao tác trên số nguyên và chỉ tính toán trên phép cộng và phép nhân 2 (phép dịch bit). Điều này là một cải tiến làm tăng tốc độ đáng kể so với thuật toán DDA. Ý tưởng chính của thuật toán này là ở chổ xét dấu Pi để quyết định điểm kế tiếp, và sử dụng công thức truy hồi Pi +1 - Pi để tính Pi bằng các phép toán đơn giản trên số nguyên. Tuy nhiên, việc xây dựng trường hợp tổng quát cho thuật toán Bresenham có phức tạp hơn thuật toán DDA. Trang 16
  18. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 1.4. Thuật toán vẽ đường tròn Trong hệ tọa độ Descartes, phương trình đường tròn bán kính R có dạng: Với tâm O(0,0) : x2 + y2 = R2 2 2 2 Với tâm C(xc,yc): (x - xc ) + (y - yc ) = R Trong hệ tọa độ cực : x = xc + R.cosθ y = yc + Y.sinθ với θ ∈ [0, 2π]. Do tính đối xứng của đường tròn C (xem hình 1.7) nên ta chỉ cần vẽ 1/8 cung tròn, sau đó lấy đối xứng qua 2 trục tọa độ và 2 đường phân giác thì ta vẽ được cả đường tròn. y (-x,y) (x,y) (-y,x) (y,x) R 2 x 2 (-y,-x) (y,-x) (-x,-y) (x,-y) Hình 1.7 : Đường tròn với các điểm đối xứng. 1.4.1. Thuật toán đơn giản Cho x = 0, 1, 2, , int( R 2 ) với R>1. 2 - Tại mỗi giá trị x, tính int(y = R2− x 2 ). - Vẽ điểm (x,y) cùng 7 điểm đối xứng của nó. Cài đặt minh họa thuật toán đơn giản. Trang 17
  19. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Procedure Circle (xc, yc, R : integer) ; Var x, y : integer ; Procedure DOIXUNG ; Begin putpixel (xc + x , yc +y, color) ; putpixel (xc - x , yc + y, color) ; putpixel (xc + x , yc - y, color) ; putpixel (xc - x , yc- y, color) ; putpixel (xc + y , yc + x, color) ; putpixel (xc - y , yc + x, color) ; putpixel (xc + y , yc - x, color) ; putpixel (xc - y , yc - x, color) ; End ; Begin For x : = 0 to round(R*Sqrt(2)/2) do Begin y : = round(Sqrt(R*R - x*x)) ; DOIXUNG; End ; End ; 1.4.2. Thuật toán xét điểm giữa (MidPoint) Do tính đối xứng của đường tròn nên ta chỉ cần vẽ 1/8 cung tròn, sau đó lấy đối xứng là vẽ được cả đường tròn. Thuật toán MidPoint đưa ra cách chọn yi+1 là yi hay yi-1 bằng cách so sánh điểm thực Q(xi+1,y) với điểm giữa MidPoind là trung điểm của S1 và S2. Chọn điểm bắt đầu để vẽ là (0,R). Giả sử (xi, yi) là điểm nguyên đã tìm được ở bước thứ i (xem hình 1.8), thì điểm (xi+1, yi+1) ở bước i+1 là sự lựa chọn giữa S1 và S2. xi+1= xi + 1 yi+1= yi - 1 yi Trang 18
  20. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản (xi,yi) S1 Q(xi+1,y) yi yi+1 MidPoint yi - 1 S2 Hình 1.8 : Đường tròn với điểm Q(xi+1, y) và điểm MidPoint. Đặt F(x,y) = x2 + y2 - R2 , ta có : . F(x,y) 0 , nếu điểm (x,y) nằm ngoài đường tròn. Xét Pi = F(MidPoint) = F(xi +1, yi - 1/2). Ta có : - Nếu Pi = 0 : điểm MidPoint nằm ngòai đường tròn. Khi đó, điểm thực Q gần với điểm S2 hơn nên ta chọn yi+1 = yi - 1. Mặt khác : Pi+1 - Pi = F(xi+1 +1, yi+1 - 1/2) - F(xi + 1, yi - 1/2) 2 2 2 2 2 2 = [(xi+1 +1) + (yi+1 - 1/2) - R ] - [(xi +1) + (yi - 1/2) - R ] 2 2 = 2xi + 3 + ((yi+1) + (yi) ) - (yi+1 - yi) Vậy : - Nếu Pi = 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + 2xi - 2yi +5. - Pi ứng với điểm ban đầu ( x0 , y0 ) = (0,R) là: 5 P0 = F(x0 + 1, y0 - 1/2) = F(1, R - 1/2) = -R 4 Trang 19
  21. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Lưu đồ thuật toán MidPoint vẽ đường tròn Begin P = 5/4 - R; x=0 ; y= R; Putpixel(x,y,c); No x < y Yes No P < 0 Yes P = P + 2*x + 3 P = P + 2*(x-y)+5 y = y -1 x = x +1 putpixel(x,y,color) End Trang 20
  22. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Minh họa thuật toán MidPoint: Procedure DTR(xc, yc, r, mau : integer); var x, y, p : integer ; begin x:=0 ; y:=r; p:=1 - r; while ( y > x) do begin doi_xung; if (p<0) then p:=p+2*x+3 else begin p:=p+2*(x-y)+5 ; y:=y-1; end; x:=x+1; end; {while} end; 1.4.3. Vẽ đường tròn bằng thuật toán Bresenham Tương tự thuật toán vẽ đường thẳng Bresenham, các vị trí ứng với các tọa độ nguyên nằm trên đường tròn có thể tính được bằng cách xác định một trong hai pixel gần nhất với đường tròn thực hơn trong mỗi bước ( xem hình 1.9). (xi,yi) S1 yi d1 yi+1 = y d2 yi - 1 S2 Hình 1.9 : Đường tròn với khoảng cách d1 và d2. Trang 21
  23. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Ta có : 2 2 2 2 2 d1 = (yi) - y = (yi) - (R - (xi + 1) ) 2 2 2 2 2 d2 = y - (yi - 1) = (R - (xi + 1) ) - (yi - 1) Pi = d1 - d2 Tính Pi+1 - Pi 2 2 ⇒ Pi+1 = Pi + 4xi + 6 + 2((yi+1) - (yi) ) - 2(yi+1 - yi) - Nếu Pi = 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + 4(xi - yi ) + 10. - P0 ứng với điểm ban đầu ( x0 , y0 ) = (0,R) là: P0= 3 - 2R. Minh họa thuật toán vẽ đường tròn bằng Bresenham Procedure DTR_BRES(xc,yc,r,mau : integer); var x,y,p:integer; begin x:=0 ; y:=r; p:= 3 – 2*r ; while ( x<y ) do begin doi_xung; if (p<0) then p:= p + 4*x + 6 else begin p:= p + 4*(x-y) + 10 ; y:=y-1; end; x:=x+1; end;{while} end; 1.4.4. Thuật toán vẽ Ellipse Tương tự thuật toán vẽ đường tròn, sử dụng thuật toán Bresenham để vẽ, ta chỉ cần vẽ 1/4 ellipse, sau đó lấy đối xứng qua các trục tọa độ sẽ vẽ được toàn bộ ellipse. x 2 y 2 Xét ellipse có tâm O, các bán kính là a và b, phương trình là : + = 1 a 2 b 2 Trang 22
  24. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Chọn tọa độ pixel đầu tiên cần hiển thị là (xi ,yi) = (0,b). Cần xác định pixel tiếp theo là (xi+1 ,yi+1). Ta có : xi+1= xi + 1 yi+1= yi - 1 yi 2 2 d1 = (yi) - y 2 2 d2 = y - (yi - 1) Pi = d1 - d2 Tính Pi+1 - Pi 2 2 2 2b ⇒ Pi+1 = Pi + 2((yi+1) - (yi) ) - 2(yi+1 - yi) + (2xi + 3) a 2 2b 2 - Nếu Pi = 0 : chọn yi+1 = yi - 1. Khi đó Pi+1 = Pi + (2xi +3) +4(1- yi) a 2 2b 2 - Pi ứng với điểm ban đầu ( x0 , y0 ) = (0,b) là: P0 = - 2b + 1 a 2 Minh họa thuật toán vẽ Ellipse Procedure Ellipse(xc,yc,a,b : integer); var x,y : integer; z1, z2, P : real; procedure dx; begin putpixel (xc + x , yc +y, color) ; putpixel (xc - x , yc + y, color) ; putpixel (xc + x , yc - y, color) ; putpixel (xc - x , yc- y, color) ; end; begin x:=0 y:=b; Trang 23
  25. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản z1:= (b*b)/(a*a); z2:= 1/ z1; P:= 2*z1 - 2*b +1; while (z1* (x/y) ≤ 1) do begin dx; if P < 0 then P:= P + 2*z1*(2*x+3) else begin P:= P + 2*z1*(2*x+3) + 4*(1-y); y:= y -1; end; x:= x+1; end; x:=a ; y:= 0; P:= 2*z2 - 2*a +1; while (z2* (y/x) < 1) do begin dx; if P < 0 then P:= P + 2*z2*(2*y+3) else begin P:= P + 2*z2*(2*y+3) + 4*(1-x); x:= x -1; end; y:= y +1; end; end; 1.4.5. Vẽ đường conics và một số đường cong khác Phương trình tổng quát của các đường conics có dạng : Ax2 + Bxy + Cy2 + Dx + Ey + F = 0 Trang 24
  26. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Giá trị của các hằng số A, B, C, D, E, F sẽ quyết định dạng của đường conics, cụ thể là nếu: B2 - 4AC 0 : dạng hyperbol. Áp dụng ý tưởng của thuật toán Midpoint để vẽ các đường conics và một số đường cong khác theo các bước theo các bước tuần tự sau: - Bước 1: Dựa vào dáng điệu và phương trình đường cong, để xem thử có thể rút gọn phần đường cong cần vẽ hay không. - Bước 2: Tính đạo hàm, từ đó phân thành các vùng vẽ. . Nếu 0 ≤ f '(x) ≤ 1 : xi+1 = xi + 1; yi+1 = yi (hoặc = yi +1) . Nếu -1≤ f '(x) ≤ 0 : xi+1 = xi + 1; yi+1 = yi (hoặc = yi - 1) . Nếu f '(x) > 1 : yi+1 = yi + 1; xi+1 = xi (hoặc = xi +1) . Nếu f '(x) < -1 : yi+1 = yi + 1; xi+1 = xi (hoặc = xi +1) - Bước 3 : Tính Pi cho từng trường hợp để quyết định f '(x) dựa trên dấu của Pi. Pi thường là hàm được xây dựng từ phương trình đường cong. Cho Pi=0 nếu (xi , yi) thuộc về đường cong. Việc chọn Pi cần chú ý sao cho các thao tác tínn Pi sau này hạn chế phép toán trên số thực. - Bước 4 : Tìm mối liên quan của Pi+1 và Pi bằng cách xét hiệu Pi+1 - Pi - Bước 5 : Tính P0 và hoàn chỉnh thuật toán. 1.4.6. Vẽ đa giác Đường gấp khúc hở Đường gấp khúc kín Hình 1.10 : Hai dạng của đường gấp khúc. Trang 25
  27. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản • Định nghĩa đa giác (Polygone): Đa giác là một đường gấp khúc kín có đỉnh đầu và đỉnh cuối trùng nhau (xem hình 1.10) • Xây dựng cấu trúc dữ liệu để vẽ đa giác Type d_dinh = record x,y: longint; end; dinh = array[0 10] of d_dinh; var d: dinh; Với cách xây dựng cấu trúc dữ liệu như thế này thì chúng ta chỉ cần nhập vào tọa độ các đỉnh và sau đó gọi thủ tục vẽ đường thẳng lần lượt qua 2 đỉnh như (0, 1), (1,2), , (n-1, n), trong đó đỉnh n trùng với đỉnh 0 thì ta sẽ vẽ được toàn bộ đa giác. • Đa giác được gọi là lồi nếu bất kỳ đường thẳng nào đi qua một cạnh của đa giác thì toàn bộ đa giác nằm về một phía của đường thẳng đó. Ngược lại, nếu tồn tại ít nhất một cạnh của đa giác chia đa giác làm 2 phần thì gọi là đa giác lõm (xem hình 1.11). P0 P3 d 4 P0 d0 P4 P1 P2 d 3 P4 d2 d1 P3 P2 P5 Hình 1.11 : Đa giác lồi và đa giác lõm • Thuật toán kiểm tra một đa giác là lồi hay lõm Thuật toán 1: Lần lượt thiết lập phương trình đường thẳng đi qua các cạnh của đa giác. Ứng với từng phương trình đường thẳng, xét xem các đỉnh còn lại có nằm về một Trang 26
  28. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản phía đối với đường thẳng đó hay không ? Nếu đúng thì kết luận đa giác lồi, ngược lại là đa giác lõm. Nhận xét : Phương trình đường thẳng y = ax + b chia mặt phẳng ra làm 2 phần. Các điểm nằm C(xc,yc) trên đường thẳng sẽ có yc > axc + b và các điểm D(xd,yd) nằm phía dưới đường thẳng sẽ có yd axc + b = .0 + 1 2 1 và Yd = 0 < axd + b = .2 + 1 2 Vậy hai điểm C, D nằm về hai phía đối với đường thẳng AB. Thuật toán 2 : Nhận xét : Trong mặt phẳng Oxy, cho 2 véc tơ a và b , Tích vô hướng của 2 véc tơ là : ax a y T(a , b ) = = ax* by - ay * bx bx b y Khi đó : a quẹo trái sang b nếu T ≥0 a quẹo phải sang b nếu T < 0 Trang 27
  29. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản Một đa giác là lồi khi đi dọc theo biên của nó thì chỉ đi theo một hướng mà thôi. Nghĩa là chỉ quẹo phải hay quẹo trái. Ngược lại là đa giác lõm (xem hình 1.13). v V 0 v V 4 P0 P1 v V1 P4 P2 v V 3 P3 v V 2 Hình 1.13 : Đa giác lồi có 5 đỉnh. Xét đa giác gồm các đỉnh P0, P1 , Pn , ( P0 = Pn ) , n ≥ 3 (xem hình 1.13). Tính Vi = Pi+1 - Pi , ∀i = 0, 1, , n-1. Tính Ti = T( Vi , Vi+1 ) Nếu với mọi Ti đều cùng dấu thì kết luận đa giác lồi. Ngược lại, là đa giác lõm. 1.4.7. Tổng kết chương 1 - Chương 1 đã trình bày khái niệm về một hệ độ họa, sự hiển thị của điểm trên màn hình với tọa độ phài là số nguyên. - Phân biệt thế nào là hệ tọa độ thế giới thực, hệ tọa độ thiết bị và hệ tọa độ chuẩn. - Cần lưu ý về hệ số góc của đường thẳng. Bởi vì, với hệ số góc khác nhau thì giải thuật có thay đổi. Nhất là trong giải thuật Bresenham. - Chú ý hơn trong cách xây dựng cấu trúc dữ liệu để lưu tọa độ của các đỉnh đa giác. - So sánh các trường hợp sử dụng công thức của các đường cong (có tham số và không có tham số). 1.4.8. Bài tập chương 1 1. Viết chương trình vẽ bầu trời có 10.000 điểm sao, mỗi điểm sao xuất hiện với một màu ngẫu nhiên. Những điểm sao này hiện lên rồi từ từ tắt cũng rất ngẫu nhiên. Trang 28
  30. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 2. Viết chương trình thực hiện 2 thao tác sau : - Khởi tạo chế độ đồ họa, đặt màu nền, đặt màu chữ, định dạng chữ (settextstyle(f,d,s)), xuất một chuổi ký tự ra màn hình. Đổi font, hướng, kích thước. - Xuất một chuổi ra màn hình, chuổi này có tô bóng. (lưu ý rằng nội dung chuổi ký tự, màu tô, màu bóng là được nhập từ bàn phím). 3. Viết chương trình vẽ đoạn thẳng AB với màu color theo giải thuật DDA. Biết rằng tọa độ A,B, color được nhập từ bàn phím. Trang trí màu nền, ghi chú các tọa độ A, B ở hai đầu đoạn thẳng. 4. Tương tự như bài tập 3 nhưng sử dụng giải thuật Bresenham. Lưu ý các trường hợp đặc biệt của hệ số góc. 5. Tổng hợp bài tập 4, viết chương trình vẽ đường thằng bằng giải thuật Bresenham cho tất cả các trường hợp của hệ số góc. Lưu ý xét trường hợp đặc biệt khi đường thẳng song song với trục tung hay với trục hoành. 6. Viết chương trình nhập tọa độ 3 điểm A, B, C từ bàn phím. Tìm tọa độ điểm D thuộc AB sao cho CD vuộng góc AB. Vẽ đoạn thẳng AB và CD. 7. Viết chương trình xét vị trí tương đối của 2 đoạn thẳng AB và CD. Biết rằng trong màn hình đồ họa đoạn thẳng AB và CD được gọi là cắt nhau khi hai điểm A, B ở về hai phía của CD và ngược lại. 8. Viết chương trình vẽ đường tròn theo giải thuật đơn giản ( đối xứng ). 9. Viết chương trình vẽ đường tròn theo giải thuật Bresenham. 10. Viết chương trình vẽ đường tròn theo giải thuật MidPoint. 11. Viết chương trình vẽ một đường tròn tâm O bán kính R. Vẽ các đường tròn đồng tâm với O, có bán kính chạy từ 1 đến R. Sau đó xoá các đường tròn đồng tâm này và vẽ các đường tròn đồng tâm khác đi từ R đến 1. 12. Viết chương trình vẽ một đường tròn tâm O bán kính R. Hãy vẽ một đoạn thẳng từ tâm O độ dài R. Hãy quay đoạn thẳng này quanh đường tròn. 13. Viết chương trình vẽ Elippse. 14. Viết chương trình vẽ Elippse có bán kính lớn là a, bán kính nhỏ là b và một đường tròn nội tiếp Elippse. Tô đường tròn bằng các đường tròn đồng tâm. Sau đó tô elippse bằng các elippse đồng tâm có bán kính lớn chạy từ b đến a, bán kính nhỏ là b. Trang 29
  31. Chương 1: Giới thiệu thuật toán vẽ và tô các đường cơ bản 15. Viết chương trình vẽ một hình chữ nhật, một hình vuông và một hình bình hành. Yêu cầu chú thích tọa độ các đỉnh. 16. Viết chương trình vẽ một tam giác. Tọa độ các đỉnh được nhập từ bàn phím, mỗi cạnh có một màu khác nhau. 17. Viết chương trình vẽ một đa giác có n đỉnh. 18. Viết chương trình xét tính lồi lõm của một đa giác bằng cách thiết lập phương trình đường thẳng đi qua các cạnh của đa giác. 19. Viết chương trình xét tính lồi lõm của một đa giác bằng cách thiết lập các véc tơ chỉ phương của các cạnh. Trang 30
  32. Chương 2: Các thuật toán tô màu Chương 2 : CÁC THUẬT TOÁN TÔ MÀU 2.1. Tổng quan • Mục tiêu Học xong chương này, sinh viên phải nắm bắt được các vấn đề sau: - Hiểu được khái niệm về không gian màu RGB,CMY, HSV. - Thiết kế và cài đặt được các giải thuật tô màu. • Kiến thức cơ bản cần thiết Kiến thức tin học : lập trình cấu trúc dữ liệu, cách lưu trữ và xây dựng mãng dữ liệu chứa các giao điểm của đường thẳng và đa giác. Kỹ năng lập trình đệ qui, tạo stack khử đệ qui. • Tài liệu tham khảo Computer Graphics . Donald Hearn, M. Pauline Baker. Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986 ( chapters 4, 78-103) • Nội dung cốt lõi - Trình bày các không gian màu RGB, CMY, HSV - Giới thiệu các thuật toán tô màu bao gồm : tô đơn giản, tô theo đường biên và tô scan-line 2.2. Các không gian màu 2.2.1. Không gian màu RGB (Red - Green - Blue) Không gian màu RGB mô tả màu sắc bằng 3 thành phần chính là Red - Green và Blue. Không gian này được xem như một khối lập phương 3 chiều với màu red là trục x, màu Green là truc y, và màu Blue là trục z. Mỗi màu trong không gian này được xác định bởi 3 thành phần R, G, B. Ứng với các tổ hợp khác nhau của 3 màu này sẽ cho ta một màu mới (xem hình 2.1). Trang 31
  33. Chương 2: Các thuật toán tô màu Green (0,1,0) Yellow (1,1,0) Cyan (1,1,1) (0,1,1) White 0 Red (1,0,0) x Black Magent Blue a (0,0,1) (1,0,1) z Hình 2.1 : Không gian màu RGB. Nhận xét : Trong hình lập phương trên (xem hình 2.1), mỗi màu gốc (R,G,B) có các gốc đối diện là các màu bù với nó. Hai màu được gọi là bù nhau khi kết hợp hai màu này lại với nhau ra màu trắng. Ví dụ : Green - Magenta, Red - Cyan, Blue - Yellow. 2.2.2. Không gian màu CMY (Cyan - Magenta - Yellow) Tương tự như không gian màu RGB nhưng 3 thành phần chính là Cyan - Magenta - Yellow. Do đó, tọa độ các màu trong không gian CMY trái ngược với không gian RGB. Ví dụ : màu White có các thành phần là (0,0,0), màu Black (1,1,1), màu Cyan (1,0,0), 2.2.3. Không gian màu HSV ( Hue - Saturation - Value ) Thực chất của không gian này là sự biến đổi của không gian RGB. Không gian HSV được mô tả bằng lệnh lập phương RGB quay trên đỉnh Black. H (Hue) là góc quay trục V (value) qua 2 đỉnh Black và White ( xem hình 2.2). Các gía trị biến thiên của H, S, V như sau : H (Hue) chỉ sắc thái có giá trị từ 00 - 3600 . S (Saturation) chỉ độ bảo hoà. V (Value) có giá trị từ 0 - 1. Các màu đạt giá trị bảo hòa khi s = 1 và v = 1. Trang 32
  34. Chương 2: Các thuật toán tô màu V=1 Green Yellow H Cyan While S Red Blue Magenta RGB HSV Red (1,0,0) (00,1,1) Yellow (1,1,0) (600,1,1) Black Hình 2.2 : Không gian màu HSV. 2.3. Các thuật toán tô màu Tô màu một vùng là thay đổi màu sắc của các điểm vẽ nằm trong vùng cần tô. Một vùng tô thường đựơc xác định bởi một đường khép kín nào đó gọi là đường biên. Dạng đường biên đơn giản thường gặp là đa giác. Việc tô màu thường chia làm 2 công đoạn : . Xác định vị trí các điểm cần tô màu. . Quyết định tô các điểm trên bằng màu nào. Công đoạn này sẽ trở nên phức tạp khi ta cần tô theo một mẫu tô nào đó chứ không phải tô thuần một màu. Có 3 cách tiếp cận chính để tô màu. Đó là : tô màu theo từng điểm (có thể gọi là tô đơn giản), tô màu theo dòng quét và tô màu dựa theo đường biên. 2.3.1. Tô đơn giản Thuật toán này bắt đầu từ việc xác định một điểm có thuộc vùng cần tô hay không ? Nếu đúng là điểm thuộc vùng cần tô thì sẽ tô với màu muốn tô. Trang 33
  35. Chương 2: Các thuật toán tô màu • Tô đường tròn - Để tô đường tròn thì ta tìm hình vuông nhỏ nhất ngoại tiếp đường tròn bằng cách xác định điểm trên bên trái (xc-r, yc-r) và điểm dưới bên phải (xc+r, yc+r) của hình vuông (xem hình 2.2). - Cho i đi từ xc-r đến xc+r Cho j đi từ yc-r đến yc+r Tính khoảng cách d giữa hai điểm (i,j) và tâm (xc,yc) Nếu d<r thì tô điểm (i,j) với màu muốn tô (0,0) xc - r xc xc + r yc - r r yc (xc,yc) yc + r Hình 2.3 : đường tròn nội tiếp hình vuông. • Tô đa giác - Tìm hình chữ nhật nhỏ nhất có các cạnh song song với hai trục tọa độ chứa đa giác cần tô dưa vào hai tọa độ (xmin, ymin), (xmax, ymax). Trong đó, xmin, ymin là hoành độ và tung độ nhỏ nhất, xmax, ymax là hoành độ và tung độ lớn nhất của các đỉnh của đa giác. - Cho x đi từ xmin đến xmax, y đi từ ymin đến ymax (hoặc ngược lai). Xét điểm P(x,y) có thuộc đa giác không ? Nếu có thì tô với màu cần tô (xem hình 2.4). Trang 34
  36. Chương 2: Các thuật toán tô màu Y Ymax Ymin X Xmin Xmax Hình 2.4 : đa giác nội tiếp hình chữ nhật. Thông thường một điểm nằm trong đa giác thì số giao điểm từ một tia bất kỳ xuất phát từ điểm đó cắt biên của đa giác phải là một số lẻ lần. Đặc biệt, tại các đỉnh cực trị (cực đại hay cực tiểu ) thì một giao điểm phải được tính 2 lần (xem hình 2.5). Tia có thể qua phải hay qua trái. Thông thường ta chọn tia qua phải. Ví dụ : Xét đa giác gồm 13 đỉnh là P0 , P1 , , P12 = P0 (xem hình 2.5). P8 P1 P3 P P6 P7 P2 Q P0 P4 P5 P9 P11 P12 P10 Hình 2.5 : Đa giác có 13 đỉnh. Lưu ý : Trang 35
  37. Chương 2: Các thuật toán tô màu Gọi tung độ của đỉnh Pi là Pi.y . Nếu : - Pi.y Max ( Pi+1.y, Pi-1.y) thì Pi là đỉnh cực trị ( cực tiểu hay cực đại ). - Pi-1.y Pi.y > Pi+1.y thì Pi là đỉnh đơn điệu. - Pi = Pi+1 và Pi.y Max ( Pi+2.y, Pi-1.y) thì đoạn [Pi,Pi+1] là đoạn cực trị ( cực tiểu hay cực đại ). - Pi = Pi+1 và Pi-1.y Pi.y > Pi+2.y thì đoạn [Pi,Pi+1] là đoạn đơn điệu. • Thuật toán kiểm tra điểm có nằm trong đa giác - Với mỗi đỉnh của đa giác ta đánh dấu là 0 hay 1 theo qui ước như sau: nếu là đỉnh cực trị hay đoạn cực trị thì đánh số 0. Nếu là đỉnh đơn điệu hay đoạn đơn điệu thì đánh dấu 1. - Xét số giao điểm của tia nữa đường thẳng từ P là điểm cần xét với biên của đa giác. Nếu số giao điểm là chẳn thì kết luận điểm không thụôc đa giác. Ngược lại, số giao điểm là lẻ thì điểm thuộc đa giác. • Minh họa thuật toán xét điểm thuộc đa giác function PointInpoly(d: dinh; P: d_dinh; n: integer): boolean; var count, i: integer; x_cut: longint; function next(i: integer): integer; begin next := (i + n + 1) mod n end; function prev(i: integer): integer; begin prev := (i + n - 1) mod n end; begin count := 0; for i := 0 to n-1 do Trang 36
  38. Chương 2: Các thuật toán tô màu if d[i].y = P.y then begin if d[i].x > P.x then begin if ((d[prev(i)].y P.y) and (P.y > d[next(i)].y)) then count := count + 1; if d[next(i)].y = P.y then if ((d[prev(i)].y P.y and (P.y > d[next(next(i))].y)) then count := count + 1; end; end else {d[i].y = P.y} if ((d[i].y P.y) and (P.y > d[next(i)].y)) then begin x_cut := d[i].x + Round((d[next(i)].x - d[i].x) / (d[next(i)].y - d[i].y) * (P.y - d[i].y)); if x_cut >= P.x then count := count + 1; end; if (count mod 2 = 0) then PointInPoly := false else PointInpoly := true; end; • Minh họa thuật toán tô đa giác (xmin, ymin, xmax, ymax: đã khai báo trong chương trình chính.) Procedure Todg ( d:dinh; n,maubien : integer ; d: dinh; n:integer ) ; var x, y:integer; P: d_dinh; begin for x:=xmin to xmax do for y:= ymin to ymax do Trang 37
  39. Chương 2: Các thuật toán tô màu begin P.x:= x; P.y := y; if pointInpoly (d, P, n) then if getpixel(x,y)<>maubien then putpixel(x,y,color); end; end; • Nhận xét: Thuật toán tô đơn giản có ưu điểm là tô rất mịn và có thể sử dụng được cho đa giác lồi hay đa giác lõm, hoặc đa giác tự cắt, đường tròn, ellipse. Tuy nhiên, giải thuật này sẽ trở nên chậm khi ta phải gọi hàm PointInpoly nhiều lần. Để khắc phục nhược điểm này người ta đưa ra thuật toán tô màu theo dòng quét. 2.3.2. Tô màu theo dòng quét (scan - line) Phương pháp này sẽ xác định phần giao của các dòng quét kế tiếp nhau với đường biên của vùng tô. Sau đó, sẽ tiến hành tô màu các điểm thuộc phần giao này. Phương pháp này thường được dùng để tô màu đa giác lồi , lõm hay đa giác tự cắt, đường tròn, ellipse, và một số đường cong đơn giản khác. • Các bước chính của thuật toán - Tìm ymin, ymax lần lượt là giá trị nhỏ nhất, lớn nhất của tập các tung độ của các đỉnh của đa giác đã cho. - Ứng với mỗi dòng quét y = k với k thay đổi từ ymin đến ymax, lặp : . Tìm tất cả các hoành độ giao điểm của dòng quét y = k với các cạnh của đa giác. . Sắp xếp các hoành độ giao điểm theo thứ tự tăng dần : x0 ,x1 , , xn , . Tô màu các đoạn thẳng trên đường thẳng y = k lần lượt được giới hạn bởi các cặp (x0, x1), ( x1 ,x2 ), (xem hình 2.6). Trang 38
  40. Chương 2: Các thuật toán tô màu Hình 2.6 : Tô đa giác bằng giải thuật scan -line. • Các vấn đề cần lưu ý: - Hạn chế đụơc số cạnh cần tìm giao điểm ứng với mỗi dòng quét vì ứng với mỗi dòng quét không phải lúc nào cũng giao điểm với các cạnh của đa giác. - Xác định nhanh hoàn độ giao điểm vì nếu lặp lại thao tác tìm giao điểm của cạnh đa giác với mỗi dòng quét sẽ tốn rất nhiều thời gian. - Giải quyết trường hợp số giao điểm đi qua đỉnh đơn điệu thì tính số giao điểm là 1 hay đi qua đỉnh cực trị.thì tính số giao điểm là 0 (hoặc 2). • Tổ chức cấu trúc dữ liệu và thuật toán - Danh sách các cạnh (Edge Table - ET) : chứa toàn bộ các cạnh của đa giác (loại các cạnh song song với trục Ox) được sắp theo thứ tự tăng dần của trục y. Xem hình 2.5 ta có thể sắp xếp các cạnh trong ET là : AB, AI, HG, BC, GF, DC, EF (loại IH và DE) - Danh sách các cạnh đang kích họat (Active Edge Table - AET) : chứa các cạnh của đa giác có thể cắt ứng với dòng quét hiện hành, các cạnh này được sắp theo thứ tự tăng dần của hoành độ giao điểm của hoành độ giao điểm giữa cạnh và dòng quét. - Khi dòng quét đi từ ymin đến ymax, các cạnh thoả điều kiện sẽ được chuyển từ ET sang AET. Nghĩa là, khi dòng quét y=k bắt đầu cắt một cạnh, khi đó k ≥ ymin, cạnh này sẽ được chuyển từ ET sang AET. Khi dòng quét không còn cắt cạnh này nữa, khi Trang 39
  41. Chương 2: Các thuật toán tô màu đó, k > ymax, cạnh này sẽ bị loại khỏi AET. Khi không còn cạnh nào trong ET hay AET thì quá trình tô màu kết thúc ( xem hình 2.5). F ymax C P D E B G yH+1 I H yH A ymin Hình 2.7 : Tô đa giác bằng giải thuật scan -line. - Để tìm giao điểm giữa cạnh đa giác và dòng quét, ta có nhận xét sau : y = k+1 x k+1 y = k xk 1 1 1 x k+1 - x k = ( (k+1) - k ) = hay x k+1 = x k + m m m Trong đó m là hệ số góc của cạnh. Trang 40
  42. Chương 2: Các thuật toán tô màu Lưu đồ thuật toán scan - line Begin Tạo danh sách tất cả các cạnh (ET) của đa giác. i = ymin i < ymax No Yes Cập nhật danh sách các cạnh kích họat AET Tìm hoành độ giao điểm và sắp xếp theo thứ tự tăng dần Tô mẫu các đoạn giao được tạo bởi từng cặp hoành độ kế tiếp nhau Cập nhật lại thông tin của các cạnh để sử dụng cho dòng quét kế tiếp i = i + 1 End Trang 41
  43. Chương 2: Các thuật toán tô màu 2.3.3. Phương pháp tô màu dựa theo đường biên Bài toán đặt ra : Cần tô màu một vùng nếu biết được màu của đường biên vùng tô và một điểm nằm bên trong vùng tô. Ý tưởng : Bắt đầu từ một điểm nằm bên trong vùng tô, kiểm tra các điểm lân cận của nó đã được tô với màu muốn tô, hay điểm lân cận có màu trùng với màu biên không ? Nếu cả hai trường hợp đều không phải thì ta sẽ tô điểm đó với màu muốn tô. Quá trình này được lặp lại cho đến khi không còn tô được nữa thì dừng (xem hình 2.8). Hình 2.8 : Tô màu theo đường biên. Có 2 quan điểm về cách tô này. Đó là dùng 4 điểm lân cận (có thể gọi là 4 liên thông) hay 8 điểm lân cận (8 liên thông) (xem hình 2.9). (x,y-1) (x-1,y) (x,y)(x+1,y) (x,y+1) Hình 2.9 : 4 liên thông và 8 liên thông. Cài đặt minh họa thuật toán 4 liên thông Procedure Boundary_fill ( x,y, mauto, maubien :integer); var mau_ht : integer; begin mau_ht:= getpixel(x, y); if (mau_ht maubien) then begin Trang 42
  44. Chương 2: Các thuật toán tô màu putpixel(x,y,color); Boundary_fill ( x+1,y, mauto, maubien ); Boundary_fill ( x-1,y, mauto, maubien ); Boundary_fill ( x,y+1, mauto, maubien ); Boundary_fill ( x,y-1, mauto, maubien ); end; end; Nhận xét : - Thuật toán có thể không chính xác khi có một số điểm nằm trong vùng tô có màu là màu cần tô của vùng. - Việc thực hiện gọi đệ qui làm thuật toán không thể sử dụng cho vùng tô lớn ( tràn stack). - Có thể khắc phục việc tràn stack bằng cách giảm số lần gọi đệ qui. Khởi đầu điểm (x,y) là điểm có vị trí đặc biệt trong vùng tô, sau đó, gọi đệ qui các điểm lân cận của (x,y) (xem hình 2.8). (100,100) (500,200) (100,400) Hình 2.10: Tam giác với 3 tọa độ đỉnh. Ví dụ 1: Trong hình 2.10, ta có thể xét điểm (x,y) có tọa độ là (498, 200). Với điểm khởi đầu này thì chỉ cần xét 3 điểm lân cận là (x-1,y), (x,y-1), (x,y+1). Khi đó thủ tục tô màu theo đường biên được viết lại như sau : Procedure Boundary_fill ( x,y,mauto, maubien :integer); var mau_ht : integer; Trang 43
  45. Chương 2: Các thuật toán tô màu begin mau_ht:= getpixel(x,y); if (mau_ht maubien) then begin putpixel(x,y,color); Boundary_fill ( x-1,y, mauto, maubien ); Boundary_fill ( x,y+1, mauto, maubien ); Boundary_fill ( x,y-1, mauto, maubien ); end; end; Ví dụ 2: Trong hình 2.10, ta có thể xét điểm (x,y) có tọa độ là (102, 102). Với điểm khởi đầu này thì chỉ cần xét 2 điểm lân cận là (x+1,y), (x,y+1). Khi đó thủ tục tô màu theo đường biên được viết lại như sau : Procedure Boundary_fill ( x,y,mauto, maubien :integer); var mau_ht : integer; begin mau_ht:= getpixel(x,y); if (mau_ht maubien) then begin putpixel(x,y,color); Boundary_fill ( x+1,y, mauto, maubien ); Boundary_fill ( x,y+1, mauto, maubien ); end; end; Trang 44
  46. Chương 2: Các thuật toán tô màu - Một cải tiến khác : không cài đặt đệ qui mà tô theo từng dòng (xem hình 2.11). Hình 2.10 : Tô theo từng dòng. 2.4. Tổng kết chương 2 - Sinh viên cần hiểu được khái niệm về các không gian màu. Lưu ý nhiều ở giải thuật tô biên và scan-line. - Trong scan-line phải đánh dấu các đỉnh đơn điệu và đỉnh cực trị. - Trong giải thuật tô biên, việc thực hiện gọi đệ qui nhiều lần làm thuật toán không thể sử dụng cho vùng tô lớn (tràn stack). Có thể khắc phục việc tràn stack bằng cách giảm số lần gọi đệ qui. Thực hiện gọi đệ qui tại đỉnh đặc biệt của đa giác. Trang 45
  47. Chương 2: Các thuật toán tô màu 2.5. Bài tập chương 2 20. Viết chương trình vẽ một đa giác n đỉnh, xét xem một điểm P nào đó có thuộc đa giác không ? 21. Viết chương trình vẽ một đa giác n đỉnh. Tô đa giác bằng giải thuật tô đơn giản ( Tìm xmin, ymin, xmax, ymax). 22. Viết chương trình vẽ một đường tròn. Tô đường tròn bằng giải thuật tô đơn giản. 23. Viết chương trình vẽ một đa giác n đỉnh. Tô đa giác bằng giải thuật tô biên. Lưu ý cho các trường hợp của đa giác : hình chữ nhật, đa giác lồi, đa giác lõm. 24. Viết chương trình vẽ một đường tròn. Tô đường tròn bằng giải thuật tô biên. 25. Viết chương trình vẽ một đa giác n đỉnh. Tô đa giác bằng giải thuật scan-line. 26. Viết chương trình vẽ một đường tròn. Tô đường tròn bằng giải thuật tô scanline. 27. Viết chương trình vẽ hai đường tròn C1 và C2 cắt nhau. Tô phần giao của hai đường tròn đó. Tô phần bù của C2. Tô phần bù của C1. Lưu ý rằng 3 màu tô này phải khác nhau. Trang 46
  48. Chương 3: Phép biến đổi trong đồ họa hai chiều Chương 3 : PHÉP BIẾN ĐỔI TRONG ĐỒ HỌA HAI CHIỀU 3.1. Tổng quan • Mục tiêu - Sinh viên cần hiểu được các phép biến đổi cơ bản trong không gian hai chiều. Nắm vững công thức tổng quát của phép biến đổi Affine, từ đó suy ra các phép tịnh tiến, quay - Có khả năng lập trình tạo một hình ảnh động trên máy tính • Kiến thức cơ bản cần thiết Kiến thức toán học : hiểu biết về ma trận, định thức. Các phép toán trên ma trận. • Tài liệu tham khảo Computer Graphics . Donald Hearn, M. Pauline Baker. Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986 (chapters 5, 106-122). • Nội dung cốt lõi Bản chất của phép biến đổi hình học là thay đổi các mô tả về tọa độ của đối tượng như thay đổi về hướng, kích thước, hình dạng. Do đó, chương này trình bày các phép biến đổi như tịnh tiến, tỉ lệ, phép quay, đối xứng, biến dạng. 3.2. Phép tịnh tiến (translation) Có hai quan điểm về phép biến đổi hình học, đó là : - Biến đổi đối tượng : thay đổi tọa độ của các điểm mô tả đối tượng theo một qui tắc nào đó. - Biến đổi hệ tọa độ : Tạo ra một hệ tọa độ mới và tất cả các điểm mô tả đối tượng sẽ được chuyển về hệ tọa độ mới. Các phép biến đổi hình học cơ sở là : tịnh tiến, quay, biến đổi tỉ lệ. Phép biến đổi Affine hai chiều (gọi tắc là phép biến đổi) là một ánh xạ T biến đổi điểm P(Px, Py) thành điểm Q(Qx, Qy) theo hệ phương trình sau: Qx = a*Px + c*Py + trx Qy = b*Px + d*Py + try Trang 47
  49. Chương 3: Phép biến đổi trong đồ họa hai chiều Hay ⎛a b ⎞ (Qx, Qy) = (Px, Py).⎜ ⎟ + (trx, try) ⎝ c d ⎠ ⇒ Q = P.M + tr Dùng để dịch chuyển đối tượng từ vị trì này sang vị trí khác. Nếu gọi trx và try lần lượt là độ dời theo trục hoành và trục tung thì tọa độ điểm mới Q(x', y') sau khi tịnh tiến điểm P(x,y) sẽ là : x' = x + trx y' = y + try (trx, try) được gọi là vector tịnh tiến hay vector độ dời (xem hình 3.1). Hay Q = P*M +tr ⎛1 0⎞ M= ⎜ ⎟ , tr = (trx, try) ⎝0 1⎠ Q(x',y') y' try P(x,y) y O x x' trx Hình 3.1 : Phép biến đổi tịnh tiến điểm P thành Q. 3.3. 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 tọa độ 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 (gọi là các hệ số tỉ lệ), ta nhân Sx và Sy lần lượt cho các tọa độ của P. x' = x.Sx y' = y.Sy - Khi các giá trị Sx , Sy nhỏ hơn 1, 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, phép biến đổi sẽ phóng lớn đối tượng. Trang 48
  50. Chương 3: Phép biến đổi trong đồ họa hai chiều - Khi Sx = Sy , người ta gọi đó là phép đồng dạng (uniform scaling). Đây là phép biến đổi bảo toàn tính cân xứng của đối tượng. Ta gọi là phép phóng đại nếu |S|>1 và là phép thu nhỏ nếu |S|<1. - Nếu hai hệ số tỉ lệ khác nhau thì ta gọi là phép không đồng dạng. Trong trường hợp hoặc Sx hoặc Sy có giá trị 1, ta gọi đó là phép căng (strain). 3.4. 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 qui ước là chiếu ngược chiều kim đồng hồ. • Phép quay quanh gốc tọa độ Ta có công thức biến đổi của phép quay điểm P(x,y) quanh gốc tọa độ góc θ (xem hình 3.2): x' = x.cosθ - y.sinθ y' = x.sinθ + y.cosθ Hay Q = P*M ⎛ cosθ sin θ ⎞ với M = ⎜ ⎟ ⎝− sinθ cos θ ⎠ y Q(x', y') P(x,y) θ O x Hình 3.2 : Phép quay quanh gốc tọa độ. Trang 49
  51. Chương 3: Phép biến đổi trong đồ họa hai chiều • Phép quay quanh một điểm bất kỳ Q y P Q' P' θ O x Hình 3.3 : Phép quay quanh một điểm bất kỳ. Xét điểm P(P.x,P.y) quay quanh điểm V(V.x, V.y) một góc θ đến điểm Q(Q.x,Q.y). Ta có thể xem phép quay quanh tâm V được kết hợp từ phép các biến đổi cơ bản sau: - Phép tịnh tiến (-V.x, -V.y) để dịch chuyển tâm quay về gốc tọa độ - Quay quanh gốc tọa độ O một góc θ - Phép tịnh tiến (+V.x, +V.y) để đưa tâm quay về vị trí ban đầu Ta cần xác định tọa độ của điểm Q (xem hình 3.3). - Từ phép tịnh tiến (-V.x,-V.y) biến đổi điểm P thành P' ta được: P' = P + V hay P'.x = P.x - V.x P'.y = P.y - V.y - Phép quay quanh gốc tọa độ biến đổi điểm P' thành Q' Q' = P'.M Q'.x = P'.x*cosθ - P'.y*sinθ Q'.y = P'.x*sinθ + P'.y*cosθ - Phép tịnh tiến (+V.x, +V.y) biến đổi điểm Q' thành Q ta được Q = Q' + V hay Q.x = Q'.x + V.x Q.y = Q'.y + V.y Q.x = (P.x - V.x)*cosθ - (P.y - V.y)*sinθ + V.x Trang 50
  52. Chương 3: Phép biến đổi trong đồ họa hai chiều Q.y = (P.x - V.x)*sinθ + (P.y - V.y)*cosθ + V.y Q.x = P.x*cosθ - P.y*sinθ + V.x*(1- cosθ) + V.y*sinθ Q.y = P.x*sinθ + P.y*cosθ - V.x*sinθ + V.y*(1- cosθ) Vậy Q = P.M + tr. Với ⎛ cosθ sin θ ⎞ M = ⎜ ⎟ ⎝− sinθ cos θ ⎠ tr = (V.x*(1- cosθ) + V.y*sinθ , - V.x*sinθ + V.y*(1- cosθ)) 3.5. Phép đối xứng Phép đối xứng trục có thể xem là phép quay quanh trục đối xứng mõt góc 1800. Phương trình ban đầu : Q.x = a*P.x + c*P.y + trx Qy = b*P.x + d*P.y + try Hay ⎛a b ⎞ (Q.x, Q.y) = (P.x, P.y).⎜ ⎟ + (trx, try) ⎝ c d ⎠ Trục đối xứng là trục hoành : ⎛1 0 ⎞ M = ⎜ ⎟ ⎝0− 1⎠ Ta có : Q.x = P.x Q.y = - P.y Tương tự trục đối xứng là trục tung : Ta có : Q.x = - P.x Q.y = P.y ⎛−1 0⎞ M = ⎜ ⎟ ⎝ 0 1⎠ 3.6. Phép biến dạng Phép biến dạng biến đổi làm thay đổi, méo mó hình dạng của các đối tượng. - Biến dạng theo phương trục x sẽ làm thay đổi hoành độ còn tung độ giữ nguyên. Trang 51
  53. Chương 3: Phép biến đổi trong đồ họa hai chiều Ví dụ : biến đổi điểm P(P.x, P.y) thành điểm Q(Q.x, Q.y) theo phương trục x là phép biến đổi được biểu diễn bởi phương trình sau : Q.x = P.x + h*P.y Q.y = P.y ⎛1 0⎞ M = ⎜ ⎟ ⎝h 1⎠ - Biến dạng theo phương trục y sẽ làm thay đổi tung độ còn hoành độ giữ nguyên. Q.x = P.x Q.y = g*P.x + P.y ⎛1 g ⎞ M = ⎜ ⎟ ⎝0 1 ⎠ 3.7. Phép biến đổi Affine ngược ( The inverse of an Affine transformation) Phép biến đổi ngược dùng để undo một phép biến đổi đã thực hiện. Gọi Q là ảnh của P qua phép biến đổi T có ma trận biến đổi M là : P.M. Phép biến đổi ngược T -1 sẽ có ma trận biến đổi là M -1 là ma trận nghịch đảo của ma trận M. ⎛a b ⎞ -1 1 ⎛ d− b⎞ Nếu M = ⎜ ⎟ thì M = ⎜ ⎟ ⎝ c d ⎠ ad− bc ⎝− c a ⎠ Ta có : ⎛1 0⎞ -1 ⎛1 0⎞ Phép tịnh tiến : M = ⎜ ⎟ thì M = ⎜ ⎟ ⎝0 1⎠ ⎝0 1⎠ ⎛ cosθ sin θ ⎞ -1 ⎛cosθ− sin θ ⎞ Phép quay : M = ⎜ ⎟ thì M = ⎜ ⎟ ⎝− sinθ cos θ ⎠ ⎝ sinθ cos θ ⎠ ⎛ 1 ⎞ ⎜ 0 ⎟ ⎛ S x 0 ⎞ S Phép biến đổi tỉ lệ : M = ⎜ ⎟ thì M -1 = ⎜ x ⎟ ⎜ 0 S ⎟ ⎜ 1 ⎟ ⎝ y ⎠ ⎜ 0 ⎟ ⎝ S y ⎠ ⎛1 g ⎞ -1 ⎛ 1 − g ⎞ Phép biến dạng : M = ⎜ ⎟ thì M = ⎜ ⎟ ⎝h 1 ⎠ ⎝− h 1 ⎠ Trang 52
  54. Chương 3: Phép biến đổi trong đồ họa hai chiều 3.8. Một số tính chất của phép biến đổi affine - Bảo toàn đường thẳng : ảnh của đường thẳng qua phép biến đổi affine là đường thẳng. Ví dụ : Để biến đổi một đoạn thẳng qua hai điểm A và B, chỉ cần thực hiện phép biến đổi cho A và B. Do vậy, để biến đổi một đa giác, chỉ cần thực hiện phép biến đổi đối với các đỉnh của đa giác. - Bảo toàn tính song song : ảnh của hai đường thẳng song song là song song. Ví dụ : ảnh của hình vuông, hình chữ nhật, hình bình hành, hình thoi sau phép biến đổi là hình bình hành. - Bảo toàn tỉ lệ khoảng cách : Nếu điểm M chia đoạn AB theo tỉ số m thì ảnh của M là M' cũng chia đoạn AB theo tỉ số m. Ví dụ : Trong hình vuông, các đường chéo cắt nhau tại trung điểm của mỗi đường nên các đường chéo của bất kỳ hình bình hành nào cũng cắy nhau tại trung điểm của mỗi đường. Trong tam giác đều, giao điểm của 3 đường trung tuyến chia mỗi đường theo tỉ số 1:2. Do ảnh của tam giác đều qua phép biến đổi affine la một tam giác nên giao điểm của các đường trung tuyến trong một tam giác cũng sẽ chia chúng theo tỉ lệ 1:2. 3.9. Hệ tọa độ thuần nhất Tọa độ thuần nhất của một điểm trên mặt phẳng được biểu diễn 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 tọa độ (x, y) của điểm đó bởi công thức : x y x = h và y = h h h Nếu một điểm có tọa độ thuần nhất là (x,y,z) thì nó cũng có tọa độ thuần nhất là (h.x, h.y, h.z) trong đó h là số thực khác 0 bất kỳ. Một điểm P(x,y) sẽ được biểu diễn dưới dạng tọa độ thuần nhất là (x,y,1). Trong hệ tọa độ thuần nhất các ma trận của phép biến đổi được biểu diễn như sau : ⎛ 1 0 0⎞ ⎜ ⎟ Phép tịnh tiến : M = ⎜ 0 1 0⎟ ⎜ ⎟ ⎝trx tr y 1⎠ Trang 53
  55. Chương 3: Phép biến đổi trong đồ họa hai chiều ⎛ S 0 0⎞ ⎜ X ⎟ Phép biến đổi tỉ lệ : M = ⎜ 0SY 0⎟ ⎜ ⎟ ⎝ 0 0 1⎠ ⎛ cosθ sin θ 0⎞ ⎜ ⎟ Phép quay : M = ⎜− sinθ cos θ 0⎟ ⎜ ⎟ ⎝ 0 0 1⎠ Thuận lợi của hệ tọa độ thuần nhất là khi ta kết hợp hai hay nhiều phép biến đổi affine thi ma trận hợp của nhiều phép biến đổi được tính bằng cách nhân các ma trận của các phép biến đổi thành phần. 3.10. Kết hợp các phép biến đổi (composing transformation) 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. • Kết hợp các phép tịnh tiến Nếu ta thực hiện phép tịnh tiến lên điểm P được điểm P', rồi lại thực hiện tiếp một phép tịnh tiến khác lên P' được điểm Q. Như vậy, điểm Q là ảnh của phép biến đổi kết hợp hai phép tịnh tiến liên tiếp. Q.x = P.x + ( trx1+t rx2 ) Q.y = P.y + ( try1+try2 ) ⎛ 1 0 0⎞ ⎛ 1 0 0⎞ ⎛ 1 0 0⎞ ⎜ ⎟ ⎜ ⎟ ⎜ ⎟ M = ⎜ 0 1 0⎟ *⎜ 0 1 0⎟ = ⎜ 0 1 0⎟ ⎜ ⎟ ⎜ ⎟ ⎜ ⎟ ⎝trx1 tr y 1 1⎠ ⎝trx2 tr y 2 1⎠ ⎝trx1+ tr x 2 tr y 1+ tr y 2 1⎠ Vậy kết hợp hai phép tịnh tiến là một phép tịnh tiến. Từ đó, ta có kết hợp của nhiều phép tịnh tiến là một phép tịnh tiến. • Kết hợp các phép biến đổi tỉ lệ Tương tự như phép tịnh tiến, ta có tọa độ điểm Q là điểm có được sau hai phép tịnh tiến M1(Sx1, Sy1 ), M2 (Sx2, Sy2 )là : Q.x = P.x* Sx1* Sx2 Q.y = P.y* Sy1* Sy2 Trang 54
  56. Chương 3: Phép biến đổi trong đồ họa hai chiều ⎛ S 0 0⎞ ⎛ S 0 0⎞ ⎛ SS* 0 0⎞ ⎜ X1 ⎟ ⎜ X 2 ⎟ ⎜ XX1 2 ⎟ M = ⎜ 0SY1 0⎟ *⎜ 0SY 2 0⎟ = ⎜ 0 SSYY1* 2 0⎟ ⎜ ⎟ ⎜ ⎟ ⎜ ⎟ ⎝ 0 0 1⎠ ⎝ 0 0 1⎠ ⎝ 0 0 1⎠ • Kết hợp các phép quay Tương tự, ta có tọa độ điểm Q là điểm kết quả sau khi kết hợp hai phép quay quanh gốc tọa độ MR1(θ1) và MR2(θ2) là : Q.x = P.x*cos(θ1+θ2) - P.y*sin (θ1+θ2) Q.y = P.x*sin(θ1+θ2) + P.y*cos(θ1+θ2) ⎛ cosθ 1 sin θ 1 0⎞ ⎛ cosθ 2 sin θ 2 0⎞ ⎜ ⎟ ⎜ ⎟ M = ⎜− sinθ 1 cos θ 1 0⎟ *⎜− sinθ 2 cos θ 2 0⎟ = ⎜ ⎟ ⎜ ⎟ ⎝ 0 0 1⎠ ⎝ 0 0 1⎠ ⎛ cos(θ 1+ θ 2) sin( θ 1+ θ 2) 0⎞ ⎜ ⎟ ⎜−sin(θ 1 + θ 2) cos( θ 1+ θ 2) 0⎟ ⎜ ⎟ ⎝ 0 0 1⎠ 3.11. Tổng kết chương 3 Sinh viên cần nắm bắt được vấn đề cơ bản của phép biến đổi 2 chiều là phép biến đổi Affine biến đổi điểm P(P.x, P.y) thành điểm Q(Q.x, Q.y) là hàm tuyến tính có dạng : ⎛a b ⎞ (Q.x, Q.y) = (P.x, P.y).⎜ ⎟ + (trx, try) ⎝ c d ⎠ ⇒ Q = P.M + tr Từ công thức cơ bản này ta suy ra được các công thức biến đổi khác. 3.12. Bài tập chương 3 1. Vẽ một hình bình hành bằng cách sử dụng phép tịnh tiến. (Vẽ đoạn thẳng AB, sau đó tịnh tiến AB thành đoạn thẳng CD//AB, vẽ AD, Tịnh tiến AD thành BC (xem hình vẽ). Trang 55
  57. Chương 3: Phép biến đổi trong đồ họa hai chiều C(xb+k1,yb+k2) B(xb,yb) D(xa+k1,ya+k 2) A(xa,ya) 2. Viết chương trình vẽ một hình vuông ABCD (xem hình vẽ). - Tịnh tiến hình vuông đó đến vị trí khác. - Phóng to hình vuông ABCD. - Biến dạng hình vuông thành hình thoi. 3. Vẽ một elip, sau đó vẽ thêm 3 elip khác có cùng tâm với elip đã cho, có độ dãn ở trục Ox là K và Oy là 1. 4. Vẽ một elip nghiêng một góc G độ có các trục không song song với các trục tọa độ. 5. Vẽ một bông hoa bằng cách vẽ các elip nghiêng một góc G độ với các màu khác nhau. Vẽ đến khi nào ấn phím bất kỳ thì ngưng. 6. Viết chương trình mô phỏng sự chuyển động của elip bằng cách cho elip này quay quanh tâm của nó. 7. Viết chương trình mô phỏng sự chuyển động của trái đất quay quanh mặt trời. 8. Viết chương trình vẽ một đường tròn tâm O bán kính R. Vẽ một đường kính AB. Quay đường kính này quanh tâm đường tròn. Trang 56
  58. Chương 3: Phép biến đổi trong đồ họa hai chiều 9. Viết chương trình vẽ đoạn thẳng AB. Trang 57
  59. Chương 4: Windowing và Clipping Chương 4 TẠO CỬA SỐ VÀ CẮT HÌNH (WINDOWING AND CLIPPING) 4.1. Tổng quan • Mục tiêu Học xong chương này, sinh viên cần phải nắm bắt được các vấn đề sau: - Thế nào là window ? - Hiểu rõ các thao tác loại bỏ phần hình ảnh nằm ngoài một vùng cho trước (thao tác này được gọi là xén hình). - Thiết kế và cài đặt được các thuật toán xén hình. • Kiến thức cơ bản cần thiết Kiến thức tin học bao gồm kỹ thuật lập trình và cấu trúc dữ liệu • Tài liệu tham khảo Computer Graphics . Donald Hearn, M. Pauline Baker. Prentice-Hall, Inc., Englewood Cliffs, New Jersey , 1986 (chapters 6, 123-153) • Nội dung cốt lõi - Trình bày các khái niệm về window. - Các thuật toán clipping : Cohen-Sutherland, Liang-Barsky - Phép biến đổi từ cửa sổ 4.2. Các khái niệm về Windowing Hệ tọa độ Descartes là dễ thích ứng cho các chương trình ứng dụng để miêu tả các hình ảnh (picture) trên hệ tọa độ thế giới thực (world coordinate system). Các hình ảnh được định nghĩa trên hệ tọa độ thế giới thực này sau đó được hệ đồ họa vẽ lên các hệ tọa độ thiết bị (device coordinate). Điển hình, một vùng đồ họa cho phép người sử dụng xác định vùng nào của hình ảnh sẽ được hiển thị và bạn muốn đặt nó ở nơi nào trên hệ tọa độ thiết bị. Một vùng đơn lẻ hoặc vài vùng của hình ảnh có thể được chọn. Những vùng này có thể được đặt ở những vị trí tách biệt, hoặc một vùng có thể được chèn vào một vùng lớn hơn. Quá trình biến đổi này liên quan đến những thao tác như Trang 58
  60. Chương 4: Windowing và Clipping tịnh tiến, biến đổi tỷ lệ vùng được chọn và xóa bỏ những phần bên ngoài vùng được chọn. Những thao tác này được gọi là windowing và clipping (xem hình 4.1). Window ywmax Viewport yvmax ywmin yvmin xwmin xwmax xvmax xvmin Hệ tọa độ thế giới thực Hệ tọa độ thiết bị Hình 4.1 : Một ánh xạ cửa sổ - đến – vùng quan sát Một vùng có dạng hình chữ nhật được xác định trong hệ tọa độ thế giới thực được gọi là một cửa sổ (window). Còn vùng hình chữ nhật trên thiết bị hiển thị để cửa sổ đó ánh xạ đến được gọi là một vùng quan sát (viewport). Hình 4.1 minh họa việc ánh xạ một phần hình ảnh vào trong một viewport. Việc ánh xạ này gọi là một phép biến đổi hệ quan sát (viewing transformation), biến đổi cửa sổ (windowing tranformation), biến đổi chuẩn hóa (normalization transformation). Các lệnh để xây dựng một cửa sổ và vùng quan sát từ một chương trình ứng dụng có thể được định nghĩa như sau: set_window(xw_min, xw_max, yw_min, yw_max) set_viewport(xv_min, xv_max, yv_min, yv_max) Các tham số trong mỗi hàm được dùng để định nghĩa các giới hạn tọa độ của các vùng chữ nhật. Các giới hạn của cửa sổ được xác định trong hệ tọa độ thế giới thực. Hệ tọa độ thiết bị chuẩn thường được dùng nhất cho việc xác định vùng quan sát, dù rằng hệ tọa độ thiết bị có thể được dùng nếu chỉ có một thiết bị xuất (output device) duy nhất trong hệ thống. Khi hệ tọa độ thiết bị chuẩn được dùng, lập trình viên xem thiết bị xuất có giá trị tọa độ trong khoảng 0 1. Một sự xác định vùng quan sát được cho với các giá trị trong khoảng này. Các việc xác định sau đây, đặt một phần Trang 59
  61. Chương 4: Windowing và Clipping của sự định nghĩa hệ tọa độ thế giới thực vào trong góc trên bên phải của vùng hiển thị, như được minh họa trong hình 4-2: set_window(-60.5, 41.25, -20.75, 82.5); set_viewport(0.5, 0.8, 0.7, 1.0); Nếu một cửa sổ buộc phải được ánh xạ lấp đầy vùng hiển thị, sự xác định viewport được cho là: Set_viewport(0,1, 0, 1) Các vị trí được biểu diễn trên hệ tọa độ thiết bị chuẩn phải được biến đổi sang hệ tọa độ thiết bị trước khi được hiển thị bởi một thiết bị xuất cụ thể. Thông thường một thiết bị xác định được chứa trong các gói đồ họa cho mục đích này. Thuận lợi của việc dùng hệ tọa độ thiết bị chuẩn là để các gói đồ họa độc lập với thiết bị. Các thiết bị xuất khác nhau có thể được dùng nhờ việc cung cấp các trình điều khiển thiết bị thích hợp. Mọi điểm được tham khảo đến trong các gói đồ họa phải được xác định tương ứng trong hệ tọa độ Descartes. Bất kỳ sự định nghĩa hình ảnh nào dùng trong một hệ tọa độ khác, như hệ tọa độ cực, người sử dụng trước tiên phải biến đổi nó sang hệ tọa độ thế giới thực. Những hệ tọa độ Descart này sau đó được dùng trong các lệnh cửa sổ để xác định phần nào của hình ảnh muốn được hiển thị (xem hình 4.2). yw (-60.5, 82.5) (-41.25, 82.5) 1 Window Viewport 0 xw 0.5 1 (-60.5, -20.75) (41.25, -20.75) Hệ tọa độ thế giới thực Hệ tọa độ thiết bị chuẩn Hình 4-2: Ánh xạ một cửa sổ vào một vùng quan sát trong hệ tọa độ thiết bị chuẩn Trang 60
  62. Chương 4: Windowing và Clipping Các lệnh về cửa sổ và vùng quan sát được phát biểu trước khi gọi các thủ tục vẽ ảnh. Các sự xác lập cho cửa sổ và vùng quan sát sẽ ảnh hưởng đến bất kỳ lệnh xuất theo sau nào cho đến khi có một sự xác lập mới. Bằng việc thay đổi vị trí vùng quan sát, các đối tượng có thể được hiển thị ở bất kỳ vị trí nào trên thiết bị xuất. Cũng như vậy, bằng việc thay đổi kích thước vùng quan sát, kích thước các phần của đối tượng có thể bị thay đổi. Khi các cửa sổ được đặt lại các kích thước khác được ánh xạ thành công vào một vùng quan sát, các hiệu ứng về phóng to (zooming) có thể thực hiện được. Hình 4-3: Hiển thị đồng thời hai biểu đồ, dùng đa cửa sổ và sự xác định vùng quan sát. Khi các cửa sổ được làm nhỏ hơn, người dùng có thể phóng to vài nơi trên ảnh để xem chi tiết hơn mà không cần phóng to toàn bộ cửa sổ. Các hiệu ứng panning có thể được tạo ra bằng cách di chuyển một cửa sổ có kích thước xác định ngang qua một hình ảnh lớn. Một ví dụ của việc dùng đa cửa sổ và các lệnh về vùng quan sát được cho trong các thủ tục sau đây. Hai biểu đồ được hiển thị trên hai phần đều nhau của một thiết bị hiển thị (xem hình 4-3). type points = array[1 max_points] of real; procedure two_graphs; var x,y : points; k: integer; begin set_window(0, 1, 0, 1); {vẽ đường chia ở trung tâm} set_viewport(0, 1, 0, 1); x[1]:=0.5; y[1]:=0; x[2]:=0.5; y[2]:=1; polyline(2, x, y); Trang 61
  63. Chương 4: Windowing và Clipping for k:=1 to 9 do begin {đọc dữ liệu cho đồ thị thứ nhất} x[k]:=k; {các giá trị dữ liệu từ 300 đến 700} readln(y[k]); end; {for k} set_window(1, 9, 300, 700); set_viewport(0.1, 0.4, 0.2, 0.8);{đặt vào phần bên trái màn hình} polyline(9, x, y); for k:=1 to 13 do begin {đọc dữ liệu cho đồ thị thứ hai} x[k]:=k; readln(y[k]); end; set_window(1, 13, 10, 100); {các giá trị dữ liệu từ 10 đến 100} set_viewport(0.6, 0.9, 0.2, 0.8);{đặt dữ liệu vào phần bên phải màn hình} polyline(13, x, y); end;{two graph} Một phương pháp khác để xây dựng các vùng đa cửa sổ và vùng quan sát trong gói đồ họa là gán nhãn đến mỗi sự xác định. Điều này có thể được làm bằng việc thêm đối số thứ năm vào các lệnh về cửa sổ và vùng quan sát để xác định vùng chỉ định. Các tham số có thể là một chỉ số nguyên (0, 1, 2, 3, ). Các lệnh xuất sau đó dùng các chỉ số này để chỉ định sự chuyển đổi từ cửa sổ đến vùng quan sát nào. Cơ chế đánh số này cũng có thể được dùng để gắn kết một độ ưu tiên với mỗi vùng quan sát, đây là cơ sở để cài đặt tính chất nhìn thấy được của các cửa sổ nằm đè lên nhau. Các vùng quan sát được hiển thị theo độ ưu tiên được trình bày ở hình 4-4: Hình 4-4: Hiển thị các vùng 2 quan sát theo thứ tự ưu tiên. Các vùng quan sát có số thứ tự nhỏ hơn sẽ có quyền ưu tiên cao hơn. 01 Trang 62
  64. Chương 4: Windowing và Clipping Để cài đặt cách làm việc đa trạm (multiple workstation) , một tập bổ sung các lệnh về cửa sổ và vùng quan sát sẽ được định nghĩa. Các lệnh này có chứa số của trạm, giúp xây dựng các cửa sổ và vùng quan sát trên các trạm làm việc khác nhau. Điều này cho phép một người dùng hiển thị các phần khác nhau của ảnh kết quả lên các thiết bị xuất khác nhau. Ví dụ, một kiến trúc sư có thể hiển thị tổng thể bản vẽ của một căn nhà lên một màn hình, còn chi tiết tầng 2 sẽ được hiển thị lên màn hình thứ hai (xem hình 4.5) Hình 4-5 Quay cửa sổ, được xác định bởi một góc a. Window a Các lệnh về cửa sổ và vùng quan sát vừa được giới thiệu được dùng cho các vùng hình chữ nhật, các đường biên của chúng song song với các trục tọa độ. Vài gói đồ họa cho phép người dùng chọn kiểu cửa sổ và vùng quan sát khác. Một cửa sổ bị quay, như hình 4-5, có thể được xác định với tham số là góc a trong một lệnh về cửa sổ. Một khả năng khác là chỉ định rõ một đa giác nào đó như một cửa sổ bằng việc cho một chuỗi các đỉnh. Chúng ta sẽ bắt đầu bằng việc trình bày các thuật toán cài đặt các cửa sổ và vùng quan sát hình chữ nhật, biên của chúng song song với trục x và y. Các cửa sổ có hình dạng đặc biệt khác sẽ được thảo luận sau đó như các thuật toán mở rộng (xem hình 4-6). Input m ột hình ảnh trên Thủ tục Ánh xạ vùng cửa Chuyển đổi Hiển thị lên hệ tọa độ thế giới thực Clipping sổ vào vùng quan vùng vùng quan thiết bị xuất nhờ một chương trình sát trong hệ tọa độ sát sang hệ tọa vật lý ứng dụng thiết bị chuẩn độ thiết bị Hình 4-6 Quá trình chuyển đổi các cửa sổ vào trong các vùng quan sát. 4.3. Các thuật toán Clipping Ánh xạ một vùng cửa sổ vào trong một vùng quan sát, kết quả là chỉ hiển thị những phần trong phạm vi cửa sổ. Mọi thứ bên ngoài cửa sổ sẽ bị loại bỏ. Các thủ tục để loại bỏ các phần hình ảnh nằm bên ngoài biên cửa sổ được xem như các thuật toán clipping (clipping algorithms) hoặc đơn giản được gọi là clipping. Trang 63
  65. Chương 4: Windowing và Clipping Việc cài đặt phép biến đổi cửa sổ thường được thực hiện bằng việc cắt (clipping) khỏi cửa sổ, sau đó ánh xạ phần bên trong cửa sổ vào một vùng quan sát (hình 6-6). Như một lựa chọn, một vài gói đồ họa đầu tiên ánh xạ sự định nghĩa trong hệ tọa độ thế giới thực vào trong hệ tọa độ thiết bị chuẩn và sau đó cắt khỏi biên vùng quan sát. Trong các các phần thảo luận sau, chúng ta giả thiết rằng việc cắt được thực hiện dựa vào đường biên cửa sổ trong hệ tọa độ thế giới thực. Sau khi cắt xong, các điểm bên trong cửa sổ mới được ánh xạ đến vùng quan sát. Việc cắt các điểm khỏi cửa sổ được hiểu đơn giản là chúng ta kiểm tra các giá trị tọa độ để xác định xem chúng có nằm bên trong biên không. Một điểm ở vị trí (x,y) được giữ lại để chuyển đổi sang vùng quan sát nếu nó thỏa các bất phương trình sau: xwmin ≤ x ≤ xwmax, ywmin ≤ y ≤ ywmax (4-1) Nếu điểm nào không thỏa một trong bốn bất phương trình trên, nó bị cắt bỏ. Trong hình 4-7, điểm P1 được giữ lại, trong khi điểm P2 bị cắt bỏ. y y P4 P P 2 • 3 Window Window ywmax ywmax P6 P6 P7 P5 P5 P1 • P’7 P1 • P10 P10 ywmin P8 ywmin P’8 P9 P’9 x x xwmin xwmax xwmin xwmax Trước khi Clipping Sau khi Clipping (a) (b) Hình 4-7 Điểm và đoạn thẳng bị cắt khỏi cửa sổ Hình 4-7 minh họa các quan hệ có thể có giữa các vị trí đoạn thẳng với biên cửa sổ. Chúng ta kiểm tra một đoạn thẳng xem có bị cắt hay không bằng việc xác định xem hai điểm đầu mút đoạn thẳng là nằm trong hay nằm ngoài cửa sổ. Một đoạn thẳng với cả hai đầu nằm trong cửa sổ thì được giữ lại hết, như đoạn từ P5 đến P6. Một đoạn với một đầu nằm ngoài (P9) và một đầu nằm trong (P10) sẽ bị cắt bớt tại giao điểm với biên cửa sổ (P’9). Các đoạn thẳng có cả hai đầu đều nằm ngoài cửa sổ, có thể rơi vào hai trường hợp: toàn bộ đoạn thẳng đều nằm ngoài hoặc đoạn thẳng cắt hai cạnh cửa sổ. Trang 64
  66. Chương 4: Windowing và Clipping Đoạn từ P3 đến P4 bị cắt bỏ hoàn toàn. Nhưng đoạn từ P7 đến P8 sẽ được giữ lại phần từ P’7 đến P’8. Thuật toán clipping đường (line-clipping) xác định xem đoạn nào toàn bộ nằm trong, đoạn nào bị cắt bỏ hoàn toàn hay bị cắt một phần. Đối với các đoạn bị cắt bỏ một phần, các giao điểm với biên cửa sổ phải được tính. Vì một hình ảnh có thể chứa hàng ngàn đoạn thẳng, việc xử lý clipping nên được thực hiện sao cho có hiệu quả nhất. Trước khi đi tính các giao điểm, một thuật toán nên xác định rõ tất cả các đoạn thẳng được giữ lại hoàn toàn hoặc bị cắt bỏ hoàn toàn. Với những đoạn được xem xét là bị cắt bỏ, việc xác định các giao điểm cho phần được giữ lại nên được thực hiện với sự tính toán ít nhất. Một tiếp cận để cắt các đoạn là dựa trên cơ chế đánh mã được phát triển bởi Cohen và Sutherland. Mọi điểm ở hai đầu mút đoạn thẳng trong hình ảnh sẽ được gán một mã nhị phân 4 bit, được gọi là mã vùng (region code), giúp nhận ra vùng tọa độ của một điểm. Các vùng này được xây dựng dựa trên sự xem xét với biên cửa sổ, như ở hình 6-8. Mỗi vị trí bit trong mã vùng được dùng để chỉ ra một trong bốn vị trí tọa độ tương ứng của điểm so với cửa sổ: bên trái (left), phải (right), trên đỉnh (top), dưới đáy (bottom). Việc đánh số theo vị trí bit trong mã vùng từ 1 đến 4 cho từ phải sang trái, các vùng tọa độ có thể liên quan với vị trí bit như sau: Bit 1 – left Bit 2 – right Bit 3 – below Bit 4 – above Giá trị 1 ở bất kỳ vị trí nào chỉ ra rằng điểm ở vị trí tương ứng, ngược lại bit ở vị trí đó là 0. Nếu một điểm nằm trong cửa sổ, mã vị trí là 0000. Một điểm bên dưới và bên trái cửa sổ có mã vùng là 0101 (xem hình 4-8). 1001 1000 1010 Hình 4-8 Các mã vùng nhị phân cho các điểm đầu mút đoạn 0001 0000 0010 thẳng, được dùng để định Window nghĩa các vùng tọa độ liên hệ với một cửa sổ. 0101 0100 0110 Trang 65
  67. Chương 4: Windowing và Clipping Các giá trị bit trong mã vùng được xác định bằng cách so sánh giá trị tọa độ (x,y) của điểm đầu mút với biên cửa sổ. Bit 1 đặt lên 1 nếu x < xwmin. Các giá trị của ba bit còn lại được xác định bằng cách so sánh tương tự. Trong các ngôn ngữ lập trình, làm việc trên bit như thế này có thể thực hiện được, các giá trị bit mã vùng có thể được xác định theo các bước sau: (1) Tìm hiệu giữa tọa độ các điểm đầu mút với biên cửa sổ. (2) Dùng bit dấu (kết quả của mỗi hiệu) để đặt giá trị tương ứng trong mã vùng. Bit 1 là bit dấu của x - xwmin; bit 2 là bit dấu của xwmax – x; bit 2 là bit dấu của y - ywmin; và bit 4 là bit dấu của ywmax – y. Khi chúng ta xây dựng xong các mã vùng cho tất cả các điểm đầu mút, chúng ta có thể xác định nhanh chóng đoạn thẳng nào là hoàn toàn nằm trong cửa sổ, đoạn nào là hoàn toàn nằm ngoài. Bất kỳ đoạn nào có mã vùng của cả 2 đầu mút là 0000 thì nằm trong cửa sổ và chúng ta chấp nhận các đường này. Bất kỳ đường nào mà trong hai mã vùng của hai đầu mút có một số 1 ở cùng vị trí bit thì đoạn hoàn toàn nằm ngoài cửa sổ, và chúng ta loại bỏ các đoạn này. Ví dụ, chúng ta vứt bỏ đoạn có mã vùng ở một đầu là 1001, còn đầu kia là 0101 (có cùng bit 1 ở vị trí 1 nên cả hai đầu mút của đoạn này nằm ở phía bên trái cửa sổ). Một phương pháp có thể được dùng để kiểm tra các đoạn cho việc cắt toàn bộ là thực hiện phép logic and với cả hai mã vùng. Nếu kết quả không phải là 0000 thì đoạn nằm bên ngoài cửa sổ (xem hình 4-9). P2 Hình 4-9 Các đọan từ một điểm này Window P’2 đến một điểm khác có thể cắt cửa sổ hoặc giao điểm P3 với các biên nằm ngoài cửa sổ. P’1 P P’3 1 P4 Các đường không được nhận dạng là hoàn toàn nằm trong hay hoàn toàn nằm ngoài một cửa sổ thông qua các phép kiểm tra trên sẽ được tìm giao điểm với biên cửa sổ. Như được chỉ ra ở hình 4-9, các đường thuộc nhóm này có thể cắt hoặc không cắt cửa sổ. Chúng ta có thể xử lý các đoạn này bằng cách so sánh một điểm đầu mút (cái đang nằm ngoài cửa sổ) với một biên cửa sổ để xác định phần nào của đường sẽ bị bỏ. Sau đó, phần đường được giữ lại sẽ được kiểm tra với các biên khác, và chúng ta tiếp tục cho đến khi toàn bộ đường bị bỏ đi hay đến khi một phần đường được xác định là Trang 66
  68. Chương 4: Windowing và Clipping nằm trong cửa sổ. Chúng ta xây dựng thuật toán để kiểm tra các điểm đầu mút tương tác với biên cửa sổ là ở bên trái, bên phải, bên dưới hay trên đỉnh. Để minh họa các bước xác định trong việc cắt các đoạn khỏi biên cửa sổ dùng thuật toán của Cohen-Sutherland, chúng ta xem các đoạn trong hình 4-9 được xử lý như thế nào. Bắt đầu ở điểm đầu mút bên dưới từ P1 đến P2, ta kiểm tra P1 với biên trái, phải và đáy cửa sổ và thấy rằng điểm này nằm phía dưới cửa sổ. Ta tìm giao điểm P’1 với biên dưới. Sau khi tìm giao điểm P’1, chúng ta vứt bỏ đoạn từ P1 đến P’1. Tương tự, vì P2 bên ngoài cửa sổ, chúng ta kiểm tra và thấy rằng điểm này nằm phía trên cửa sổ. Giao điểm P’2 được tính, và đoạn từ P’1 đến P’2 được giữ lại. Kết thúc quá trình xử lý đoạn P1P2. Bây giờ xét đoạn kế tiếp, P3P4. Điểm P3 nằm bên trái cửa sổ, vì vậy ta xác định giao điểm P’3 và loại bỏ đoạn từ P’3 đến P3. Bằng cách kiểm tra mã vùng phần đoạn thẳng từ P’3 đến P4, chúng ta thấy rằng phần còn lại này nằm phía dưới cửa sổ và cũng bị vứt bỏ luôn. Các giao điểm với biên cửa sổ có thể được tính bằng cách dùng các tham số của phương trình đường thẳng. Với một đường thẳng đi qua hai điểm (x1, y1) và (x2, y2), tung độ y của giao điểm với một biên dọc cửa sổ có thể tính được theo phép tính: y = y1 + m (x - x1) (4-2) Ở đây giá trị x được đặt là xwmin hoặc xwmax, và độ dốc m được tính bằng là m = (y2 - y1)/ (x2 - x1) Tương tự, nếu ta tìm giao điểm với biên ngang, hoành độ x có thể được tính như sau: x = x1 + (y - y1)/m (4-3) với y là ywmin hoặc ywmax. Thủ tục sau đây minh họa thuật toán clipping đường (line-clipping) của Cohen- Sutherland. Các mã cho mỗi điểm đầu mút được chứa trong các mảng Boolean bốn phần tử. var xw_min, xw_max, yw_min, yw_max: real; procedure clip_a_line (x1, y1, x2, y2: real); type Trang 67
  69. Chương 4: Windowing và Clipping boundaries = (left, right, bottom, top); code = array [boundaries] of boolean; var code1, code2 : code; done, display: boolean; m: real; procedure encode (x, y : real; var c: code); begin if x xw_max then c[right]:= true else c[right]:= false; if y yw_max then c[top]:= true else c[top]:= false end; {encode} function accept (c1, c2 : code) : boolean; var k : boundaries; begin {nếu điểm có trị “true” ở bất kỳ vị trí nào trong mã của nó, một chấp nhận bình thường là không thể} accept :=true; for k:= left to top do if c1[k] or c2[k] then accept :=false end; {accept} function reject (c1, c2 : code) : boolean; var k : boundaries; begin {nếu hai điểm đầu mút có trị ‘true’ ở cùng vị trí tương ứng, đoạn thẳng bị xóa bỏ} Trang 68
  70. Chương 4: Windowing và Clipping reject:=false; for k:= left to top do if c1[k] and c2[k] then reject :=true end; {reject} procedure swap_if_needed (var x1, y1, x2, y2: real; var c1, c2: code); begin {đảm bảo rằng x1, y1 là điểm nằm ngoài cửa sổ và c1 chứa mã đó} end; {swap_if_needed} begin done :=false; display :=false; while not done do begin encode (x1, y1, code1); encode (x2, y2, code2); if accept (code1, code2) then begin done :=true; display :=true; end {if accept} else if reject (code1, code2) then done :=true else begin {tìm giao điểm} {bảo đảm rằng x1, y1 nằm ngoài cửa sổ} swap_if_needed (x1, y1, x2, y2, code1, code2); m := (y2-y1) / (x2-x1); if code1[left] then begin y1 := y1 + (xw_min – x1) * m; x1 :=xw_min end {cắt biên phải} else if code1[right] then begin Trang 69
  71. Chương 4: Windowing và Clipping y1 := y1 + (xw_max – x1)*m; x1 := xw_max end {cắt biên trái} else if code1[bottom] then begin x1 := x1 + (yw_min – y1) / m; y1 := yw_min end {cắt biên dưới đáy} else if code1[top] then begin x1 := x1 + (yw_max – y1) / m; y1 := yw_max end {cắt biên đỉnh} end {ngược lại tìm giao điểm} end; {while not done} if display then {draw x1, y1, to x2, y2} end; {clip_a_line} Một kỹ thuật để xác định giao điểm với biên cửa sổ mà không dùng đến phương trình đường thẳng là dùng thủ tục tìm kiếm nhị phân, được gọi là sự phân chia tại trung điểm. Đầu tiên, việc kiểm tra các đoạn một lần nữa được thực hiện bằng cách dùng mã vùng. Bất kỳ đoạn nào không được chấp nhận hoàn toàn hoặc không bị huỷ bỏ hoàn toàn (nhờ vào kiểm tra mã vùng) thì sẽ được đi tìm giao điểm bằng cách kiểm tra tọa độ trung điểm. Tiếp cận này được minh họa trong hình 4-10 (xem hình 4-10). Mọi đoạn thẳng với hai điểm đầu mút (x1,y1) và (x2, y2), trung điểm được tính như sau: xm = (x1 + x2) / 2; ym = (y1 + y2) / 2 (4-4) Mỗi kết quả tính toán cho tọa độ giao điểm liên quan đến một phép cộng và một phép chia 2. Khi tọa độ giao điểm được xác định, mỗi nữa đoạn thẳng được kiểm tra để chấp nhận hay huỷ bỏ toàn bộ. Nếu một nữa đoạn được chấp nhận hoặc bị huỷ bỏ, một nữa kia sau đó sẽ được xử lý theo cách tương tự. Điều này tiếp tục cho đến khi gặp một giao điểm. Nếu một nữa được chấp nhận hoặc bị huỷ bỏ toàn bộ, nữa kia tiếp Trang 70
  72. Chương 4: Windowing và Clipping tục được xử lý cho đến khi toàn bộ nó là bị huỷ bỏ hoặc được giữ lại. Cài đặt phần cứng theo phương pháp này có thể giúp ta clipping khỏi biên vùng quan sát nhanh chóng sau khi các đối tượng vừa được chuyển sang hệ tọa độ thiết bị. P • Window m P • Hình 4-10 m P • Các trung điểm, Pm m được dùng trong thuật toán clipping Pm Pm • • Pm • Các kỹ thuật khác cho việc clipping đoạn dùng phương trình tham số của đường thẳng. Chúng ta có thể viết phương trình đường thẳng qua 2 điểm (x1, y1) và (x2, y2) theo hình thức tham số: x = x1 + (x2 – x1)u = x1 + Δx u (4-5) y = y1 + (y2 – y1)u = y1 + Δy u Với Δx = x2 – x1 và Δy = y2 – y1. Tham số u được gán các giá trị từ 0 đến 1, và các tọa độ (x,y) là tọa độ các điểm trên đường ứng với các giá trị cụ thể của u trong đoạn [0,1]. Khi u = 0, (x, y) = (x1, y1). Ở đầu kia của đoạn, u = 1 và (x, y) = (x2, y2). Một thuật toán clipping đường hiệu quả dùng phương trình tham số đã được phát triển bởi Liang và Barsky. Họ ghi chú rằng nếu một điểm (x, y) dọc theo đường mà nằm trong cửa sổ được định nghĩa bởi các tọa độ (xwmin, ywmin) và (xwmax, ywmax), thì các điều kiện sau đây phải được thỏa: xwmin ≤ x1 + Δx u ≤ xwmax (4-6) ywmin ≤ y1 + Δy u ≤ ywmax Bốn bất phương trình trên có thể được viết lại theo hình thức sau: pk u ≤ qk, k = 1, 2, 3, 4 (4-7) ở đây p và q được định nghĩa như sau: p1 = -Δx, q1 = x1 - xwmin p2 = -Δx, q2 = xwmax – x1 (4-8) Trang 71
  73. Chương 4: Windowing và Clipping p3 = -Δy, q3 = y1 - ywmin p4 = Δy, q4 = ywmax – y1 Bất kỳ đoạn thẳng nào song song với một trong các biên cửa sổ sẽ có pk = 0, giá trị k phụ thuộc vào biên cửa sổ (k = 1, 2, 3, và 4 tương ứng với biên trái, phải, dưới, trên ). Nếu với các giá trị đó của k, chúng ta có thể gặp qk 0, đoạn thẳng tiến từ bên trong ra bên ngoài. Với pk khác 0, chúng ta có thể tính giá trị của u tương ứng với điểm mà tại đó đoạn thẳng kéo dài cắt biên k kéo dài của cửa sổ: u = qk/pk (4-9) Đối với mỗi đoạn thẳng, chúng ta có thể tính các giá trị cho các tham số u1 và u2 để xác định phần nào của đoạn nằm bên trong cửa sổ. Giá trị của u1 được xác định bằng cách nhìn ở các cạnh của cửa sổ xem đoạn kéo dài nào từ ngoài vào trong (p 0). Một giá trị của rk được tính cho mỗi biên cửa sổ, và giá trị của u2 là nhỏ nhất trong tập chứa 1 và các giá trị đã được tính của r. Nếu u1 > u2, đoạn hoàn toàn nằm ngoài cửa sổ và có thể bị vứt bỏ. Ngược lại, các điểm đầu mút của đoạn bị cắt được tính từ hai giá trị của tham số u. Thuật toán này được trình bày trong thủ tục sau đây. Các tham số giao điểm của đoạn được khởi tạo các giá trị u1 =0 và u2 = 1. Đối với mỗi biên cửa sổ, các giá trị thích hợp cho p và q được tính và được dùng bởi hàm cliptest để xác định xem đoạn nào có thể bị loại bỏ hoặc xem các tham số giao điểm sắp sửa bị thay đổi không. Khi p 0, tham số r được dùng để cập nhật u2. Nếu việc cập nhật u1 hoặc u2 đưa đến kết quả u1 > u2, chúng ta loại bỏ đoạn thẳng. Ngược lại, chúng ta cập nhật tham số u thích hợp chỉ nếu giá trị mới đưa đến kết quả làm ngắn đoạn thẳng. Khi p=0 và q<0, chúng ta vứt bỏ đoạn thẳng bởi vì nó song song và ở bên ngoài biên. Nếu đoạn thẳng vẫn chưa bị loại bỏ sau tất cả bốn giá trị của p và Trang 72
  74. Chương 4: Windowing và Clipping q vừa được kiểm tra xong, các điểm đầu mút của đoạn bị cắt được xác định từ các giá trị của u1 và u2. var xwmin, xwmax, ywmin, ywmax : real; procedure clipper (var x1, y1, x2, y2 : real); var u1, u2, dx, dy : real; function cliptest (p, q : real; var u1, u2 : real); var r : real; result : boolean; begin result := true; if p u2 then result := false {huỷ bỏ đoạn hoặc cập nhật u1 nếu thích hợp} else if r > u1 then u1 :=r end {if p 0 then begin {đoạn từ bên trong ra bên ngoài của biên} r := q / p; if r 0} else if q < 0 then result := fasle; cliptest := result end; {cliptest} begin {clipper} u1 := 0; u2 := 1; Trang 73
  75. Chương 4: Windowing và Clipping dx := x2 – x1; if cliptest (-dx, x1 – xwmin, u1, u2) then if cliptest (dx, xwmax – x1, u1, u2) then begin dy := y2 - y1; if cliptest (-dy, y1 – ywmin, u1, u2) then if cliptest(dy, ywmax – y1, u1, u2) then begin {nếu u1 và u2 nằm trong đoạn [0,1], dùng để tính các điểm đầu mút mới} if u2 0 then begin x1 := x1 + u1 * dx; y1 := y1 + u1 * dy end; {if u1 > 0} end {if cliptest} end {if cliptest} end; {clipper} Thuật toán clipping đường của Liang và Barsky giảm bớt các tính toán cần thiết để cắt các đoạn. Mỗi lần cập nhật u1 và u2 cần chỉ một phép chia, và các giao điểm với cửa sổ được tính chỉ một lần, khi mà các giá trị u1 và u2 vừa hoàn thành. Trái lại, thuật toán của Cohen và Sutherland lặp lại việc tính giao điểm của đoạn với các biên cửa sổ, và mỗi phép tính giao điểm cần cả hai phép chia và nhân (xem hình 4-11). Hình 4-11 Cửa sổ bị quay được bao quanh bởi một biên chữ nhật lớn hơn (có các cạnh song Window song với hệ trục tọa độ) Hình chữ nhật bao quanh Trang 74
  76. Chương 4: Windowing và Clipping Khi các cửa sổ bị quay hay các đa giác có hình dạng bất kỳ (được dùng làm cửa sổ và vùng quan sát), các thuật toán clipping đã được thảo luận sẽ cần vài sự thay đổi. Nó vẫn có thể được dùng để che chắn các đoạn thẳng. Một cửa sổ bị quay, hoặc một đa giác bất kỳ nào khác, có thể bị bao quanh trong một hình chữ nhật lớn hơn (hình chữ nhật này có các trục song song với các trục tọa độ) (hình 4 -11). Bất kỳ đoạn thẳng nào nằm bên ngoài hình chữ nhật bao quanh lớn hơn (bounding rectangle) thì cũng nằm bên ngoài cửa sổ (window). Các kiểm tra nằm trong cũng không dễ dàng, và các giao điểm phải được tính dùng phương trình đường thẳng của các biên cửa sổ và của các đoạn thẳng bị cắt. Clipping một vùng (Area clipping) Làm thế nào các đa giác được dùng trong các ứng dụng vẽ đường (line-drawing application) có thể bị cắt bằng cách xử lý các đoạn thẳng thành phần thông qua các thuật toán clipping đường đã được thảo luận. Một đa giác được xử lý theo cách này sẽ được thu giảm một loạt các đoạn sẽ bị cắt (xem hình 4-12). Hình 4-12: Đa giác bị cắt bởi một thuật toán clipping đường. Trước khi clipping Sau khi clipping Khi một một biên đa giác định nghĩa một vùng tô, như ở hình 4-13. Một version thay đổi của thuật toán clipping đường được cần đến. Trong trường hợp này, một hoặc nhiều vùng kép kín phải được tạo ra để định nghĩa các biên cho vùng tô (xem hình 4-13). Trang 75
  77. Chương 4: Windowing và Clipping Hình 4 –13: Một vùng có hình dạng, trước và sau khi clipping. Trước khi clipping Sau khi clipping Một kỹ thuật cho việc clipping đa giác, được phát triển bởi Sutherland và Hodgman, thực hiện việc clipping bằng cách so sánh một đa giác với lần lượt mỗi biên cửa sổ. Kết quả trả về của thuật toán là một tập các đỉnh định nghĩa vùng bị cắt (vùng này được tô với một màu hay một mẫu tô nào đó). Phương pháp căn bản được thể hiện trong hình 4-14. Các vùng đa giác được định nghĩa bằng việc xác định một dãy có thứ tự các đỉnh. Để cắt một đa giác, chúng ta so sánh lần lượt mỗi đỉnh với biên một cửa sổ. Các đỉnh nằm bên trong cạnh cửa sổ này được giữ lại cho việc clipping với biên kế tiếp của cửa sổ (xem hình 4-15). Hình 4-14 Clipping một vùng đ a giác bằng cách dùng Đa giác Cắt bên Cắt bên Cắt bên Cắt bên các biên cửa sổ. gốc trái phải dưới trên I Hình 4-15 •S P• S• • •P clipping. • P •S • P• I S• Lưu P Lưu I Không điểm Lưu I, P (a) (b) nào được lưu (d) (c) Trang 76
  78. Chương 4: Windowing và Clipping Quá trình xử lí các đỉnh của một dâ giác liên Hình 4-16 Clipping một đa giác khỏi cạnh bên quan đến biên của cửa sổ. Từ đỉnh S, đỉnh kế tiếp trái cửa sổ, bắt đầu với đỉnh 1. Các số có phẩy được dùng để đánh nhãn được xét (P) có thể sinh ra một điểm, không điểm các điểm được lưu bởi thuật toán clipping. nào, hoặc hai điểm sẽ được lưu bởi thuật toán các Window đỉnh bên ngoài cạnh cửa sổ bị vứt bỏ. Nếu chúng ta 3 2’ 1’ khởi hành từ một điểm bên trong cạnh cửa sổ đi đến 2 một điểm bên ngoài, chúng ta lưu lại giao điểm của 1 đoạn thẳng với biên cửa sổ. Cả hai giao điểm và đỉnh 3’ 4 6 đa giác được lưu lại nếu chúng ta đi từ ngoài cạnh cửa 5’ 4’ sổ vào bên trong. Khả năng thứ tư có thể xảy ra khi 5 chúng ta xử lí một điểm (P) và điểm trước đó (S) với biên cửa sổ được minh họa trong hình 4-15. Một điểm bên trong biên cửa sổ được lưu lại (trường hợp a), trong khi một điểm bên ngoài thì không (trường hợp c). Nếu một điểm P và điểm trước đó S nằm trên các phía đối diện nhau qua một biên (P ở trong, S ở ngoài và ngược lại), giao điểm I được tính và được lưu (trường hợp b và d). Trong trường hợp d, điểm P nằm trong và điểm trước đó S nằm ngoài, vì vậy cả hai giao điểm I và P được lưu. Khi tất cả các đỉnh vừa được xử lí với biên trái cửa sổ, tập các điểm được lưu sẽ tiếp tục bị cắt khi xem xét với biên kế tiếp của cửa sổ. Chúng ta minh họa phương pháp này bằng việc xử lí vùng trong hình 4-16 khi xem xét với biên bên trái của cửa sổ. Đỉnh 1 và 2 được xác định là nằm bên ngoài của biên. Đi qua đến đỉnh 3, đang nằm bên trong, chúng ta tính giao điểm và lưu lại cả hai giao điểm và đỉnh 3. Đỉnh 4 và 5 được xác định là nằm trong, và chúng nó cũng được lưu lại. Đỉnh thứ sáu và đỉnh cuối cùng thì nằm ngoài, vì vậy chúng ta tính và lưu giao điểm. Dùng năm điểm vừa được lưu, chúng ta lặp lại quá trình này khi xem xét với biên kế tiếp của cửa sổ. Cài đặt các thuật toán vừa được mô tả đòi hỏi phải dùng không gian lưu trữ ngoài để lưu các điểm. Điều có thể tránh được nếu chúng ta quản lý được mỗi điểm (điểm sắp sửa được lưu và đi nhanh qua nó để kiểm tra tiếp), cùng với các lệnh (instructions) để cắt nó khỏi biên kế tiếp của cửa sổ. Chúng ta lưu một điểm (dù là một đỉnh nguyên thuỷ của đa giác hay một đỉnh có được khi tính giao điểm) chỉ sau khi nó được xử lí khi xem xét với tất cả các biên. Như thể chúng ta có một đường ống chứa Trang 77
  79. Chương 4: Windowing và Clipping một chuỗi các động tác clipping. Một điểm nằm bên trong hay nằm trên biên cửa sổ ở một giai đoạn sẽ được đi qua để đến giai đoạn kế tiếp. Thủ tục sau đây thể hiện tiếp cận này . Một mảng s, lưu những điểm mới nhất vừa bị cắt cho với mỗi biên của cửa sổ. Quá trình chính đi qua mỗi đỉnh p đi vào quá trình clip_this để xem xét việc cắt với cạnh đầu tiên của cửa sổ . Nếu đoạn thẳng được định nghĩa bởi điểm đầu mút p và s[edge] cắt cạnh cửa sổ này, giao điểm được xác định và được đi qua để đến giai đoạn kế tiếp. Nếu p nằm bên trong cửa sổ, nó bị bỏ qua để đến giai đoạn clipping kế tiếp. Bất kì điểm nào còn được giữ lại sau khi xem xét với tất cả các cạnh của cửa sổ thì sau đó được gia nhập vào mảng kết quả kết xuất x_out và y_out. Mảng first_point lưu giữ cho mỗi cạnh cửa sổ điểm đầu tiên bị cắt bởi cạnh đó. Sau khi tất cả các đỉnh của đa giác vừa được xem xét xong, một quá trình kết thúc cắt các đoạn (đoạn đã được định nghĩa bởi các điểm đầu và cuối (các điểm bị cắt khỏi mỗi mỗi cạnh)). type point = array [1 max_points] of real; procedure polygon_clip (n : integer; x, y : points; var m : integer; var x_out, y_out : points); const boundary_count = 4; type vertex = array [1 2] of real; boundary_range = 1 boundary_count; var k : integer; p : vertex; s, first_point : array [1 boudary_count] of vertex; new_edge : array [1 boundary_count] of boolean; function inside (p : vertex; edge : boundary_range) : boolean; begin {trả về true nếu đỉnh p nằm trong cạnh edge cửa sổ} end; { inside} Trang 78
  80. Chương 4: Windowing và Clipping function cross (p, s : vertex; edge : integer) : boolean; begin {trả về true nếu cạnh đa giác ps cắt biên cửa sổ} end; {cross} procedure output_vertex (p : vertex); begin m := m +1; x_out[m] := p[1]; y_out[m] := p[2]; end; { output_vertex } procedure find_intersection (p, s : vertex; edge : boundary_range; var i; vertex); begin {trả về trong tham số i giao điểm của ps với biên edge cửa sổ } end; { intersection } procedure clip_this (p : vertex; edge : boundary_range); var i : vertex; begin{ clip_this } {lưu điểm đầu tiên cắt biên cửa sổ} if new_edge[edge] then begin first_point[edge] := p; new_edge[edge] := false end {new_edge} else {nếu ps cắt biên cửa sổ, tìm giao điểm, cắt giao điểm khỏi cạnh kế tiếp của cửa sổ} if cross (p, s[edge], edge) then begin find_intersection (p, s[edge], edge , i); if edge < boundary_count then clip_this (i, edge +1) else output_vertex (i) Trang 79
  81. Chương 4: Windowing và Clipping end; {nếu ps cắt cạnh} {cập nhật các đỉnh đã được lưu} s[edge] := p; {nếu p nằm bên trong cạnh cửa sổ này, cắt nó khỏi cạnh kế tiếp của cửa sổ} if inside (p, edge) then if edge < boundary_count then clip_this (p, edge +1) else output_vertex (p) end; {clip_this} procedure clip_closer; {đóng quá trình. Đối với mỗi cạnh của cửa sổ, cắt đường (đang nối với đỉnh được lưu sau cùng và điểm first_point bị xử lý khỏi cạnh)} var i : vertex; edge : integer; begin for edge := 1 to boundary_count do if cross (s[edge], first_point[edge], edge) then begin find_intersection (s[edge], first_point[edge], edge, i); if edge < boundary_count then clip_this (i, edge +1) else output_vertex (i) end {nếu s và first_point cắt cạnh} end; {clip_closer} begin {polygon_clip} m :=0; {số các đỉnh kết xuất} for k := 1 to boundary_count do new_edge[k] := true; for k:= 1 to n do begin {đặt mỗi đỉnh vào đường ống (pipeline)} p[1] := x[k]; p[2] := y[k]; clip_this (p, 1) {cắt khỏi cạnh đầu tiên của cửa sổ} end; {for k} Trang 80
  82. Chương 4: Windowing và Clipping clip_closer {đóng đa giác} end; { polygon_clip } Khi một đa giác lõm bị cắt bởi một cửa sổ hình chữ nhật, vùng bị cắt sau cùng có thể hình thành hai đa giác riêng biệt thật sự. Vì thuật toán cắt vùng này chỉ tạo ra một danh sách các đỉnh, các vùng riêng biệt này sẽ được nối lại bằng các đoạn thẳng nối. Một ví dụ của hiệu ứng này được thể hiện trong hình 4-17. Sự xem xét đặt biệt có thể được thực hiện đối với trường hợp như thế để gỡ bỏ các đoạn nối dư thừa, hoặc các thuật toán clipping tổng quát hơn sẽ được phát triển (xem hình 4-17). Hình 4-17: Clipping đa giác lõm trong hình (a) bởi một cửa sổ tạo ra hai vùng nối nhau trong hình (b) Window (a) (b) Dù chúng ta đã và đang giới hạn việc thảo luận của chúng ta đối với các cửa sổ chữ nhật có các cạnh song song với trục x và trục y., chúng ta có thể cài đặt thuật toán này với cửa sổ có hình đa giác bất kì. Chúng ta có thể cần lưu trữ thông tin về mỗi biên cửa sổ, và chúng ta có thể cần thay đổi thủ tục inside và find_intersection để quản lý thuộc tính của các biên tuỳ ý. Một tiếp cận khác để clipping các vùng đa giác là dùng các phương pháp phương trình tham số. Các cửa sổ hình dạng tuỳ ý sau đó có thể được xử lí bằng cách dùng phương trình tham số của đường thẳng để mô tả cả hai: biên cửa sổ và các biên của vùng bị cắt. Các vùng bị clipping hình dạng khác đa giác cần thực hiện nhiều công việc hơn một chút, vì biên của các vùng này không được định nghĩa bằng các phương trình Trang 81
  83. Chương 4: Windowing và Clipping đường thẳng. Ví dụ, trong hình 4-18, phương trình đường tròn được cần để tìm hai giao điểm trên biên cửa sổ. Hình 4-18: Clipping một vùng có hình dạng tròn. Trước khi clipping Clipping văn bản (Text Clipping) Có vài kỹ thuật có thể được dùng để clipping văn bản trong gói đồ họa. Việc chọn lựa phương pháp cụ thể để cài đặt phụ thuộc vào các phương pháp đã được dùng để sinh ra các kí tự và mức độ tinh vi được đòi hỏi bởi người dùng trong việc xử lí văn bản (xem hình 4-19). Hình 4-19 Clipping văn bản dùng các biên chữ nhật. Bất kỳ hình chữ nhật nào mà nằm đè lên biên cửa sổ đều bị vứt bỏ hoàn toàn. Trước khi clipping Sau khi clipping Phương pháp đơn giản nhất để xử lí các chuỗi kí tự có liên quan đến một biên cửa sổ là dùng chiến lượt “clipping tất cả văn bản hoặc không clipping gì cả” (all-or-none text-clipping), được trình bày trong hình 6-19. Nếu tất cả chuỗi kí tự nằm bên trong một cửa sổ, chúng ta giữ lại nó. Ngược lại, chuỗi vứt bỏ. Thủ tục này có thể được cài đặt bằng việc xem xét một hình chữ nhật bao quanh mẫu văn bản. Các vị trí biên của hình chữ nhật sau đó được so sánh với các biên cửa sổ, và chuỗi bị huỷ bỏ nếu có bất kì sự nằm đè nào. Phương pháp này cho ta clipping nhanh nhất. Một sự chọn lựa để loại bỏ toàn bộ chuỗi kí tự nếu nó nằm đè lên biên một cửa sổ là dùng chiến lược “clipping kí tự toàn bộ hoặc không” (all-or-none character- clipping). Ở đây chúng ta vứt bỏ chỉ những kí tự nào không hoàn toàn nằm trong cửa Trang 82
  84. Chương 4: Windowing và Clipping sổ ( xem hình 4-20). Trong trường hợp này, các giới hạn biên của các kí tự đơn lẻ được so sánh với cửa sổ. Bất kì kí tự nào hoặc nằm đè lên hoặc nằm bên ngoài biên cửa sổ đều bị cắt bỏ. Hình 4-20 Các chuỗi kí tự có thể hoàn toàn bị cắt để mà chỉ những kí tự hoàn nằm bên trong cửa sổ mới được giữ lại. Trước khi clipping Sau khi clipping Phương pháp sau cùng cho việc quản lí việc cắt văn bản là cắt các kí tự riêng lẻ. Bây giờ chúng ta xem các kí tự cũng tương tự như các đoạn thẳng. Nếu một kí tự riêng lẻ nằm đè lên biên cửa sổ, chúng ta cắt bỏ phần nằm ngoài cửa sổ (xem hình 4-21). Các kí tự được hình thành với các đoạn thẳng có thể được xử lí theo cách này, bằng cách dùng thuật toán clipping đường. Việc xử lí các kí tự được hình thành bởi các bản đồ bit cần clipping những pixel đơn lẻ bằng cách so sánh các vị trí liên hệ của các mẫu lưới (patern grid) với các biên cửa sổ. Hình 4-21 Clipping các kí tự đơn lẻ. Trước khi clipping Sau khi clipping Tẩy xoá (banking) Thay vì lưu giữ lại thông tin trong một vùng được định nghĩa,, một vùng cửa sổ có thể được dùng để xóa bỏ bất kì thứ gì bên trong biên của nó. Những gì nằm bên ngoài được giữ lại. Việc xoá bỏ tất cả các màu kết xuất trong một vùng chỉ định có ý nghĩa thuận lợi cho việc nạp chồng các hình ảnh khác. Các kỹ thuật này thường được dùng để thiết kế các trang trình bày (layout) trong quảng cáo hoặc trong các ứng dụng xuất bản (publishing) hoặc cho việc thêm các nhãn hoặc mẫu thiết kế đến một hình ảnh. Kỹ Trang 83
  85. Chương 4: Windowing và Clipping thuật cũng được dùng để nối kết các biểu đồ, bản đồ, hoặc giản đồ. Hình 4-22 minh họa vài ứng dụng của tẩy xóa. Khi hai hiển thị che phủ lên nhau dùng đến các phương pháp tẩy xóa, một cái có thể được nghĩ đến như cận cảnh (ảnh ở gần-foreground) và những cái còn lại được xem như ảnh nền (background). Một cửa sổ xóa, cái đang bao quanh vùng hiển thị cận ảnh, được đặt lên trên ảnh nền, và các phần hình ảnh nằm trong vùng cửa sổ bị xóa sạch. Hai hiển thị được nối kết lại, với các thông tin của cận ảnh được đặt vào vùng cửa sổ bị xóa. Hình 4-22 Các ví dụ về tẩy xóa: (a) Một vùng được cung cấp để dán nhãn; (b) Một vùng được dùng để xóa một phần của hiển thị trước đó để tạo ra một vùng trống cho nạp chồng ảnh mới lên. (a) (b) 4.4. Phép biến đổi từ cửa sổ - đến – vùng quan sát Khi tất cả các điểm, đoạn thẳng, và văn bản vừa bị cắt, chúng được ánh xạ lên vùng vùng quan sát để hiển thị. Phép biến đổi đến vùng quan sát này được thực hiện để các vị trí tọa độ liên hệ được giữ lại. Trong hình 4-23, một điểm ở vị trí (xw, yw) trong một cửa sổ được ánh xạ và trong vị trí (xv, yv) trong vùng quan sát. Để duy trì sự sắp đặt liên hệ tương tự trong vùng quan sát như trong cửa sổ, chúng ta cần: xw− xw xv− xv min = min (4-10) xw− xw xv− xv max min max min và yw− yw yv− yv min = min (4-11) yw− yw yv− yv max min max min Ta viết lại phương trình (4-10) và (4-11) như các phép tính biến đổi rõ ràng cho các tọa độ xv và yv: xv− xv xv = max min (xw− xw) + xv (4-12) xw− xw min min max min yvmax − yvmin yv = (yw− ywmin ) + yvmin ywmax − ywmin Trang 84