Windowing và Clipping
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à ...
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ổ
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ư 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).
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 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).
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.
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); 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:
Để 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)
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).
Á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.
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ỏ.
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ổ. Đ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).
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).
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à 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 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_min then c[left]:= true else c[left]:= false; if x > xw_max then c[right]:= true else c[right]:= false; if y < yw_min then c[bottom]:= true else c[bottom]:= 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ỏ// 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 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 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ị.
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)
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, khi đó đoạn thẳng sẽ hoàn toàn nằm ngoài biên và có thể bị loại bỏ khi xét sau này. Nếu qk ≥ 0, đường thẳng tương ứng nằm trong biên.
Khi pk < 0, sự kéo dài không giới hạn của đoạn thẳng từ bên ngoài vào bên trong của biên cửa sổ kéo dài. Nếu pk > 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). Đối với các cạnh cửa sổ, chúng ta tính rk = qk/ pk. Giá trị của u1 là lớn nhất trong tập chứa 0 và các giá trị khác của r. Ngược lại, giá trị của u2 được xác định bằng cách kiểm tra các biên xem đoạn nào kéo dài nào từ bên trong ra bên ngoài (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 u1; 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à 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 < 0 then begin //đoạn từ bên ngoài vào bên trong biên // r := q / p; if r > 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// else 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 < u1 then result := false else if r < u2 then u2 := r end //if p > 0// else if q < 0 then result := fasle; cliptest := result end; //cliptest// begin //clipper// u1 := 0; u2 := 1; 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 < 1 then begin x2 := x1 + u2 * dx; y2 := y1 + u2 * dy end; {if u2 < 1} if u1 > 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).
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).
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).
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).
Quá trình xử lí các đỉnh của một đa giác liên quan đến biên của cửa sổ. Từ đỉnh S, đỉnh kế tiếp được xét (P) có thể sinh ra một điểm, không điểm nào, hoặc hai điểm sẽ được lưu bởi thuật toáncác đỉnh bên ngoài cạnh cửa sổ bị vứt bỏ. Nếu chúng ta khởi hành từ một điểm bên trong cạnh cửa sổ đi đến một điểm bên ngoài, chúng ta lưu lại giao điểm của đoạn thẳng với biên cửa sổ. Cả hai giao điểm và đỉnh đa giác được lưu lại nếu chúng ta đi từ ngoài cạnh cửa sổ vào bên trong. Khả năng thứ tư có thể xảy ra khi 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 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// 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) 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} 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).
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 đườ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ổ.
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).
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 4-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 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ỏ.
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ổ.
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ỹ 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.
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−xwminxwmax−xwmin=xv−xvminxvmax−xvmin size 12{ { { ital "xw" - ital "xw" rSub { size 8{"min"} } } over { ital "xw" rSub { size 8{"max"} } - ital "xw" rSub { size 8{"min"} } } } = { { ital "xv" - ital "xv" rSub { size 8{"min"} } } over { ital "xv" rSub { size 8{"max"} } - ital "xv" rSub { size 8{"min"} } } } } {} (4-10)
yw−ywminywmax−ywmin=yv−yvminyvmax−yvmin size 12{ { { ital "yw" - ital "yw" rSub { size 8{"min"} } } over { ital "yw" rSub { size 8{"max"} } - ital "yw" rSub { size 8{"min"} } } } = { { ital "yv" - ital "yv" rSub { size 8{"min"} } } over { ital "yv" rSub { size 8{"max"} } - ital "yv" rSub { size 8{"min"} } } } } {} (4-11)và
xv=xvmax−xvminxwmax−xwmin(xw−xwmin)+xvmin size 12{ ital "xv"= { { ital "xv" rSub { size 8{"max"} } - ital "xv" rSub { size 8{"min"} } } over { ital "xw" rSub { size 8{"max"} } - ital "xw" rSub { size 8{"min"} } } } ( ital "xw" - ital "xw" rSub { size 8{"min"} } ) + ital "xv" rSub { size 8{"min"} } } {} (4-12) (6-12) 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:
yv=yvmax−yvminywmax−ywmin(yw−ywmin)+yvmin size 12{ ital "yv"= { { ital "yv" rSub { size 8{"max"} } - ital "yv" rSub { size 8{"min"} } } over { ital "yw" rSub { size 8{"max"} } - ital "yw" rSub { size 8{"min"} } } } ( ital "yw" - ital "yw" rSub { size 8{"min"} } ) + ital "yv" rSub { size 8{"min"} } } {} (6-12)
Các phép tính biến đổi từ cửa sổ - đến - vùng quan sát có thể được viết chặt chẽ hơn như sau:
xv = sx(xw - xwmin) + xvmin (4-13)
yv = sy(yw - ywmin) + yvmin
Phép biến đổi này bao gồm cả hai phép biến đổi tỉ lệ và tịnh tiến. Các hệ số tỉ lệ sx và sy phụ thuộc vào kích thước liên hệ của cửa sổ và vùng quan sát. Các hệ số tỉ lệ này phải bằng nhau nếu các đối tượng muốn được bảo tồn sự cân đối (đồng dạng) khi chúng được ánh xạ đến vùng quan sát. Khi cửa sổ và vùng quan sát có kích thước bằng nhau (sx = sy = 1), không có sự thay đổi nào về kích thước của các đối tượng được biến đổi. Giá trị của xvmin và yvmin cho biết các hệ số tịnh tiến để di chuyển các đối tượng vào vùng quan sát.
Các chuỗi kí tự có thể được quản lí theo hai cách khi chúng được ánh xạ đến vùng quan sát. Việc ánh xạ đơn giản nhất bảo tồn kích thước kí tự, thậm chí khi vùng quan sát được mở rộng hay thu nhỏ lại so với cửa sổ. Phương pháp này có thể được dùng đến khi văn bản được tạo ra với các font chuẩn – không thể bị thay đổi. Trong các hệ thống khi mà có sự cho phép thay đổi kích thước kí tự chuẩn, sự định nghĩa chuỗi có thể được đặt trong cửa sổ tương tự như các từ gốc. Đối với các kí tự được hình thành bởi các đoạn thẳng, việc ánh xạ đến vùng quan sát có thể được thực hiện như một dãy tuần tự các phép biến đổi đường (xem hình 4-23).
- Cần nắm vững khái niệm Window, cách mã vùng theo giải thuật Cohen-Sutherland. Phân biệt điểm thuộc và không thuộc window.
- Lưu ý cách sử dụng phương trình tham số của đường thẳng trong giải thuật Liang-Barsky.
- Có thể hiệu chỉnh các thuật toán xén đoạn thẳng để xén đa giác bằng cách xem đa giác như là một tập các đoạn thẳng liên tiếp nối với nhau. Tuy nhiên, kết quả xén được là tập các đoạn thẳng rời nhau.
- Lưu ý điều chúng ta mong muốn là kết quả sau khi xén một đa giác phải là một hoặc các đa giác để có thể chuyển thành các vùng tô.
- Viết chương trình tạo cửa sổ hình chữ nhật có tọa độ các điểm dưới bên trái và điểm trên bên phải lần lượt là (Xmin, Ymin) và (Xmax, Ymax).
- Tiếp tục bài 1, hãy xét một điểm P(x,y) có nằm bên trong cửa sổ không ? Biết rằng nếu P(x,y) nằm bên trong cửa sổ thì P sẽ thoả hệ bất phương trình sau :
Xmin ≤ x ≤ Xmax
Ymin ≤ y ≤ Ymax
- Tiếp tục bài tập 2, xét bài toán xén đoạn thẳng được cho bởi các điểm P1(x1, y1), P2(x2, y2) bất kỳ.
- Tiếp tục bài tập 3, sử dụng thuật toán Cohen - Sutherland (phân chia mã vùng) xét bài toán xén các đoạn thẳng được cho bởi các điểm P1(x1, y1), P2(x2, y2), P3(x3, y3), P4(x4, y4), P5(x5, y5), P6(x6, y6), P7(x7, y7), và P8(x8, y8) vào cửa sổ chữ nhật trên xem hình vẽ (a) và (b)).
5. Thảo luận kỹ nhân tố căn bản đằng sau các kiểm tra và phương khác nhau để tính các tham số giao nhau u1 và u2 trong thuật toán clipping đường Liang-Barsky.
6. So sánh số lượng các phép tính toán học được thực hiện trong các thuật toán clipping đường Cohen-Sutherland và Liang-Barsky đối với vài hướng đoạn thẳng khác nhau liên quan đến cửa sổ clipping.
7. Cài đặt thuật toán thuật toán clipping đường Liang-Barsky lên hệ thống của bạn.
8. Hãy nghĩ ra một thuật toán để thực hiện việc clipping đường bằng cách dùng phương pháp phân chia điểm ở giữa. Sự cài đặt phần mềm của thuật toán này có thuận lợi hơn hai thuật toán clipping đường đã được thảo luận trong chương không?
9. Cài đặt một thuật toán cắt các đoạn thẳng bằng cách dùng một cửa sổ bị quay, được định nghĩa bởi các giá trị tọa độ nhỏ nhất và lớn nhất và bị quay một góc như trong hình 6-5.
10. Thay đổi thuật toán clipping đa giác để cắt các vùng đa giác lõm một cách hợp lý. (Một phương pháp để thực hiện điều này là chia đa giác lõm ra làm các đa giác lồi.)
11. Sửa lại cho hợp lí thuật toán clipping đường Liang-Barsky để clipping đa giác.
12. Viết thủ tục để cắt một ellipse bằng cách dùng cửa sổ chữ nhật.
13. Giả sử rằng các kí tự được định nghĩa trong một lưới điểm (pixel grid), hãy phát triển một thuật toán clipping văn bản để cắt các kí tự đơn lẻ theo chiến lược “tất cả - hoặc - không”.
14. Hãy phát triển một thuật toán clipping văn bản để cắt các kí tự đơn lẻ, giả sử rằng các kí tự được định nghĩa trong một lưới điểm (pixel grid).
15. Viết một thủ tục thực hiện xóa một phần bất kì của hình ảnh đã được định nghĩa, dùng kích thước cửa sổ xóa được xác định bất kỳ.
16. Viết các thủ tục để cài đặt các lệnh của cứa sổ và vùng quan sát. Tức là, các thủ tục có chứa tham số về hệ tọa độ trong các lệnh để thực hiện biến đổi sang vùng quan sát cho các cảnh cụ thể: clipping trong hệ tọa độ thế giới thực, chuyển đổi sang hệ tọa độ chuẩn hóa, sau cùng biến đổi đến hệ tọa độ thiết bị.