逐边裁剪法实现多边形裁剪

已经处理退化边的多边形裁剪算法

//编译环境:Visual C++ 6.0,EasyX_20190219(beta)
#include<graphics.h>
#include<conio.h>
#include<iostream>
#define max 30
using namespace std;

//设置裁剪框的大小和位置,裁剪多边形顶点和顶点数,以全局变量给出
double xl=5,xr=140,yt=190,yb=74;
int inlength=9;
POINT Vertex[]={ {110,84},{160,94},{90,169},{90,94},{70,90},{50,230}, {165,230},{175,89},{163,54} };
//求多边形的一条边sp和裁剪边point0 point1的交点
void Intersect(POINT S,POINT P,POINT point0,POINT point1,POINT &I)
{
	if(point0.y==point1.y)//水平裁剪边
	{
		I.y=point0.y;
		I.x=S.x+(point0.y-S.y)*(P.x-S.x)/(P.y-S.y);
	}
	else//竖直裁剪边
	{
		I.x=point0.x;
		I.y=S.y+(point0.x-S.x)*(P.y-S.y)/(P.x-S.x);
	}
}

//测试顶点与裁剪边的内外关系
bool Inside(POINT text,POINT point0,POINT point1)
{
	if(point1.x>point0.x){//裁剪边为窗口的下边
		if(text.y>=point0.y)
			return true;}

	else if(point1.x<point0.x){//裁剪边为窗口的上边
        if(text.y<=point0.y)
			return true;}

	else if(point1.y>point0.y){//裁剪边为窗口的右边
		if(text.x<=point0.x)
			return true;}

	else if(point1.y<point0.y){//裁剪边为窗口的左边
		if(text.x>=point0.x)
			return true;}

	return false;
}

//将新的定点加入结果多边形顶点表
void Output(POINT newpoint,int &length,POINT outps[])
{
	outps[length].x=newpoint.x;
	outps[length].y=newpoint.y;
	length++;
}

//裁剪算法
void SutherlandHodgmanPolygonClip(int inlength,POINT inpoints[],int &outlength,POINT outpoints[],POINT point0,POINT point1)
{
	POINT S,P,I;
	int j;
	outlength=0;
	S=inpoints[inlength-1];
	for(j=0;j<inlength;j++)
	{
		P=inpoints[j];
		if(Inside(P,point0,point1))
		{ 
			if(Inside(S,point0,point1))
			{Output(P,outlength,outpoints);}
			else
			{
				Intersect(S,P,point0,point1,I);
				Output(I,outlength,outpoints);
				Output(P,outlength,outpoints);}}
		else if(Inside(S,point0,point1))
		{
			Intersect(S,P,point0,point1,I);
			Output(I,outlength,outpoints);}
		S=P;}
}

