Skip navigation.

不再更新的 Maple

曼妙光阴,一缕繁华

Sutherland-Hodgeman 多边形裁剪

, , , ,

Sutherland—Hodgeman 多边形裁剪的原理即是将多边形看作一个整体,按裁剪窗口的每一条边依次裁剪,因此也可称为连续多边形裁剪。贴在这里的算法参照了电子工业版《计算机图形学》(Donald Hearn 等著)中的相关算法,并在CSDN技术社区诸位朋友的帮助下完成,在此致谢。这段代码可在VC6环境下通过,欢迎各位提出意见或者改进建议。 

include "malloc.h" 
#define N_EDGE 4 
typedef enum {Left,Right,Bottom,Top} Edge;  

struct dcPt  
{ 
int x; 
int y; 
};  

struct wcPt2 
{ 
int x; 
int y; 
};  

int inside(wcPt2 p,Edge b,dcPt wMin,dcPt wMax)//判断点所在位置 
{ 
switch(b) 
{ 
   case Left: if(p.x<wMin.x) return (false);break; 
   case Right: if(p.x>wMax.x) return (false);break; 
   case Bottom: if(p.y<wMin.y) return (false);break; 
   case Top: if(p.y>wMax.y) return (false);break; 
} 
return (true); 
}  

int cross(wcPt2 p1,wcPt2 p2,Edge b,dcPt wMin,dcPt wMax)//判断裁还是不裁 
{ 
if(inside(p1,b,wMin,wMax)==inside(p2,b,wMin,wMax)) 
return (false); 
else return (true); 
}  

wcPt2 intersect(wcPt2 p1,wcPt2 p2,Edge b,dcPt wMin,dcPt wMax)//计算交点 
{ 
wcPt2 iPt; 
float m; 
float dx,dy;  

if(p1.x!=p2.x)  
{ 
    dy=float(p1.y-p2.y); 
    dx=float(p1.x-p2.x); 
    m=dy/dx; 
} 
switch(b) 
{ 
    case Left: 
        iPt.x=wMin.x; 
        iPt.y=int(p2.y+(wMin.x-p2.x)*m); 
        break; 
    case Right: 
        iPt.x=wMax.x; 
        iPt.y=int(p2.y+(wMax.x-p2.x)*m); 
        break; 
    case Bottom: 
        iPt.y=wMin.y; 
        if(p1.x!=p2.x) iPt.x=int(p2.x+(wMin.y-p2.y)/m); 
        else iPt.x=p2.x; 
        break; 
    case Top: 
        iPt.y=wMax.y; 
        if(p1.x!=p2.x) iPt.x=int(p2.x+(wMax.y-p2.y)/m); 
        else iPt.x=p2.x; 
        break; 
    } 
return(iPt); 
}  

void clipPoint(wcPt2 p,Edge b,dcPt wMin,dcPt wMax,wcPt2 *pOut,int *cnt,wcPt2 *first[],wcPt2 *s)//连续裁剪,将结果代入下一裁剪边或最终多边形 
{ 
wcPt2 iPt;  

if(! first) 
   first=&p; 
else 
   if(cross(p,s,b,wMin,wMax)) 
   { 
      iPt=intersect(p,s,b,wMin,wMax); 
      if(b<Top) 
         clipPoint(iPt,Edge(b+1),wMin,wMax,pOut,cnt,first,s); 
      else 
         { 
            pOut[*cnt]=iPt; 
            (*cnt)++; 
         } 
    } 
    s=p;  

    if(inside(p,b,wMin,wMax)) 
       if(b<Top) 
           clipPoint(p,Edge(b+1),wMin,wMax,pOut,cnt,first,s); 
       else 
       { 
           pOut[*cnt]=p; 
           (*cnt)++; 
       } 
}  

void closeClip(dcPt wMin,dcPt wMax,wcPt2 *pOut,int *cnt,wcPt2 *first[],wcPt2 *s)//完成多边形裁剪 
{ 
   wcPt2 i; 
   Edge b;  

   for(b=Left;b<=Top;) 
   { 
      if(cross(s,*first,b,wMin,wMax)) 
      { 
         i=intersect(s,*first,b,wMin,wMax); 
         if(b<Top) 
         { 
             clipPoint(i,Edge(b+1),wMin,wMax,pOut,cnt,first,s); 
         } 
         else 
         { 
             pOut[*cnt]=i; 
             (*cnt)++; 
         } 
       } 
       b=Edge(b+1); 
   } 
}  

int clipPolygon(dcPt wMin,dcPt wMax,int n,wcPt2 *pIn,wcPt2 *pOut) 
{ 
    wcPt2 *first[N_EDGE]={0,0,0,0},s[N_EDGE]; 
    int i,cnt=0;  

    for(i=0;i<n;i++) 
        clipPoint(pIn,Left,wMin,wMax,pOut,&cnt,first,s); 
    closeClip(wMin,wMax,pOut,&cnt,first,s); 
    return (cnt); 
} 

枚举(enumerate)