Nguyên lý chung

Một phần của tài liệu Giao trinh đồ họa máy tính 2012 (Trang 28)

Đầu vào: cho 2 điểm đầu mút (x1,y1) (x2,y2), màu vẽ C. Phương trình đường thẳng đi qua 2 điểm đầu mút: (x-x1)/(y-y1)=(x2-x1)/(y2-y1)

Y=(y2-y1)*(x-x1)/(x2-x1)+y1 Đặt m= (y2-y1)/(x2-x1) b= y1-mx1

ta cĩ phương trình y=mx+b

m được gọi là độ dốc hay hệ số gĩc của đường thẳng b được gọi là đoạn chắn trên trục y.

Từ phương trình này chúng ta cĩ thể xây dựng quá trình vẽ các đường thẳng khi cho x biến thiên các khoảng ∆x và kết quả ta cĩ thể thu được giá trị của y thay đổi với các khoảng ∆y tương ứng ∆y=m∆x.

Hoặc cĩ thể làm ngược lại cho y biến thiên từng khoảng ∆y và kết quả ta cĩ thể thu được giá trị của x thay đổi các khoảng ∆x tương ứng ∆x=∆y/m

Đơn vị nhỏ nhất của màn hình là một điểm ảnh nên thơng thường chọn ∆x= 1 (∆x= -1) hoặc ∆y= 1 (∆y= -1).

Nguyên lý chung là cho một thành phần tọa độ x hay nguyên biến đổi theo từng đơn vị và tính tọa độ nguyên cịn lại sao cho gần với tọa độ thực nhất.

Việc quyết định chọn x hay y biến đổi phụ thuộc vào dáng điệu của đoạn thẳng để ta cĩ thể thu được đoạn thẳng xấp xỉ tốt nhất của đoạn thẳng thực tế.

Nếu |dx| >|dy|, x biến đổi theo từng đơn vị, tính thành phần y tương ứng Nếu |dx| < |dy|, y biến đổi theo từng đơn vị, tính thành phần x tương ứng

Do các đường thẳng được mơ tả trong hệ tọa độ thực nhưng khi hiển thị trong máy tính, hệ tọa độ chính là lưới nguyên nên bản chất của quá trình vẽ các đường thẳng chính là sự nguyên hĩa các tọa độ các điểm thuộc đường thẳng và vẽ các pixel tương ứng.

2.1.2 Thuật tốn DDA (Digital DifferentialAnalyzer)

Để đơn giản hĩa giải thuật, chúng ta chỉ xét các đường thẳng cĩ hệ số gĩc m trong khoảng [0,1] và Dx>0. Mỗi bước nhẩy của x trong mỗi lần tính tương đương một điểm ảnh. Như vậy tại bước i+1

xi+1=xi + 1

Và tọa độ y tương ứng yi+1=yi+m

Vì m là số thực nên để thu được yi+1 nguyên buộc ta phải làm trịn y trước khi đưa tọa độ truy xuất lên màn hình.

Với đường thẳng cĩ hệ số gĩc m>1, ta cĩ thể cho x biến đổi theo y nghĩa là ở đây y đĩng vai trị tăng và x được tính theo tương ứng: yi+1=yi+1, xi+1=xi+1/m. Và chúng ta cĩ thể tính tương tự cho các trường hợp cịn lại.

Hình 2.8

Cài đặt minh họa thuật tốn DDA

#define Round(a) int(a+0.5) int Color = GREEN;

void LineDDA (int x1, int y1, int x2, int y2) {

int x = x1; float y = y1;

float m = float(y2-y1)/(x2-x1);

putpixel(x, Round(y), Color); for(int i=x1; i<x2; i++) {

x++;

y +=m;

putpixel(x, Round(y), Color); }

} // LineDDA

Nhận xét:

Độ chính xác của thuật tốn cao, đoạn thẳng vẽ được thể hiện rất gần với đoạn thẳng thực tế.

Tuy nhiên tốc độ tính tốn chậm do phải thường xuyên làm việc với các phép tốn cộng số thực và làm trịn. (adsbygoogle = window.adsbygoogle || []).push({});

2.1.3 Thuật tốn vẽ đoạn thẳng Bresenham

Giữa những năm 1960 nhà nghiên cứu Bresenham thuộc IBM đã theo nguyên lý tìm ra các điểm gần với đường thẳng dựa trên độ phân giải hữu hạn của màn hình vẽ.

