Giải thuật cắt đa giác gồm 2 bước chính:
Giả sử ta có v1, v2,.., vn là các đỉnh của 1 đa giác bất kì. Quá trình clipping được thực hiện trên các cạnh của đa giác tạo bởi 2 đỉnh liên tiếp vi và vi+1. Quá trình được thực hiện tuần tự từ vn ->v1->vn và lặp lại với 4 cạnh của cửa sổ clipping.
Với 1 cạnh bất kì của cửa sổ, 4 trường hợp khi ta xét đến một cạnh của đa giác được tiến hành như sau:
Giả sử S=vi, P=vi+1
Trường hợp 1: Khi S, P nằm trong cửa sổ ta lưu lại P
Trường hợp 2: Khi s ở trong, P ở ngoài ta lưu lại I là giao điểm của SP và cạnh cửa sổ. Trường hợp 3: Khi s, p ngoài ta không lưu lại cả 2 điểm.
Trường hợp 4: Khi S ngoài, P trong thì ta lưu lại cả P và giao điểm J của chúng.
Cài đặt minh họa thuật toán Sutherland-Hodgeman
#include<graphics.h> P P S a) Lưu P P S b) Lưu I I S c)Không lưu gì P S d) Lưu I, P I
#include<mem.h> #include<conio.h> #include<stdio.h> #include<stdlib.h> #define TRUE 1 #define FALSE 0 #define LEFT 1 #define RIGHT 2 #define TOP 4 #define BOTTOM 8 typedefstruct{ int x, y; }POINT; typedefstruct{
int Left, Top, Right, Bottom; }RECT;
// Xac dinh p co nam ben trong cua so neu xet theo mot canh b
intInside(POINT p,int Edge, RECT rWin) { switch(Edge) { case LEFT : if(p.x < rWin.Left) return FALSE;
break; case RIGHT : if(p.x > rWin.Right) return FALSE; break; case TOP :
if(p.y > rWin.Top) return FALSE; break;
case BOTTOM :
if(p.y < rWin.Bottom) return FALSE; break;
}
return TRUE; } //Inside
// Tra ve giao diem cua doan noi p1&p2 voi canh b
POINT Intersect(POINT p1, POINT p2,int Edge, RECT rWin) {
POINT iPt; float m;
if(p1.x != p2.x)
m =float(p2.y-p1.y)/(p2.x-p1.x); switch(Edge)
{
case LEFT :
iPt.x = rWin.Left;
iPt.y = p2.y +(rWin.Left-p2.x)*m; break;
case RIGHT :
iPt.x = rWin.Right;
iPt.y = p2.y +(rWin.Right-p2.x)*m; break;
case TOP :
iPt.y = rWin.Top; if(p1.x != p2.x)
iPt.x = p2.x +(rWin.Top-p2.y)/m; else iPt.x = p2.x; break; case BOTTOM : iPt.y = rWin.Bottom; if(p1.x != p2.x)
iPt.x = p2.x +(rWin.Bottom-p2.y)/m; else
iPt.x = p2.x; break; }
return(iPt); } // Intersect
// Tien hanh cat da giac voi mot canh nao do cua cua so.
voidClipEdge(POINT *pIn,int N, POINT *pOut,int&Cnt,int Edge,
RECT rWin) {
int FlagPrevPt = FALSE;
Cnt = 0;
POINT pPrev;
pPrev = pIn[0];
if(Inside(pPrev, Edge, rWin))// Save point
{ pOut[Cnt]= pPrev; Cnt++; FlagPrevPt = TRUE; } for(int i=1; i<N; i++) {
if(FlagPrevPt)// Diem bat dau nam trong
{
if(Inside(pIn[i], Edge, rWin))// Save point P
{
pOut[Cnt]= pIn[i];
}
else// Save I
{
FlagPrevPt = FALSE;
pOut[Cnt]= Intersect(pPrev, pIn[i], Edge, rWin);
Cnt++; } }
else // Diem bat dau canh nam ngoai
{
if(Inside(pIn[i], Edge, rWin))// Save point I, P
{
FlagPrevPt = TRUE;
pOut[Cnt]= Intersect(pPrev, pIn[i], Edge, rWin);
Cnt++; pOut[Cnt]= pIn[i]; Cnt++; } } pPrev = pIn[i]; }
// Neu Diem cuoi va dau giao voi bien cua cua so Save point I
if(!(Inside(pIn[N], Edge, rWin)== Inside(pPrev, Edge, rWin))) {
pOut[Cnt]= Intersect(pPrev, pIn[N], Edge, rWin);
Cnt++; }
pOut[Cnt]= pOut[0]; } // Intersect
voidClipPolygon(POINT *pIn,int N, POINT *pOut,int&Cnt,
RECT rWin) {
POINT pTmp[20];
_fmemcpy(pTmp, pIn,(N+1)*sizeof(POINT));
ClipEdge(pTmp, N, pOut, Cnt, LEFT, rWin);
N = Cnt;
_fmemcpy(pTmp, pOut,(N+1)*sizeof(POINT));
ClipEdge(pTmp, N, pOut, Cnt, RIGHT, rWin);
N = Cnt;
_fmemcpy(pTmp, pOut,(N+1)*sizeof(POINT));
ClipEdge(pTmp, N, pOut, Cnt, TOP, rWin);
N = Cnt;
_fmemcpy(pTmp, pOut,(N+1)*sizeof(POINT));
ClipEdge(pTmp, N, pOut, Cnt, BOTTOM, rWin); } // ClipPolygon
Nhận xét
Thuật toán Sutherland-Hodgeman cho kết quả rất chính xác khi làm việc với các đa giác lồi, tuy nhiên với các đa giác lõm kết quả hiển thị có thể sẽ có đoạn thừa. Điều này xảy ra khi đa giác sau khi xén bị tách thành hai hay nhiều vùng. Do chúng ta chỉ lưu kết quả xuất trong một danh sách các đỉnh nên đỉnh cuối của danh sách ứng với đa giác
trước sẽ nối với đỉnh đầu của danh sách ứng với đa giác sau. Một trong nhiều cách để khắc phục điểm này là phân đa giác lõm thành hai hay nhiều đa giác lồi và xử lí mỗi đa giác lồi riêng.
Câu hỏi cuối chương
1. Ý nghĩa của mã vùng trong thuật toán Cohen-Sutherland.
2. Hãy cho một đoạn thẳng minh họa mà trong trường hợp này thuật toán phải thực hiện việc tìm giao điểm 4 lần theo thứ tự LEFT, TOP, RIGHT, BOTTOM.
3. Cài đặt thuật toán Cohen-Sutherland để xén một đa giác. Phân tích các trường hợp thuật toán này cho kết quả là các đoạn thẳng rời rạc.
4. So sánh hai thuật toán Cohen-Sutherland và Liang-Barsky về số phép toán thực hiện trong các trường hợp chính.
CHƯƠNG V. GIỚI THIỆU ĐỒ HOẠ BA CHIỀU
Trong thực tế có hai cách nhìn về sự chuyển động của đối tượng + Đối tượng chuyển động còn hệ toạđộđứng yên
+ Đối tượng đứng yên còn hệ toạđộ nhìn chuyển động
Trong trường hợp 1: Sử dụng phép chuyển đổi đối tượng còn trong trường hợp 2 thì sử dụng phép chuyển đổi toạđộ
Hệ toạđộ 3 chiều được quy ước
Trục của phép quay Hướng dương của phép quay
x y tới z
y z tới x
z x tới y
Thông thường người ta sử dụng hệ toạ độ tay phải, chiều dương là chiều ngược chiều kim đồng hồ nhưng toạđộ này không thích hợp cho đồ hoạ ba chiều do đó người dùng thêm vào hệ toạ độ tay trái . Trong hệ toạđộ này chiều dương là chiều thuận chiều kim đồng hồ.