int main()
{
	POINT Edge[]={ {xr,yb},{xr,yt},{xl,yt},{xl,yb} };
	initgraph(1000,900);
	polygon(Edge,4);
	setcolor(RED);
	polygon(Vertex,inlength);
    int i;
	POINT OutPts1[max],OutPts2[max],OutPts3[max],OutPts4[max];
	int length1,length2,length3,length4;
    SutherlandHodgmanPolygonClip(inlength,Vertex,length1,OutPts1,Edge[0],Edge[1]);//右边窗口裁剪边
	SutherlandHodgmanPolygonClip(length1,OutPts1,length2,OutPts2,Edge[1],Edge[2]);//下边窗口裁剪边
	SutherlandHodgmanPolygonClip(length2,OutPts2,length3,OutPts3,Edge[2],Edge[3]);//左边窗口裁剪边
	SutherlandHodgmanPolygonClip(length3,OutPts3,length4,OutPts4,Edge[3],Edge[0]);//上边窗口裁剪边
	MOUSEMSG m;
	while(true)
	{		  
		  m=GetMouseMsg();
		  switch(m.uMsg)
		  {
		    case WM_LBUTTONDOWN:
				cleardevice();
				setcolor(RED);
				polygon(Edge,4);
				setcolor(YELLOW);
				polygon(OutPts4,length4);
				for(i=0;i<length4;i++)
				{OutPts4[i].x+=300;}
				polygon(OutPts4,length4);
				break;
			case WM_RBUTTONDOWN:
				return 0;
		  }
	}
	_getch();
	closegraph();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
以上是按照右下左上的顺序进行裁剪的,当然读者可以按照自己的习惯进行调整。

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
MFC中提供了多边形裁剪的相关函数,可以使用以下代码实现: ```c++ void ClipPolygon(CDC* pDC, CPoint* pts, int nCount, CRect rectClip) { // 定义裁剪区域的左、右、上、下边界 int nLeft = rectClip.left; int nRight = rectClip.right; int nTop = rectClip.top; int nBottom = rectClip.bottom; // 定义裁剪区域的四个顶点 CPoint ptsClip[4]; ptsClip[0] = CPoint(nLeft, nTop); ptsClip[1] = CPoint(nRight, nTop); ptsClip[2] = CPoint(nRight, nBottom); ptsClip[3] = CPoint(nLeft, nBottom); // 定义裁剪后的顶点序列 CPoint ptsResult[50]; int nResultCount = 0; // 对每条裁剪边进行裁剪 for (int i = 0; i < 4; i++) { CPoint ptStart = pts[nCount - 1]; for (int j = 0; j < nCount; j++) { CPoint ptEnd = pts[j]; // 判断线段与裁剪边之间的位置关系 bool bStartIn = PtInPolygon(ptStart, ptsClip, 4); bool bEndIn = PtInPolygon(ptEnd, ptsClip, 4); if (bStartIn && bEndIn) // 线段在裁剪区域内,直接添加到结果序列中 { ptsResult[nResultCount++] = ptEnd; } else if (bStartIn && !bEndIn) // 线段从裁剪区域内部到外部,计算交点并添加到结果序列中 { CPoint ptIntersect = GetIntersection(ptStart, ptEnd, ptsClip[i], ptsClip[(i + 1) % 4]); ptsResult[nResultCount++] = ptIntersect; } else if (!bStartIn && bEndIn) // 线段从裁剪区域外部到内部,计算交点并添加到结果序列中 { CPoint ptIntersect = GetIntersection(ptStart, ptEnd, ptsClip[i], ptsClip[(i + 1) % 4]); ptsResult[nResultCount++] = ptIntersect; ptsResult[nResultCount++] = ptEnd; } else // 线段在裁剪区域外部,不做处理 { } // 更新起点 ptStart = ptEnd; } // 将当前裁剪边的结果序列作为下一条裁剪边的输入序列 nCount = nResultCount; memcpy(pts, ptsResult, sizeof(CPoint) * nResultCount); nResultCount = 0; } // 绘制裁剪后的多边形 if (nCount > 0) { pDC->MoveTo(pts[0]); for (int i = 1; i < nCount; i++) { pDC->LineTo(pts[i]); } pDC->LineTo(pts[0]); } } // 判断点是否在多边形内 bool PtInPolygon(CPoint pt, CPoint* pts, int nCount) { int nCross = 0; for (int i = 0; i < nCount; i++) { CPoint pt1 = pts[i]; CPoint pt2 = pts[(i + 1) % nCount]; if (((pt1.y <= pt.y) && (pt2.y > pt.y)) || ((pt1.y > pt.y) && (pt2.y <= pt.y))) { double d = (double)(pt.y - pt1.y) / (double)(pt2.y - pt1.y); if (pt.x < pt1.x + d * (pt2.x - pt1.x)) { nCross++; } } } return (nCross % 2 == 1); } // 计算线段与裁剪边的交点 CPoint GetIntersection(CPoint pt1, CPoint pt2, CPoint pt3, CPoint pt4) { double d1 = (double)(pt1.y - pt3.y) * (double)(pt4.x - pt3.x) - (double)(pt1.x - pt3.x) * (double)(pt4.y - pt3.y); double d2 = (double)(pt2.y - pt1.y) * (double)(pt4.x - pt3.x) - (double)(pt2.x - pt1.x) * (double)(pt4.y - pt3.y); double d = d1 / d2; CPoint pt; pt.x = (int)(pt1.x + d * (pt2.x - pt1.x)); pt.y = (int)(pt1.y + d * (pt2.y - pt1.y)); return pt; } ``` 该函数接受五个参数:绘图设备上下文(CDC*)、多边形顶点序列(CPoint*)、多边形顶点数(int)、裁剪区域(CRect)。在函数中,首先定义裁剪区域的边界和四个顶点,然后对每条裁剪边进行裁剪,最终得到裁剪后的多边形顶点序列,并绘制出来。裁剪过程中,使用了判断点是否在多边形内、计算线段与裁剪边的交点等函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值