多边形裁剪的Sutherland—Hodgman算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

多边形裁剪的Sutherland—Hodgman算法

1>. Sutherland—Hodgman多边形裁剪算法思想
该算法的基本思想是每次用窗口的一条边界及其延长线来裁剪多边形的各边。多边形通常由它的顶点序列来表示,经过裁剪规则针对某条边界裁剪后,结果形成新的顶点序列,又留待下条边界进行裁剪,…,直到窗口的所有边界都裁剪完毕,算法形成最后的顶点序列,才是结果多边形(它可能构成一个或多个多边形)。
当多边形一个顶点Pi相对于窗口某条边界及其延长线进行剪裁时,不外乎下列四种情况(即裁剪规则):
1、顶点Pi在内侧,前一顶点Pi-1也在内侧,则将Pi纳入新的顶点序列;
2、顶点Pi在内侧,前一顶点Pi-1在外侧,则先求交点Q,再将Q、Pi依次纳入新的顶点序列;
3、顶点Pi在外侧,前一顶点Pi-1在内侧,则先求交点Q,再将Q纳入新的顶点序列;
4、顶点Pi与前一顶点Pi-1均在外侧,则顶点序列中不增加新的顶点。
2>. Sutherland—Hodgman多边形裁剪算法步骤
考虑多边形相对于一条边界及其延长线进行裁剪的算法:
1.从主函数得到待裁剪多边形的顶点序列P[][2]、顶点序列数n、窗口一条边界参数xl(假如为矩形窗口的左边界);
2.赋初值:将顶点序列中的最后一个顶点赋给前一顶点S;
设置初始标志flag:
if(S在边界内侧)flag=0;
else flag=1;
设新的顶点序列数j=0;
3.对多边形各顶点进行裁剪规则处理,结果放入新的多边形顶点序列Q[][2]中:
for(对第一个顶点直到最后一个顶点,逐一处理)
{
if(Pi在边界内侧)
{
if(flag!=0)
{
flag=0;
求交点并放入新的多边形顶点序列Qj中;
j++;
}
将当前顶点放入新的多边形顶点序列Qj中:Qj=Pi;
j++;
}
else
{
if(flag==0)
{
flag=1;
求交点并放入新的多边形顶点序列Qj中;
j++;
}
}
将当前顶点赋给S:S=Pi;
}
4.做返回准备:
将新的多边形顶点序列Q又逐一放回原多边形顶点序列P中:P=Q;
将新的多边形顶点数j放回原多边形顶点数n中:n=j;

//////////////////////////////////////////////////////////////////////////////////////


//-----多边形裁剪的Sutherland—Hodgman算法---------//

/////////////////////////////////////////////////////////////////////////////////////

void CMyClip_AView::ClipedgeL(CPoint polypoint[], CPoint clipwindow[], UINT polynum)

/*其中参数polypoint[]为多边形顶点,clipwindow[]为裁剪窗口顶点,polynum为多边形顶点数目*/