Đây là một phương pháp cĩ hiệu quả chỉ sử dụng cộng trừ các số nguyên và phép nhân. Thực tế cho thấy rằng, máy tính cĩ thể biểu diễn phép cộng trừ các số nguyên một cách nhanh chĩng, giải quyết được về mặt thời gian khi biểu diễn các phép nhân, chia cho lũy thừa của 2 vì chỉ phải sử dụng các phép dịch bit.

Xét đoạn thẳng cĩ hệ số gĩc m∈[0,1] Dx>0

Lúc này bằng cách cho x tăng một đơn vị tại mỗi bước, ta sẽ tìm cách tính y để vẽ các pixel tương ứng.

Giả sử ở bước thứ k ta đã xác định các tọa độ nguyên (xk, yk) như vậy chúng ta cần xác định tọa độ (xk+1, yk+1) cho bước kế tiếp

Theo cơng thức ta cĩ: xk+1= xk+1

Giá trị của yk+1 cĩ thể được chọn bởi một trong 2 giá trị yk hoặc yk+1. Điểm được chọn là điểm gần với y thực nhất.

Hình 2.8

Xét khoảng cách d1, d2 từ y thực đến yk và đến yk+1

Gọi (xk+1,y) là điểm thuộc đoạn thẳng, ta cĩ y=m(xk+1)+b d1 = y - yk = m(xk +1) + b - yk d2 = yk+1 - y = yk + 1 - m(xk + 1) - b - Nếu d1 < d2 => yk+1 = yk - Ngược lại d1 >= d2 => yk+1 = yk +1 d1 - d2= 2m(xk + 1) - 2yk + 2b - 1 m=(y2-y1)/(x2-x1)

Nếu xác định được dấu của d1-d2 thì sẽ biết được điểm ảnh nào gần với đoạn thẳng hơn. Xác định tham số quyết định Pk cùng dấu với d1-d2.

Đặt Pk = (x2-x1) (d1 - d2)

Do Dx>0 nên Pk cùng dấu với d1-d2

Pk = (x2-x1)[(2(y2-y1)(xk +1)+(x2-x1)(- 2yk +2b-1)]/(x2-x1) =2(y2-y1)xk-2(x2-x1)yk+c

Trong đĩ c là hằng số đối với đoạn thẳng và c=2(y2-y1)+(x2-x1)(2b-1) Pk+1 =2(y2-y1)xk+1-2(x2-x1)yk+1+c

Pk+1 tại bước thứ k+1 được tính tăng dần bằng cách sử dụng giá trị Pk tại bước thứ k như sau : +) Pk<0 ⇒d1<d2 chọn yk+1=yk Pk+1 =2(y2-y1)(xk+1)-2(x2-x1)yk+c =Pk +2(y2-y1) +) Pk>=0 ⇒d1>=d2 chọn yk+1=yk+1 Pk+1 =2(y2-y1)(xk+1)-2(x2-x1)(yk+1)+c =Pk +2(y2-y1)-2(x2-x1)

Tính giá trị P1 khởi tạo :

P1=2(y2-y1)x1-2(x2-x1)y1+2(y2-y1)+(2b-1)(x2-x1)

Do (x1, y1) là điểm nguyên thuộc đoạn thẳng nên ta cĩ y1=mx1+b = (Dy/Dx)*x1 + b.

Thế vào phương trình trên ta suy ra : P1=2(y2-y1)- (x2-x1)

Nhận xét :

Thuật tốn Bresenham chỉ thao tác trên số nguyên và chỉ tính tố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 tốn DDA.

Ý tưởng chính của thuật tố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 tố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 tốn Bresenham cĩ phức tạp hơn thuật tốn DDA.

2.1.4 Thuật tốn trung điểm vẽ đoạn thẳng (MidPoint)

Giải thuật trung điểm được Pitteway đưa ra những năm 1967 và được Vanken áp dụng cho việc sinh các đường thẳng và đường trịn năm 1985 cho ra các cơng thức đơn giản hơn, nhưng tạo ra được các điểm tương tự như với giải thuật Bresenham.

Xét đoạn thẳng cĩ hệ số gĩc thuộc [0,1]. Dx>0

Tại mỗi bước x tăng lên một đơn vị, y giữ nguyên hoặc tăng lên một đơn vị, chọn giá trị y gần với đường thẳng nhất.

Thuật tố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 MidPoint là trung điểm của S và P. Ta cĩ: (adsbygoogle = window.adsbygoogle || []).push({});

+ Nếu điểm Q nằm dưới điểm MidPoint, ta chọn S.

