1. 程式人生 > >計算機圖形學(六)多邊形裁剪Sutherland-Hodgeman演算法講解與原始碼

計算機圖形學(六)多邊形裁剪Sutherland-Hodgeman演算法講解與原始碼

因為最近CSDN上傳資源出現問題,無法上傳,等可以上傳之後再給出下載地址。

原始碼下載:點我下載

首先講一下演算法的原理:

Sutherland-Hodgeman演算法:
基本思想是一次用視窗的一條邊裁剪多邊形。
考慮視窗的一條邊以及延長線構成的裁剪線,該線把平面分成兩個部分:可見一側;不可見一側。
多邊形的各條邊的兩端點S、P。它們與裁剪線的位置關係只有四種,

如圖:

S、P與裁剪線的位置關係 對於情況(1)僅輸出頂點P;情況(2)輸出0個頂點;情況(3)輸出線段SP與裁剪線的交點I;情況(4)輸出線段SP與裁剪線的交點I和終點P 

上述演算法僅用一條裁剪邊對多邊形進行裁剪,得到一個頂點序列,作為下一條裁剪邊處理過程的輸入。
 
對於每一條裁剪邊,只是判斷點在視窗哪一側改變求線段SP與裁剪邊的交點的演算法。

演算法的實現過程還是比較複雜的。

程式碼過程:

1首先畫一個多邊形,然後記錄邊數和邊的2個頂點。

2.執行演算法。