{
//找出裁剪窗口边界
long xl,xr,yt,yb;
UINT i;
xl=clipwindow[0].x;
xr=clipwindow[0].x;
yt=clipwindow[0].y;
yb=clipwindow[0].y;
for(i=1;i<=4;i++)
{
if(xl>clipwindow[i].x)
xl=clipwindow[i].x;

if(xrxr=clipwindow[i].x;
if(yb>clipwindow[i].y)
yb=clipwindow[i].y;
if(ytyt=clipwindow[i].y;
}
//
CPoint B[Polygon_Num],C[Polygon_Num];
UINT m_nA,m_nB;
int x,y;
long tem1,tem2;
m_nA=polynum;/*记载原始多边形顶点顶点个数*/
m_nB=0;/*记载新生成多边形顶点顶点个数*/
for(i=0;i{
if(polypoint[i].x{
continue;/*如果是这种情况,那么就对继续对下一条多边形边作判断,也就是说下面的判断不用做了*/
}

if(polypoint[i].x>=xl && polypoint[i+1].x>=xl) /*边两个端点都在内部,保留*/
/*因为每个保留的点在数组中只出现一次,且下一次判断时第二个端点一定会要取到,因此只保留的两个点中的第一个*/
{


B[m_nB].x =polypoint[i].x ;
B[m_nB].y =polypoint[i].y ;
m_nB=m_nB+1;
continue;
}
if(polypoint[i].x=xl)/*边两个端点起点在外部,终点在内部,求交点,然后交点,终点都应该送入临时数组*/
{
/*保留交点*/
x=xl;
tem1=(xl-polypoint[i].x);
//tem2=(xl-x1)*dy/dx+y1;
//y/x=dy/dx---->y=x*dy/dx
tem2=tem1*(polypoint[i+1].y-polypoint[i].y)/(polypoint[i+1].x-polypoint[i].x)+polypoint[i].y;
y=tem2;
B[m_nB].x =x;
B[m_nB].y =y;
m_nB=m_nB+1;
continue;
}
if(polypoint[i].x>=xl && polypoint[i+1].x{ /*保留内部点*/
B[m_nB].x =polypoint[i].x ;
B[m_nB].y =polypoint[i].y ;
m_nB=m_nB+1;
/*保留交点*/
x=xl;
tem1=(xl-polypoint[i].x);
tem2=tem1*(polypoint[i+1].y-polypoint[i].y)/(polypoint[i+1].x-polypoint[i].x)+polypoint[i].y;
y=tem2;
B[m_nB].x =x;
B[m_nB].y =y;
m_nB=m_nB+1;
continue;
}
}
//把第一个点的数据拷贝到最后
//形成裁剪后的多边形
if(i==m_nA)
{
B[m_nB]=B[0];
}

//下------------------
m_nA=0;
for(i=0;i{
if(B[i].y//两个点全在下方
{
continue;//下一条边

}

if(B[i].y>=yb && B[i+1].y>=yb)
//p1,p2都在yb上方
{
C[m_nA].x =B[i].x;
C[m_nA].y =B[i].y;
m_nA++;
continue;
}

if(B[i].y=yb)
//p1在下,P2在上,留交点,外->内
{
y=yb;
tem1=yb-B[i].y;
//tem2=x1+(yb-y1)*dx/dy
tem2=tem1*(B[i+1].x-B[i].x)/(B[i+1].y-B[i].y) + B[i].x;
x=tem2;
C[m_nA].x =x;
C[m_nA].y =y;
m_nA++;
continue;
}

if(B[i].y>=yb && B[i+1].y//p1在上方,P2在下方,留P1和交点,内-外
{
//save p1
C[m_nA].x=B[i].x;
C[m_nA].y=B[i].y;
m_nA++;
//留交点
y=yb;
tem1=yb-B[i].y;
//tem2=x1+(yb-y1)*dx/dy
tem2=tem1*(B[i+1].x-B[i].x)/(B[i+1].y-B[i].y)+B[i].x;
x=tem2;
C[m_nA].x =x;
C[m_nA].y =y;
m_nA++;
continue;
}
}
//形成第二次裁剪多边形
if(i==m_nB)
{
C[m_nA]=C[0];
}
//右------------------
m_nB=0;
for(i=0;i{
if(C[i].x>xr && C[i+1].x>xr)
//P1,P2都在右方--go next
{
continue;
}
if(C[i].x<=xr && C[i+1].x<=xr)
//P1,P2都在左方,留P1
{
B[m_nB].x =C[i].x;
B[m_nB].y =C[i].y;
m_nB++;
continue;
}
if(C[i].x>xr && C[i+1].x<=xr)
//P1在右方,P2在左方,留交点
{
x=xr;
tem1=C[i].x-xr;
tem2=C[i].y-tem1*(C[i+1].y-C[i].y)/(C[i+1].x-C[i].x);
y=tem2;
B[m_nB].x =x;
B[m_nB].y =y;
m_nB++;
continue;
}
if(C[i].x<=xr && C[i+1].x>xr)
//P1在内,P2在外,留P1和交点
{
//save p1
B[m_nB].x =C[i].x;
B[m_nB].y =C[i].y;
m_nB++;
//save 交点
x=xr;
tem1=C[i].x-xr;
tem2=C[i].y-tem1*(C[i+1].y-C[i].y)/(C[i+1].x-C[i].x);
y=tem2;
B[m_nB].x =x;
B[m_nB].y =y;
m_nB++;
continue;
}
}
//三次裁剪后的新多边形
if(i==m_nA)
{
B[m_nB]=B[0];
}


//上-------------------
m_

nA=0;
for(i=0;i{
if(B[i].y>yt && B[i+1].y>yt)
//p1,p2都在上方,next
{
continue;
}
if(B[i].y<=yt && B[i+1].y<=yt)
//p1,p2都在下方,留P1
{
C[m_nA].x =B[i].x;
C[m_nA].y =B[i].y;
m_nA++;
continue;
}
if(B[i].y>yt && B[i+1].y<=yt)
//P1在上方,P2在下方外->内,留交点
{
y=yt;
tem1=B[i].y-yt;
//tem2=x1+(yb-y1)*dx/dy
tem2=B[i].x-tem1*(B[i+1].x-B[i].x)/(B[i+1].y-B[i].y);
x=tem2;
C[m_nA].x =x;
C[m_nA].y =y;
m_nA++;
continue;
}
if(B[i].y<=yt && B[i+1].y>yt)
//P1在下方,P2在上方,内->外,留P1和交点
{
//save p1,,,
C[m_nA].x =B[i].x;
C[m_nA].y =B[i].y;
m_nA++;
//save 交点
y=yt;
tem1=B[i].y-yt;
//tem2=x1+(yb-y1)*dx/dy
tem2=B[i].x-tem1*(B[i+1].x-B[i].x)/(B[i+1].y-B[i].y);
x=tem2;
C[m_nA].x =x;
C[m_nA].y =y;
m_nA++;
continue;
}
}
//形成裁剪后的多边形
if(i==m_nB)
{
C[m_nA]=C[0];
}
CClientDC dc(this);
CPen tempen;
tempen.CreatePen(PS_SOLID,1,RGB(255,0,0));
dc.SelectObject(tempen);

dc.MoveTo(C[0]);
for(i=1;i<=m_nA;i++)
{
dc.LineTo(C[i]);
}
}//.....

本篇文章来源于 3SDN 转载请以链接形式注明出处 网址:/programing/algorithm/2008-11-24/92_4.html

相关文档
最新文档