+ Ngược lại nếu điểm Q nằm trên điểm MidPoint ta chọn P.

Hình 2.9

Ta cĩ dạng tổng quát của phương trình đường thẳng: F(x,y)=Ax+By+C=0

A=y2-y1, B=-(x2-x1), C=x2y1-x1y2

F(x,y)=0 với mọi điểm (x,y) thuộc đường thẳng

F(x,y)>0 với các điểm (x,y) nằm phía dưới đường thẳng F(x,y)<0 với các điểm (x,y) nằm phía trên đường thẳng

Lúc này việc chọn các điểm S, P ở trên được đưa về việc xét dấu của pi=2F(M)=2F(xi+1, yi+0.5)= 2A(xi+1)+2B(yi+0.5)+C

+ Nếu pi < 0 điểm M nằm phía trên đoạn thẳng. Lúc này điểm thực Q nằm dưới điểm M nên ta chọn S tức là yi+1=yi

Pi+1=2F(xi+1+1, yi+1+0.5)=2F(xi+2, yi+0.5)= 2A(xi+2)+2B(yi+0.5)+C = pi+2A = pi+2Dy

+ Nếu pi>=0, điểm M nằm phía dưới đoạn thẳng. Lúc này điểm thực Q nằm phía trên điểm M nên ta chọn P tức là yi+1=yi+1

Pi+1=2F(xi+1+1, yi+1+0.5)=2F(xi+2, yi+1.5)= 2A(xi+2)+2B(yi+1.5)+C =pi+2A+2B=pi + 2Dy-2Dx

Ta tính giá trị p1 ứng với điểm ban đầu (x1, y1), với nhận xét rằng (x1, y1) là điểm thuộc về đoạn thẳng, tức là ta cĩ Ax1+By1+C=0.

P1=2F(x1+1, y1+0.5)= 2A(x1+1)+2B(y1+0.5)+C =2(Ax1+By1+C)+ 2A+B =2A+B= 2Dy-Dx

Nhận xét rằng thuật tốn MidPoint cho kết quả tương tự như thuật tốn Breshenham.

Vẽ đa giác

Đa giác là thành phần cơ bản nhất của bề mặt. Việc biểu diễn đa giác cĩ thể thơng qua tập các đường thẳng hay tập các điểm thuộc đa giác.

Đường gấp khúc là tập các đoạn thẳng nối với nhau một cách tuần tự. Các đoạn thẳng này khơng nhất thiết phải tạo thành một hình khép kín và các đoạn cĩ thể cắt lẫn nhau. Điểm giao của hai đoạn thẳng được gọi là đỉnh. Các đường gấp khúc được xác định qua danh sách các đỉnh, mỗi đỉnh được cho bởi các cặp tọa độ (xi, yi)

Hình 2.10

Các đường thẳng bao đa giác - cạnh của đa giác. Các điểm giao của cạnh - đỉnh của đa giác.

Thơng tin cần thiết để xác định đa giác: - Số cạnh

- Toạ độ các đỉnh của đa giác

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;

Đ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ì tồ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

Hình 2.11 : Đa giác lồi và đa giác lõm.

Thuật tốn kiểm tra một đa giác là lồi hay lõm (adsbygoogle = window.adsbygoogle || []).push({});

Thuật tố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 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 < axd + b.

Ví dụ : Cho đường thẳng AB cĩ phương trình y = 0.5x + 1 và hai điểm C, D cĩ tọa độ là C(0,4), D(2,0)

Hình 2.12

Ta cĩ : Yc = 4 > axc + b = 0,5.0 + 1 và Yd = 0 < axd + b = 0,5.2 + 1

Vậy hai điểm C, D nằm về hai phía đối với đường thẳng AB.

Thuật tốn 2 :

Nhận xét :

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

Hình 2.13

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.

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.

Đa giác là thành phần cơ bản của bề mặt

2.2 Thuật tốn vẽ đường trịn2.2.1 Nguyên lý chung 2.2.1 Nguyên lý chung

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

Với tâm C(xc, yc): (x-xc)2+ (y-yc)2=R2 Trong hệ tọa độ cực :

x = xc+ R.cosθ y = yc + R.sinθ với θ ∈ [0, 2π].

Do tính đối xứng của đường trịn C 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.

Với đường trịn tâm (xc, yc) ta cĩ thể vẽ đường trịn tâm (0,0) sau đĩ tịnh tiến theo vecto (xc, yc).

