Clipping một vựng (Area clipping)

Một phần của tài liệu Tìm hiểu về đồ họa máy tính ppt (Trang 104 - 117)

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

Khi một một biờn đa giỏc định nghĩa một vựng tụ. 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ụ.

Hỡnh 6.13. Một vựng cú hỡnh dạng, trước và 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 như hỡnh 5.14:

Hỡnh65.12. Đa giỏc bị cắt bởi một thuật toỏn clipping đường

Hỡnh 6.14.Clipping một vựng đa giỏc bằng cỏch dựng cỏc biờn cửa sổ

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ổ.

Hỡnh 6.15.Clipping

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ỏn cỏ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 clipping. 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 như hỡnh dưới đõy 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

104

Hỡnh 6.16. Clipping một đa giỏc khỏi cạnh bờn 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ỏc điểm được lưu bởi thuật toỏn clipping.

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}

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}

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 sau. 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.

Hỡnh 6.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)

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 insidefind_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. Phương trỡnh đường trũn được cần để tỡm hai giao điểm trờn biờn cửa sổ như hỡnh dưới đõy.

Hỡnh 6.18. Clipping một vựng cú hỡnh dạng trũn.

6.2.5.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.

Hỡnh 6.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.

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). 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ổ. 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 6.20. Cỏc chuỗi kớ tự cú thể hoàn toàn bị cắt để mà chỉ những kớ tự nằm trong cửa sổ mới được giữ lại.

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ổ. 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 6.21. Clipping cỏc kớ tự đơn lẻ.

Vấn đề Clipping (cắt bỏ những phần khụng nằm trong cửa sổ)

Vấn đề đặt ra là cần phải cắt bỏ những phần của đối tượng khụng nằm trong cửa sổ. Vỡ ta đó coi đoạn thẳng là nguyờn thể đồ họa nờn vấn đề quy về việc làm sao để clipping một đoạn thẳng. Sau đõy ta ỏp dụng thuật toỏn Cohen – Sutherland để giải quyết vấn đề này.

Trước hết xột một điểm (X,Y). Nếu tọa độ của nú vi phạm một trong cỏc điều kiện sau thỡ điểm đú nằm ngoài cửa sổ và sẽ bị loại bỏ

F1≤ X ≤ F2 và F3≤ Y ≤ F4

Dấu bằng cho thấy cỏc điểm nằm trờn biờn được coi như nằm trong cửa sổ.

Với đoạn thẳng, ta kộo dài cỏc đường biờn cửa sổ thành cỏc đường thẳng. Chỳng chia mặt phẳng làm 9 vựng. Mỗi điểm trong mặt phẳng sẽ tương ứng với mó 4 bit được xỏc định theo quy tắc sau:

• bit thứ 1 là 1 nếu điểm đú nằm bờn trỏi cửa sổ

• bit thứ 2 là 1 nếu điểm đú nằm bờn phải cửa sổ

• bit thứ 3 là 1 nếu điểm đú nằm bờn dưới cửa sổ

• bit thứ 4 là 1 nếu điểm đú nằm bờn trờn cửa sổ

Nhận xột:

• Đoạn thẳng nằm hoàn toàn trong cửa sổ khi và chỉ khi mó của cả 2 đầu mỳt là 0000. Ngược lại, nếu một trong hai mó khỏc 0000 thỡ đoạn thẳng cú 1 phần hoặc toàn bộ nằm ngoài cửa sổ

• Nếu kết quả phộp AND hai mó của 2 đầu mỳt khỏc 0000 thỡ đoạn thẳng tương ứng hoàn toàn nằm ngoài cửa sổ và sẽ khụng được hiển thị lờn màn hỡnh. 1001 1000 1010 0001 0101 Cửa sổ 0000 0100 0010 0110

Cỏc bước:

- Nếu cả hai mó thuộc tớnh đều là 0000 thỡ đoạn thẳng hoàn toàn nằm trong cửa sổ

- Nếu kết quả phộp AND hai mó khỏc 0000 thỡ đoạn thẳng hoàn toàn nằm ngoài cửa sổ

- Trường hợp khụng rơi vào hai khả năng trờn: giao điểm của đoạn thẳng với biờn cửa sổ chia đoạn thẳng đó cho thành nhiều đoạn. Ta xột từng đoạn theo cỏch như trờn.

Toàn bộ cỏc bước kể trờn được thể hiện trong thủ tục CAT dưới đõy:

PROCEDURE Cat (X1,Y1,X2,Y2 : Real); TYPE Region = (Left,Right,Low,High); Code = SET OF Region;

VAR C,C1,C2 : Code; X,Y : Real;

XX1,YY1 : Integer; XX2,YY2 : Integer;

PROCEDURE MaNhiPhan (X,Y : Real; VAR C : Code); {Tạo mó thuộc tớnh cho 2 đầu, xõy dựng tập C của điểm (X,Y)}

BEGIN 1001 1000 1010 0001 0101 0000 0100 0010 0110 a b m n j f g e c d h i 112

C := [];

IF X < XgFen THEN C := [Left] {nằm bờn trỏi đường thẳng X=XgFen}

ELSE IF X > XdFen THEN C := [Right]; IF Y < YbFen THEN C := C+[Low]

ELSE IF Y > YhFen THEN C := C+[High] END; {MaNhiPhan}

BEGIN

MaNhiPhan (X1,Y1,C1); MaNhiPhan (X2,Y2,C2);

WHILE (C1 <> []) OR (C2 <> []) DO {chừng nào ớt nhất 1 trong 2 điểm cũn nằm ngoài cửa sổ }

BEGIN {Cắt dần để tỡm đoạn hiển thị}

IF (C1*C2) <> [] THEN Exit; {C1∩C2 ≠∅: cắt toàn bộ}

IF C1 = [] THEN C := C2 ELSE C := C1; {chọn C là điểm nằm ngoài} IF Left IN C

THEN BEGIN

{tỡm giao điểm (X,Y) với dt X=XgFen} X := XgFen;

Y := Y1+(Y2-Y1)*(XgFen-X1)/(X2-X1) END

ELSE IF Right IN C THEN

{tỡm giao điểm (X,Y) với dt X=XdFen} BEGIN X := XdFen; Y := Y1+(Y2-Y1)*(XdFen-X1)/(X2-X1) END ELSE IF Low IN C THEN BEGIN Y := YbFen; X := X1+(X2-X1)*(YbFen-Y1)/(Y2-Y1) END

ELSE IF High IN C THEN BEGIN

Y := YhFen;

X := X1+(X2-X1)*(YhFen-Y1)/(Y2-Y1) END;

IF C = C1 {X1,Y1 nằm ngoài cửa sổ} THEN BEGIN

X1 := X; {gỏn giao điểm (X,Y) mới tỡm được cho (X1,Y1)} Y1 := Y;

MaNhiPhan (X,Y,C1) {tớnh lại tập C1} END

ELSE BEGIN {X2,Y2 nằm ngoài cửa sổ } X2 := X; Y2 := Y; MaNhiPhan (X,Y,C2) END END; {While} XX1 := Round ((X1-XgFen)*Xtl); YY1 := Round ((YhFen-Y1)*Ytl); XX2 := Round ((X2-XgFen)*Xtl); YY2 := Round ((YhFen-Y2)*Ytl); MoveTo (XX1,YY1);

LineTo (XX2,YY2) END;

Một phần của tài liệu Tìm hiểu về đồ họa máy tính ppt (Trang 104 - 117)

Tải bản đầy đủ (DOC)

(177 trang)
w