計算機圖形學(六)多邊形裁剪Sutherland-Hodgeman演算法講解與原始碼
因為最近CSDN上傳資源出現問題,無法上傳,等可以上傳之後再給出下載地址。
原始碼下載:點我下載
首先講一下演算法的原理:
Sutherland-Hodgeman演算法:
基本思想是一次用視窗的一條邊裁剪多邊形。
考慮視窗的一條邊以及延長線構成的裁剪線,該線把平面分成兩個部分:可見一側;不可見一側。
多邊形的各條邊的兩端點S、P。它們與裁剪線的位置關係只有四種,
如圖:
S、P與裁剪線的位置關係 對於情況(1)僅輸出頂點P;情況(2)輸出0個頂點;情況(3)輸出線段SP與裁剪線的交點I;情況(4)輸出線段SP與裁剪線的交點I和終點P
上述演算法僅用一條裁剪邊對多邊形進行裁剪,得到一個頂點序列,作為下一條裁剪邊處理過程的輸入。
對於每一條裁剪邊,只是判斷點在視窗哪一側改變求線段SP與裁剪邊的交點的演算法。
演算法的實現過程還是比較複雜的。
程式碼過程:
1首先畫一個多邊形,然後記錄邊數和邊的2個頂點。
2.執行演算法。
演算法的實現:
-
typedef struct
-
{
-
int x;
-
int y;
-
}Vertex;
-
typedef struct
-
{
-
int xmin;
-
int xmax;
-
int ymin;
-
int ymax;
-
}
-
rectangle;
-
typedef Vertex Edge[2];
-
typedef Vertex VertexArray[MAX];
-
VertexArray InVertexArray;
-
VertexArray OutVertexArray;
-
Edge ClipBoundary[4];
-
rectangle rect1;
-
int InLength;
-
int OutLength;
-
void CClipingView::InitClipBoundary(rectangle rect1)
-
{
-
//InitRectangle();
-
ClipBoundary[0][0].y=YT;
-
ClipBoundary[0][0].x=XL;
-
ClipBoundary[0][1].y=YT;
-
ClipBoundary[0][1].x=XR;
-
ClipBoundary[1][0].x=XR;
-
ClipBoundary[1][0].y=YT;
-
ClipBoundary[1][1].x=XR;
-
ClipBoundary[1][1].y=YB;
-
ClipBoundary[2][0].x=XR;
-
ClipBoundary[2][0].y=YB;
-
ClipBoundary[2][1].x=XL;
-
ClipBoundary[2][1].y=YB;
-
ClipBoundary[3][0].x=XL;
-
ClipBoundary[3][0].y=YB;
-
ClipBoundary[3][1].x=XL;
-
ClipBoundary[3][1].y=YT;
-
}
-
void CClipingView::SutherlandHodgmanPolygonClip(int InLength, VertexArray InVertexArray, int *OutLength, VertexArray OutVertexArray, Edge ClipBoundary)
-
{
-
Vertex *s,*p,I;
-
int j;
-
*OutLength=0;
-
s=&(InVertexArray[InLength-1]);
-
for(j=0;j<InLength;j++)
-
{
-
p=&(InVertexArray[j]);
-
if(Inside(p,ClipBoundary))
-
{
-
if(Inside(s,ClipBoundary))
-
Output(p,OutLength,OutVertexArray);
-
else
-
{
-
Intersect(s,p,ClipBoundary,&I);
-
Output(&I,OutLength,OutVertexArray);
-
Output(p,OutLength,OutVertexArray);
-
}
-
}
-
else
-
if(Inside(s,ClipBoundary))
-
{
-
Intersect(s,p,ClipBoundary,&I);
-
Output(&I,OutLength,OutVertexArray);
-
}
-
s=p;
-
}
-
}
-
bool CClipingView::Inside(Vertex *textVertex, Edge ClipBoundary)
-
{
-
if(ClipBoundary[1].x>ClipBoundary[0].x)//裁剪邊為視窗的下邊
-
{
-
if(textVertex->y>=ClipBoundary[0].y)
-
return TRUE;
-
}
-
else
-
if(ClipBoundary[1].x<ClipBoundary[0].x)//裁剪邊為視窗的上邊
-
{
-
if(textVertex->y<=ClipBoundary[0].y)
-
return TRUE;
-
}
-
else
-
if(ClipBoundary[1].y>ClipBoundary[0].y)//裁剪邊為視窗的右邊
-
{
-
if(textVertex->x<=ClipBoundary[0].x)
-
return TRUE;
-
}
-
else
-
if(ClipBoundary[1].y<ClipBoundary[0].y)//裁剪邊為視窗的左邊
-
{
-
if(textVertex->x>=ClipBoundary[0].x)
-
return TRUE;
-
}
-
return FALSE;
-
}
-
void CClipingView::Intersect(Vertex *s, Vertex *p, Edge ClipBoundary, Vertex *I)
-
{
-
if(ClipBoundary[0].y==ClipBoundary[1].y)
-
{
-
I->y=ClipBoundary[0].y;
-
I->x=s->x+(ClipBoundary[0].y-s->y)*(p->x-s->x)/(p->y-s->y);
-
}
-
else
-
{
-
I->x=ClipBoundary[0].x;
-
I->y=s->y+(ClipBoundary[0].x-s->x)*(p->y-s->y)/(p->x-s->x);
-
}
}
-
void CClipingView::All_SutherlandHodgmanPolygonClip()
-
{
-
int i;
-
InitClipBoundary(rect1);
-
SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[0]);//裁剪邊為下
-
InLength=OutLength;
-
for(i=0;i<=OutLength-1;i++)
-
{
-
InVertexArray[i].x=OutVertexArray[i].x;
-
InVertexArray[i].y=OutVertexArray[i].y;
-
}
-
OutLength=0;
-
SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[1]);//裁剪邊為右
-
InLength=OutLength;
-
for(i=0;i<=OutLength-1;i++)
-
{
-
InVertexArray[i].x=OutVertexArray[i].x;
-
InVertexArray[i].y=OutVertexArray[i].y;
-
}
-
OutLength=0;
-
SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[2]);//裁剪邊為上
-
InLength=OutLength;
-
for(i=0;i<=OutLength-1;i++)
-
{
-
InVertexArray[i].x=OutVertexArray[i].x;
-
InVertexArray[i].y=OutVertexArray[i].y;
-
}
-
OutLength=0;
-
SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[3]);
-
InitPloygon2();
-
//Invalidate();
-
}
其中只給出了一些核心的演算法和資料結構。
想要了解更多可以下載我的原始碼時時的執行或進行DeBug來檢視程式碼的具體情況。
如果有什麼不多的地方還請指出。讓我們一起學習,一起進步。謝謝。