Cho x = 0, 1, 2, ..., int(R x sqrt(2)/2) với R>1. - Tại mỗi giá trị x, tính int(y = sqrt(R2-x2)). - Vẽ điểm (x,y) cùng 7 điểm đối xứng của nĩ.

Cách làm này khơng hiệu quả do gặp phải các phép tốn nhân và lấy căn làm hạn chế tốc độ, ngồi ra đường trịn vẽ ra theo cách này cĩ thể khơng liền nét (trừ trường hợp R lớn) khi x gần R (do chỉ cĩ một giá trị y duy nhất cho một giá trị x). Chúng ta cĩ thể khắc phục điều này bằng cách điều chỉnh đối tượng thay đổi là x (rồi tính y theo x) hay y (rồi tính x theo y) tùy vào giá trị tuyệt đối của hệ số gĩc đường trịn là lớn hơn hay nhỏ hơn 1, nhưng cách làm này địi hỏi thêm các phép tính tốn và kiểm tra nên làm cho thuật tốn phức tạp thêm.

Hình 2.15

Một cách tiếp cận khác là vẽ các điểm (R cos (θ), R sin (θ)), với θ chạy từ 00 đến 900. Cách này sẽ khắc phục hạn chế đường khơng liền nét của thuật tốn trên, tuy nhiên điểm hạn chế chính của thuật tốn này đĩ là chọn bước nhảy cho θ như thế nào cho phù hợp khi bán kính thay đổi.

2.2.2 Thuật tốn trung điểm (MidPoint) vẽ đường trịn

Xét đường trịn tâm tại gốc tọa độ, bán kính R. Xét cung 1/8 thứ hai đường trịn C(1/8), sau đĩ lấy đối xứng

Hình 2.16

Như vậy nếu cĩ (x, y) thuộc (C1/8) thì các điểm : (y, x), (y,-x), (x,-y), (-x,-y), (-y,- x), (-y,x), (-x,y) sẽ thuộc (C).

Chọn điểm bắt đầu để vẽ là điểm (0,R). Dựa vào hình vẽ, nếu (xi, yi) là điểm nguyên đã tìm được ở bước thứ i, thì (xi+1, yi+1) ở bước thứ (i+1) là sự lựa chọn giữa S và P. Như vậy:

xi+1=xi+1 yi+1ϵ{yi, yi-1}

Tương tự như thuật tốn MidPoint vẽ đoạn thẳng, việc quyết định chọn một trong hai điểm S và P sẽ được thực hiện thơng qua việc xét dấu của một hàm nào đĩ tại điểm MidPoint là điểm nằm giữa chúng. (adsbygoogle = window.adsbygoogle || []).push({});

Hình 2.17

Đặt F(x,y)=x2+y2-R2, ta cĩ

F(x,y) <0 nếu (x,y) nằm trong đường trịn F(x,y) =0 nếu (x,y) thuộc đường trịn F(x,y) > 0 nếu (x,y) nằm ngồi đường trịn Gọi M là trung điểm PS

Xét pi=F(M)=F(xi+1, yi-0.5)= (xi+1)2+ (yi-0.5)2-R2 pi+1=F(xi+1+1, yi+1-0.5)= (xi+1+1)2+ (yi+1-0.5)2-R2 Ta cĩ :

+ Nếu pi<0, điểm M nằm trong đường trịn. Lúc này điểm thực Q gần S hơn nên ta chọn S, tức là yi+1=yi

pi+1=F(xi+2, yi-0.5)= (xi+2)2+ (yi-0.5)2-R2 =pi+ 2xi+3

+ Nếu pi>=0, điểm M nằm ngồi đường trịn. Lúc này điểm thực Q gần P hơn nên ta chọn P, tức là yi+1=yi-1

pi+1=F(xi+2, yi-1.5)= (xi+2)2+ (yi-1.5)2-R2 =pi+ 2xi-2yi+5

Tính giá trị p1 ứng với điểm ban đầu (x1, y1) = (0, R) P1=F(1, R-0.5)= 5/4 –R

Cài đặt minh họa thuật tốn MidPoint vẽ đường trịn // Ve 8 diem doi xung

void Put8Pixel(int x, int y) { putpixel(x, y, Color); putpixel(y, x, Color); putpixel(y, -x, Color); putpixel(x, -y, Color); putpixel(-x, -y, Color); putpixel(-y, -x, Color);

putpixel(-y, x, Color);

putpixel(-x, y, Color); } // Put8Pixel