演算法的實現:

  1. typedef struct 

  2. {

  3. int x;

  4. int y;

  5. }Vertex;

  6. typedef  struct   

  7. {   

  8. int   xmin;    

  9. int   xmax;    

  10. int   ymin;    

  11. int   ymax;   

  12. }   

  13. rectangle;

  1. typedef Vertex Edge[2];

  2. typedef Vertex VertexArray[MAX];

  3. VertexArray InVertexArray;

  4. VertexArray OutVertexArray;

  5. Edge ClipBoundary[4];

  6. rectangle rect1;

  7. int InLength;

  8. int OutLength;

  1. void CClipingView::InitClipBoundary(rectangle rect1)

  2. {

  3. //InitRectangle();

  4. ClipBoundary[0][0].y=YT;

  5. ClipBoundary[0][0].x=XL;

  6. ClipBoundary[0][1].y=YT;

  7. ClipBoundary[0][1].x=XR;

  8. ClipBoundary[1][0].x=XR;

  9. ClipBoundary[1][0].y=YT;

  10. ClipBoundary[1][1].x=XR;

  11. ClipBoundary[1][1].y=YB;

  12. ClipBoundary[2][0].x=XR;

  13. ClipBoundary[2][0].y=YB;

  14. ClipBoundary[2][1].x=XL;

  15. ClipBoundary[2][1].y=YB;

  16. ClipBoundary[3][0].x=XL;

  17. ClipBoundary[3][0].y=YB;

  18. ClipBoundary[3][1].x=XL;

  19. ClipBoundary[3][1].y=YT;

  20. }

  1. void CClipingView::SutherlandHodgmanPolygonClip(int InLength, VertexArray InVertexArray, int *OutLength, VertexArray OutVertexArray, Edge ClipBoundary)

  2. {

  3. Vertex  *s,*p,I;   

  4.     int j;   

  5.     *OutLength=0;   

  6.     s=&(InVertexArray[InLength-1]);   

  7.     for(j=0;j<InLength;j++)   

  8.     {   

  9.         p=&(InVertexArray[j]);   

  10.         if(Inside(p,ClipBoundary))   

  11.         {   

  12.             if(Inside(s,ClipBoundary))   

  13.                 Output(p,OutLength,OutVertexArray);   

  14.             else   

  15.             {   

  16.                 Intersect(s,p,ClipBoundary,&I);   

  17.                 Output(&I,OutLength,OutVertexArray);   

  18.                 Output(p,OutLength,OutVertexArray);   

  19.             }   

  20.         }   

  21.         else   

  22.             if(Inside(s,ClipBoundary))   

  23.             {   

  24.                 Intersect(s,p,ClipBoundary,&I);   

  25.                 Output(&I,OutLength,OutVertexArray);   

  26.             }   

  27.         s=p;   

  28.     }  

  29. }

  1. bool CClipingView::Inside(Vertex *textVertex, Edge ClipBoundary)

  2. {

  3. if(ClipBoundary[1].x>ClipBoundary[0].x)//裁剪邊為視窗的下邊   

  4.     {   

  5.         if(textVertex->y>=ClipBoundary[0].y)   

  6.             return TRUE;   

  7.     }   

  8.     else    

  9.         if(ClipBoundary[1].x<ClipBoundary[0].x)//裁剪邊為視窗的上邊   

  10.         {   

  11.             if(textVertex->y<=ClipBoundary[0].y)   

  12.                 return TRUE;   

  13.         }   

  14.         else   

  15.             if(ClipBoundary[1].y>ClipBoundary[0].y)//裁剪邊為視窗的右邊   

  16.             {   

  17.                 if(textVertex->x<=ClipBoundary[0].x)   

  18.                     return TRUE;   

  19.             }   

  20.             else    

  21.                 if(ClipBoundary[1].y<ClipBoundary[0].y)//裁剪邊為視窗的左邊   

  22.                 {   

  23.                         if(textVertex->x>=ClipBoundary[0].x)   

  24.                         return TRUE;   

  25.                 }   

  26.     return FALSE; 

  27. }

  1. void CClipingView::Intersect(Vertex *s, Vertex *p, Edge ClipBoundary, Vertex *I)

  2. {

  3. if(ClipBoundary[0].y==ClipBoundary[1].y)   

  4.     {              

  5.         I->y=ClipBoundary[0].y;         

  6.         I->x=s->x+(ClipBoundary[0].y-s->y)*(p->x-s->x)/(p->y-s->y);       

  7.     }   

  8.     else   

  9.     {      

  10.         I->x=ClipBoundary[0].x;        

  11.         I->y=s->y+(ClipBoundary[0].x-s->x)*(p->y-s->y)/(p->x-s->x);   

  12.     }  

}

  1. void CClipingView::All_SutherlandHodgmanPolygonClip()

  2. {

  3. int i;

  4. InitClipBoundary(rect1);

  5. SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[0]);//裁剪邊為下

  6. InLength=OutLength;

  7. for(i=0;i<=OutLength-1;i++)

  8. {

  9. InVertexArray[i].x=OutVertexArray[i].x;

  10. InVertexArray[i].y=OutVertexArray[i].y;

  11. }

  12. OutLength=0;

  13. SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[1]);//裁剪邊為右

  14. InLength=OutLength;

  15. for(i=0;i<=OutLength-1;i++)

  16. {

  17. InVertexArray[i].x=OutVertexArray[i].x;

  18. InVertexArray[i].y=OutVertexArray[i].y;

  19. }

  20. OutLength=0;

  21. SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[2]);//裁剪邊為上

  22. InLength=OutLength;

  23. for(i=0;i<=OutLength-1;i++)

  24. {

  25. InVertexArray[i].x=OutVertexArray[i].x;

  26. InVertexArray[i].y=OutVertexArray[i].y;

  27. }

  28. OutLength=0;

  29. SutherlandHodgmanPolygonClip(InLength,InVertexArray,&OutLength,OutVertexArray,ClipBoundary[3]);

  30. InitPloygon2();

  31. //Invalidate();

  32. }


其中只給出了一些核心的演算法和資料結構。

想要了解更多可以下載我的原始碼時時的執行或進行DeBug來檢視程式碼的具體情況。

如果有什麼不多的地方還請指出。讓我們一起學習,一起進步。謝謝。