计算机图形学(五)线段的中点分割裁剪算法讲解与源代码

来源:互联网 发布:腾讯软件管理下载 编辑:程序博客网 时间:2024/05/21 21:42

因为CSDN现在上传不上去资源,所以使用了百度云。

源码下载:点我下载

基本思想:

对于每条线段P1P2分为三种情况处理:
 (1) 若P1P2完全在窗口内,则显示该线段P1P2简称“取”之。
 (2) 若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。
 (3) 若线段不满足“取”或“弃”
的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。
为快速判断,采用如下编码方法:每个区域赋予4位编码CtCbCrCl。

定义:



本算法与Cohen-Sutherland算法一样首先对线段端点进行编码,并把线段与窗口的关系分为三种情况:全在、完全不在和线段和窗口有交。
对前两种情况,进行一样的处理。对于第三种情况,用中点分割的方法求出线段与窗口的交点。


描述算法:

求线段与窗口的交点,A、B分别为距P0、P1最近的可见点,Pm为P0、P1中点。

AB之间的连线即为线段P0、P1的可见部分。

从P0出发找最近可见点A的方法先求出P0、 P1的中点Pm ,若P0、Pm不是显然不可见的,并且P0 、P1在窗口中有可见部分,则距P0最近的可见点一定落在 P0 Pm上,所以用P0 Pm代替P0 P1;否则取PmP1代替P0 P1  再对新的P0 P1求中点Pm。
重复上述过程,直到PmP1长度小于给定的控制常数为止,此时Pm收敛于交点。

从P1出发找最近可见点B采用上面类似方法。


下面给出设置编码:

# define MAX 1000# define LEFT 1# define RIGHT 2# define BOTTOM 4# define TOP 8
int XL;int XR;int YB;int YT;
CClipingView::CClipingView(){Draw=false;XL=120;XR=800;YB=400;YT=100;}
int CClipingView::EnCode(CPoint p){int code=0;if(p.x<XL)code|=LEFT; if(p.x>XR)code|=RIGHT;if(p.y<YT)code|=TOP;if(p.y>YB)code|=BOTTOM;return code;}
核心代码:

void CClipingView::OnMove() {CDC *pDC;pDC=GetDC();CString str;CBrush bru;bru.CreateSolidBrush(RGB(255,0,0));CBrush *oldbru=pDC->SelectObject(&bru);CPoint temp,p;bool Y=true;while(1){Y=true;CPen pen1(0,3,RGB(255,255,0));CPen *oldpen=pDC->SelectObject(&pen1);pDC->MoveTo(p1);pDC->LineTo(p2);pDC->SelectObject(oldpen);pDC->SelectObject(&bru);Invalidate();//this->Sleep(700);if(EnCode(p1)==EnCode(p2)&&EnCode(p2)==0){Sleep(700);Invalidate();return;}else if((EnCode(p1)&EnCode(p2))!=0){Yn=false;Sleep(700);Invalidate();return;}else{int i=0;while(1){if(p1.x-p2.x<=1&&p1.x-p2.x>=-1){p2=p;p1=temp;Sleep(700);break;}if(EnCode(p1)==0){ExChange(p1,p2);pDC->TextOut(50,500,"交换P1和P2!        ");pDC->TextOut(p1.x,p1.y+8,"P1");pDC->TextOut(p2.x,p2.y+8,"P2");Sleep(700);}if(Y)temp=p2;p.x=(p1.x+p2.x)/2;p.y=(p1.y+p2.y)/2;pDC->TextOut(50,500,"求出中点坐标P!     ");pDC->TextOut(p.x,p.y+8,"P");pDC->Ellipse(p.x-4,p.y+4,p.x+4,p.y-4);Sleep(700);if((EnCode(p1)&EnCode(p))!=0){CPen pen(0,4,RGB(255,255,255));CPen *oldpen=pDC->SelectObject(&pen);pDC->MoveTo(p1);pDC->LineTo(p);pDC->SelectObject(oldpen);pDC->SelectObject(&bru);Sleep(700);p1=p;pDC->TextOut(50,500,"P1赋值为P!            ");pDC->TextOut(p1.x,p1.y+8,"P1");pDC->Ellipse(p1.x-4,p1.y+4,p1.x+4,p1.y-4);Sleep(700);}else{CPen pen(0,4,RGB(255,255,255));CPen *oldpen=pDC->SelectObject(&pen);pDC->MoveTo(p2);pDC->LineTo(p);pDC->SelectObject(oldpen);pDC->SelectObject(&bru);Sleep(700);p2=p;pDC->TextOut(50,500,"P2赋值为P!            ");pDC->TextOut(p2.x,p2.y+8,"P2");pDC->Ellipse(p2.x-4,p2.y+4,p2.x+4,p2.y-4);Sleep(700);}Y=false;}}}}
void CClipingView::ExChange(CPoint &p1, CPoint &p2){p1.x=p1.x^p2.x;p2.x=p1.x^p2.x;p1.x=p1.x^p2.x;p1.y=p1.y^p2.y;p2.y=p1.y^p2.y;p1.y=p1.y^p2.y;}

代码中我输出了一些算法运算时的过程在界面上。

说一下源码使用的过程:

1.一开始进来就是直线分割,可已选择在正常情况下,也可以选择在网格情况下。如果在网格情况下,请先设置网格大小。

2.可以点击“Draw”来画一个窗口。

3.画一条直线。

4.点击第一个“开”来运非网格下的直线分割。点击第3个开运行网格下的直线分割算法。

如果有什么问题,还望大家多多指教。一起学习,一起进步。


1 0