void CircleMidPoint (int R) { int x, y; x = 0; y = R; Put8Pixel(x, y); p = 1 - R; // 5/4-R while (x < y) { if (p < 0) p += 2*x + 3; else { p += 2*(x -y) + 5; y--; } x++; Put8Pixel(x, y); } } // CircleMidPoint

2.3 Thuật tốn vẽ đường elip2.3.1 Nguyên lý chung 2.3.1 Nguyên lý chung

Cho elip tâm (h, k), độ dài trục chính là a, độ dài trục phụ là b Phương trình đường elip được xác định như sau :

(x-h)2/a2+(y-k)2/b2=1.

Phương trình elip với tâm tại gốc tọa độ

x2/b2+y2/b2=1

Elip được chia thành 4 phần đối xứng qua 2 trục tọa độ, do vậy ta chỉ cần vẽ cung ¼ elip sau đĩ thực hiện lấy đối xứng để thu được các phần cịn lại.

Để vẽ elip tâm (h,k) ta cĩ thể thực hiện vẽ elip tâm tại gốc tọa độ sau đĩ tịnh tiến theo véc tơ (h,k).

Tại mỗi bước ta cho x tăng từ 0 đến a sau đĩ tính giá trị y tương ứng qua biểu thức trên, sau đĩ lấy giá trị nguyên gần với giá trị y thực nhất.

Phương pháp này khơng hiệu quả do phải làm nhiều phép tốn lấy bình phương và phép khai căn. Tốc độ thuật tốn chậm.

2.3.2 Thuật tốn trung điểm (MidPoint) vẽ elip

Xét elip tâm tại gốc tọa độ. Phương trình đường elip:

F(x,y)=b2x2+a2y2−a2b2=0

Xét vẽ cung ¼ elip, sau đĩ lấy đối xứng để thu được các phần cịn lại 0<=x<=a

0<=y<=b

Chia cung ¼ elip này thành 2 vùng với điểm chia P là tiếp điểm của tiếp tuyến cĩ hệ số gĩc là -1.

Hình 2.18 (adsbygoogle = window.adsbygoogle || []).push({});

Véc tơ gradient vuơng gĩc với tiếp tuyến tại tiếp điểm được xác định như sau: GradF(x,y) = (∂F/∂x)i+(∂F/∂y)j=2b2x.i+2a2y.j

Ta cĩ tiếp tuyến với cung trịn (độ dốc) = -1

Vector gradient cĩ độ dốc là 1, do đĩ tại P các thành phần i và j của vecto gradient cĩ cùng độ lớn.

Trong mỗi vùng thành phần nào của vecto gradient lớn hơn thì xác định trung điểm theo hướng đĩ. Thành phần nhỏ hơn sẽ biến thiên theo từng đơn vị.

Trong vùng 1 thành phần j lớn hơn thành phần i của gradient. a2(yp-0.5)>b2(xp+1).

Trong vùng 2 thì ngược lại. + Xét trên phần 1:

Bắt đầu từ (0,b),

Tại mỗi bước x tăng lên một đơn vị, y biến đổi theo x

bước thứ i (xi,yi), Ở bước i+1 chọn tiếp A(xi+1, yi) hoặc B(xi+1,yi-1). Chọn điểm gần với đường elip nhất dựa trên việc xét dấu của hàm F tại trung điểm M của AB.

Tham số quyết định:

pi =F(M)= F(xi+1,yi-1/2) = b2(xi+1)2 + a2(yi-1/2)2 -a2b2 pi+1 = F(xi+1+1,yi+1-1/2) = b2(xi+1+1)2 + a2(yi+1-1/2)2 -a2b2 - Nếu pi <0 chọn A

xi+1=xi+1 yi+1=yi

pi+1 = b2(xi+1+1)2 + a2(yi+1-1/2)2 -a2b2 = b2(xi+2)2 + a2(yi-1/2)2 -a2b2 = pi + b2(2xi +3) - Nếu pi >=0 chọn B xi+1=xi+1 yi+1=yi -1 pi+1 = b2(xi+2)2 + a2(yi-1.5)2 -a2b2 = pi + b2(2xi +3) + a2(-2yi +2) - Tính P1 khởi tạo tại (0,b)

p1 = F(1,b-1/2) = b2 + a2(b-1/2)2 -a2b2 p1 = b2 - a2b +a2/4

+ Xét trên phần 2:

Một phần của tài liệu Giao trinh đồ họa máy tính 2012 (Trang 28)