计算机图形学_实验报告三_图形裁剪算法
计算机图形学裁剪

学院:理学院专业:信息与计算科学班级:
姓名
学号
指导教师
实验时间
4.
实验地点
计算机实验室
成绩
实验项目名称
裁剪
实验环境
VC++ 6.0
实验内容
(1)理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
(2)利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
};
Rectangle rect;
int x0,y0,x1,y1;
int CompCode(int x,int y,Rectangle rect)
{
int code=0x00;
if(y<rect.ymin)
code=code|4;
if(y>rect.ymax)
code=code|8;
if(x>rect.xmax)
x0=450,y0=0,x1=0,y1=450;
printf("Press key'c'to Clip!\nPress key'r'to Rrstore!\n");
}
void Reshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
accept=0;
done=0;
int code0,code1,codeout;
code0=CompCode(x0,y0,rect);
code1=CompCode(x1,y1,rect);
图形学实验报告直线段的裁剪算法

实验报告Experimentation Report of Taiyuan teachers College系部计算机系年级三年级课程图形学姓名同组者日期项目直线段的裁剪算法一、实验目的:1.熟悉图形裁剪的基本知识2.掌握Cohen-Sutherland 直线裁剪算法二、实验内容:在矩形窗口的裁剪算法中,考虑到构成图形的基本元素就是线段,曲线可看成是有很多小线段逼近而成的,因此,讨论线段的裁剪算法更为实用,即Cohen-Sutherland裁剪算法。
Cohen-Sutherland裁剪算法具体思路如下。
任意平面线段和矩形窗口的位置关系只会有如下3种:(1)完全落在窗口内。
(2)完全落在窗口外。
(3)部分落在窗口内,部分落在窗口外。
要想判断线段和窗口的位置关系,只要找到线段的两端点相对于矩形窗口的位置即可,线段的两端点相对于矩形窗口的位置可能会有如下几种情况:(1)线段的两个端点均在窗口内,这时线段全部落在窗口内,完全可见,应予以保留。
(2)线段的两个端点均在窗口边界线外同侧,这时线段全部落在窗口外,完全不可见,应予以舍弃。
(3)线段的一个端点在窗口内,另一个端点在窗口外,这时线段部分可见,应求出线段与窗口边界线的交点,从而得到线段在窗口内的可见部分。
(4)线段的两个端点均不在窗口内,但不处于窗口边界线外同侧,这时有可能线段是部分可见的,也可能是完全不可见的。
Cohen-Sutherland裁剪算法就是按照上述思路来对线段进行裁剪的,只是在线段的两端点相对于矩形窗口的位置上,巧妙地运用了编码的思想。
首先,延长窗口的四条边界线,将平面划分成9个区域,然后,用四位二进制数C3C2C1C0对这9个区域进行编码,编码规则如下:第0位C0:当线段的端点在窗口的左边界之左时,该位编码为1,否则,该位编码为0。
第1位C1:当线段的端点在窗口的右边界之右时,该位编码为1,否则,该位编码为0。
第2位C2:当线段的端点在窗口的下边界之下时,该位编码为1,否则,该位编码为0。
图形裁剪

PrivateSubButton5_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesButton5.Click
g = PictureBox1.CreateGraphics
CallDBX(p)
EndSub
FunctionDBX(ByValpcolorAsObject)AsInteger
FunctionZF(ByValZFCAsString)AsString
DimdrawstringAs[String] = ZFC
DimdrawfontAsNewFont("Arial", 20)
DimdrawbrushAsNewSolidBrush(Color.Blue)
Dimdrawpoint1AsNewPointF(150.0F, 150.0F)
四、实验过程及步骤:
(包括程序界面设计、控件属性说明、程序代码和程序运行四部分)
PublicClassForm1
InheritsWindows.Forms.Form
PrivategAsGraphics
PrivatepAsPen =NewPen(Color.Red, 3)
PrivatesAsPen =NewPen(Color.Blue, 2)
Dimpoint7AsNewPoint(100, 15)
DimcurvepointsAsPoint() = {point1, point2, point3, point4, point5, point6, point7}
g.DrawPolygon(Pens.Blue, curvepoints)
EndFunction
4上机实验报告3:图形裁剪算法的具体实现

计算机图形学课程实验报告信息与计算科学(三)上机实验3:裁剪算法班级:姓名:学号:上机实验(3)的题目和要求一、实验目的掌握图形裁剪算法的基本思想,并能上机编程实现相应的算法。
二、实验要求(Direction)1.每个学生单独完成。
2.开发语言规定为C语言。
3.请在自己的实验报告上写明姓名、学号、班级。
4.每次交的实验报告内容包括:试验目的和意义、题目、程序制作步骤、主程序(包括源代码注释)。
三、实验题目实验题1:上机编一程序实现直线的中点裁剪算法。
具体要求如下说明:1 该程序能实现窗口屏幕上任意一条直线的裁剪;2 直线段要求可以随机输入;运行结果图:裁剪之前裁剪之后#define LE 2#define RI 4#define BO 6#define TO 10#define XLEFT 150#define XRIGHT 350#define YBOTTOM 150#define YTOP 300#include "math.h"#include "stdio.h"#include "graphics.h"void main(){int x1,y1,x2,y2,xx,yy,xxx,yyy;int graphdriver=DETECT,graphmode;initgraph(&graphdriver,&graphmode," ");setcolor(6);line(XLEFT,YTOP,XRIGHT,YTOP);line(XLEFT,YBOTTOM,XRIGHT,YBOTTOM);line(XLEFT,YTOP,XLEFT,YBOTTOM);line(XRIGHT,YTOP,XRIGHT,YBOTTOM);x1=50;y1=200;x2=400;y2=300;setcolor(1);line(x1,y1,x2,y2);xx=0;yy=0;xxx=0;yyy=0;draw_ett(x1,y1,x2,y2,&xx,&yy);draw_ett(x2,y2,xx,yy,&xxx,&yyy);setcolor(4);line(xx,yy,xxx,yyy);getch();closegraph();}int encode (int x, int y, int *code){ int c=0;if (x<XLEFT) c=c|LE;else if (x>XRIGHT) c=c|RI;if (y<YBOTTOM) c=c|BO;else if (y>YTOP) c=c|TO;*code=c;return code;}draw_ett(int x1, int y1, int x2, int y2, int *x, int *y) { int code1,code2,code;int xx,yy;float d,d1,d2;encode(x1,y1,&code1);encode(x2,y2,&code2);if (code2==0) { xx=x2;yy=y2; *x=xx; * y=yy;return;}if ((code1&code2)!=0) return;L1: xx=(x1+x2)/2;yy=(y1+y2)/2;encode(xx, yy, &code);d1=(yy-y1)*(yy-y1);d2=(xx-x1)*(xx-x1);d=sqrt(d1+d2);if (d<=1) { *x=xx;*y=yy; return;}if ((code&code1)!=0){ x1=xx; y1=yy; }else { x2=xx; y2=yy;}goto L1;}实验题2:实现Sutherland-Hodgeman多边形裁剪算法。
计算机图形学裁剪III剖析

则有 tQ iD iiL ,R ,B ,T
20计09算-2机01图0-形2:学CG裁:S剪CIIUI剖EC析
3
梁友栋-Barsky算法
由 tQ iD iiL ,R ,B ,T
Di Qi
(Qi
0)
t
Dj Qj
(Qj
0)
Di Qi
(Qi
0)
t
Dj Qj
(Qj
0)
0 t 1
i, j {L, R}i j i, j {B,T}i j
else if(d < 0) return false;
drawline(P0+(P1-P0)t0, P0+(P1-P0)t1);
return true;
}
} 梁-Barsky算法演示例
子
20计09算-2机01图0-形2:学CG裁:S剪CIIUI剖EC析
7
Cyrus-Beck裁剪算法(参数化裁剪算法)
A1 P2
A2
A3
t N(P1 A) N(P2 P1)
(x1 XL) ( x2 x1 )
(x1 XR) x2 x1 ( y1 YB)
( y2 y1 )
( y1 YT) y2 y1
14
多边形裁剪-凸多边形的二维裁剪
多边形是由一组线段围成的封闭区域,线段裁剪是多边形 裁剪的基础。下图(b)是多边形的线段被裁剪后的结果,但 已不再是封闭的区域。正确的剪裁结果应是一个有边界的区 域,即裁剪后的结果仍是一个(或多个)多边形 ,这就要求 在裁剪过程中应当保留多边形的区域性质。
Sutherland-Hodgman 算法
❖ 算法的输入是以顶点序列表示的多边形,输出也是一个顶 点序列,构成一个或多个多边形。
计算机图形学实验三

太原工业学院实验报告GetClientRect(&rect);//获得客户区的大小pDC->SetMapMode(MM_ANISOTROPIC);//pDC自定义坐标系pDC->SetWindowExt(rect.Width(),rect.Height());//设置窗口范围pDC->SetViewportExt(rect.Width(),-rect.Height());//设置视区范围,x轴水平向右,y轴垂直向上pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//客户区中心为原点CDC memDC;//内存DCCBitmap NewBitmap,*pOldBitmap;//内存中承载的临时位图memDC.CreateCompatibleDC(pDC);//创建一个与显示pDC兼容的内存memDCNewBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//创建兼容位图pOldBitmap=memDC.SelectObject(&NewBitmap);//将兼容位图选入memDCmemDC.FillSolidRect(rect,pDC->GetBkColor());//按原来背景填充客户区,否则是黑色memDC.SetMapMode(MM_ANISOTROPIC);//memDC自定义坐标系memDC.SetWindowExt(rect.Width(),rect.Height());memDC.SetViewportExt(rect.Width(),-rect.Height());memDC.SetViewportOrg(rect.Width()/2,rect.Height()/2);rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);DrawWindowRect(&memDC);//绘制窗口if(PtCount>=1){memDC.MoveTo(Round(P[0].x),Round(P[0].y));memDC.LineTo(Round(P[1].x),Round(P[1].y));}pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&memDC,-rect.Width()/2,-rect.Height()/2,SRCCOPY);//将内存memDC中的位图拷贝到显示pDC中memDC.SelectObject(pOldBitmap);//恢复位图NewBitmap.DeleteObject();//删除位图}(2)绘制裁剪窗口void CTestView::DrawWindowRect(CDC* pDC)//绘制裁剪窗口{// TODO: Add your message handler code here and/or call defaultpDC->SetTextColor(RGB(128,0,255));pDC->TextOut(-10,Wyt+20,CString("窗口"));CPen NewPen3,*pOldPen3;//定义3个像素宽度的画笔NewPen3.CreatePen(PS_SOLID,3,RGB(255,128,0));pOldPen3=pDC->SelectObject(&NewPen3);pDC->Rectangle(Wxl,Wyt,Wxr,Wyb);pDC->SelectObject(pOldPen3);NewPen3.DeleteObject();}(3)Cohen-Sutherland算法void CTestView::Cohen()//Cohen-Sutherland算法{CP2 p;//交点坐标EnCode(P[0]);//起点编码EnCode(P[1]);//终点编码while(P[0].rc!=0 || P[1].rc!=0)//处理至少一个顶点在窗口之外的情况{if((P[0].rc & P[1].rc)!=0)//简弃之{PtCount=0;return;}if(0==P[0].rc)//确保P[0]位于窗口之外{CP2 Temp;Temp=P[0];P[0]=P[1];P[1]=Temp;}UINT RC=P[0].rc;double k=(P[1].y-P[0].y)/(P[1].x-P[0].x);//直线段的斜率//窗口边界按左、右、下、上的顺序裁剪直线段if(RC & LEFT)//P[0]点位于窗口的左侧{p.x=Wxl;//计算交点y坐标p.y=k*(p.x-P[0].x)+P[0].y;}else if(RC & RIGHT)//P[0]点位于窗口的右侧{p.x=Wxr;//计算交点y坐标p.y=k*(p.x-P[0].x)+P[0].y;}else if(RC & BOTTOM)//P[0]点位于窗口的下侧{p.y=Wyb;//计算交点x坐标p.x=(p.y-P[0].y)/k+P[0].x;}else if(RC & TOP)//P[0]点位于窗口的上侧{p.y=Wyt;//计算交点x坐标p.x=(p.y-P[0].y)/k+P[0].x;}EnCode(p);P[0]=p;}}void CTestView::EnCode(CP2 &pt)//端点编码函数{pt.rc=0;if(pt.x<Wxl)pt.rc=pt.rc|LEFT;else if(pt.x>Wxr)pt.rc=pt.rc|RIGHT;if(pt.y<Wyb)pt.rc=pt.rc|BOTTOM;else if(pt.y>Wyt)pt.rc=pt.rc|TOP;}(4)人机交互void CTestView::OnDrawpic(){// TODO: Add your command handler code herePtCount=0;bDrawLine=TRUE;MessageBox(CString("鼠标画线,剪刀裁剪"),CString("提示"),MB_OKCANCEL);Invalidate(FALSE);}运行结果:实验拓展:在屏幕上显示一个直线构成的图案,使用鼠标选择两点绘制矩形代表窗口对图案矩形裁剪。
图形学实验报告裁剪

#ifdef _AFXDLL
Enable3dControls();// Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic();// Call this when linking to MFC statically
// CMyApp
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
//{{AFX_MSG_MAP(CMyApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyApp construction
#endif
CMyDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
计算机图形学实验报告三图形裁剪算法

图形裁剪算法1.实验目的:理解地区编码设计直线裁剪算法编程实现直线裁剪算法2.实验描绘:设置裁剪窗口坐标为:wxl=250;wxr=850;wyb=250;wyt=450;裁剪前以下列图所示:裁剪后结果为:3.算法设计:直线裁剪算法:假定裁剪窗口是标准矩形,由上(y=wyt )、下( y=wyb )、左( x=wxl )、右( x=wxr )四条边构成,以下列图所示。
延伸窗口四条边形成9 个地区。
依据被裁剪直线的任一端点P(x, y)所处的窗口地区地点,能够给予一组 4 位二进制地区码C4C3C2C1 。
编码定义规则:第一位 C1:若端点位于窗口之左边,即第二位 C2:若端点位于窗口之右边,即第三位 C3:若端点位于窗口之下侧,即第四位 C4:若端点位于窗口之上侧,即X<WxlX>WxrY<WybY>Wyt,则,则,则,则C1=1 ,不然C2=1 ,不然C3=1 ,不然C4=1 ,不然C1=0。
C2=0。
C3=0 。
C4=0。
裁剪步骤:1.若直线的两个端点的地区编码都为0,即 RC1|RC2=0 (两者按位相或的结果为 0,即2.若直线的两个端点的地区编码都不为0,即 RC1&RC2 ≠ 0(两者按位相与的结果不为0,即 RC1≠0 且 RC2≠ 0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“ 简弃”。
3.若直线既不知足“ 简取” 也不知足“ 简弃” 的条件,直线段必定与窗口订交,需要计算直线与窗口界限的交点。
交点将直线分为两段,此中一段完整位于窗口外,可“ 简弃”。
对另一段给予交点处的地区编码,再次测试,再次求交,直至确立完整位于窗口内的直线段为止。
4.实现时,一般按固定次序左( x=wxl )、右( x=wxr )、下( y=wyb )、上( y=wyt )求解窗口与直线的交点。
4.源程序:class CTestView : public CView{.protected:double Pointx[2],Pointy[2];//用户绘制的直线int wxl,wxr,wyb,wyt;//左上与右下CDC Picture;// 内存 (预存 )DC, 防备屏幕闪耀char m_i; // 第一个点仍是第二个点BOOL m_Attatch;BOOL m_Draw;unsigned int RC,RC0,RC1;..}CTestView::CTestView(){//窗口地点坐标wxl=250;wxr=850;wyb=250;wyt=450;m_Attatch=FALSE;m_i=0;m_Draw=FALSE;RC0=0;RC1=0;}void CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);//装载位图CRect Rect;GetClientRect(&Rect);// 获取客户区的大小CBitmap Bitmap,*pBitmap;Bitmap.LoadBitmap(IDB_BITMAP);CDC MemDC;MemDC.CreateCompatibleDC(GetDC());pBitmap=MemDC.SelectObject(&Bitmap);MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);MemDC.TextOut((wxl+wxr)/2,wyb-20,"窗口");//窗口标题//绘制窗口和直线CPen Pen3,*pOldPen3;// 定义 3 个像素宽度的画笔Pen3.CreatePen(PS_SOLID,3,RGB(0,0,0));pOldPen3=MemDC.SelectObject(&Pen3);MemDC.MoveTo(wxl,wyt);MemDC.LineTo(wxr,wyt);MemDC.LineTo(wxr,wyb);MemDC.LineTo(wxl,wyb);MemDC.LineTo(wxl,wyt);MemDC.SelectObject(pOldPen3);Pen3.DeleteObject();CPen Pen1,*pOldPen1;// 定义 1 个像素宽度的画笔Pen1.CreatePen(PS_SOLID,1,RGB(0,0,255));pOldPen1=MemDC.SelectObject(&Pen1);if(m_i>=1){MemDC.MoveTo(ROUND(Pointx[0]),ROUND(Pointy[0]));MemDC.LineTo(ROUND(Pointx[1]),ROUND(Pointy[1]));}MemDC.SelectObject(pOldPen1);Pen1.DeleteObject();CDC *dc=GetDC();dc->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);MemDC.SelectObject(pBitmap);}void CTestView::OnMENUClip()//裁剪菜单函数{Cohen();Invalidate(FALSE);}unsigned int CTestView::EnCode(double LinePx,double LinePy)//端点编码函数{// 次序左右下上RC=0;if(LinePx<wxl){RC=RC | LEFT;}if(LinePx>wxr){RC=RC | RIGHT;}if(LinePy<wyb){RC=RC | BOTTOM;}if(LinePy>wyt){RC=RC | TOP;}return RC;}void CTestView::OnMENUDrawLine()//绘制直线菜单函数{//TODO: Add your command handler codehere if(FALSE==m_Attatch){Picture.CreateCompatibleDC(GetDC());CBitmap *Bitmap,*pBitmap;Bitmap=new CBitmap;Bitmap->LoadBitmap(IDB_BITMAP);pBitmap=Picture.SelectObject(Bitmap);m_Attatch=TRUE;}m_Draw=TRUE;m_i=0;Invalidate(FALSE);AfxGetMainWnd()->SetWindowText("事例10:Cohen-Sutherland直线裁剪算法");// 显示标题MessageBox(" 请使用鼠标在屏幕上绘制直线,而后点击裁剪按钮进行裁剪"," 提示",MB_OKCANCEL);}void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//单击鼠标左键函数{//TODO: Add your message handler code here and/or call defaultif(TRUE==m_Draw){if(m_i<2){Pointx[m_i]=point.x;Pointy[m_i]=point.y;m_i++;}}CView::OnLButtonDown(nFlags, point);}void CTestView::OnMouseMove(UINT nFlags, CPoint point) //鼠标挪动函数{//TODO: Add your message handler code here and/or call defaultif(TRUE==m_Draw){if(m_i<2){Pointx[m_i]=point.x;Pointy[m_i]=point.y;Invalidate(FALSE);}}CView::OnMouseMove(nFlags, point);}void CTestView::Cohen()//Cohen - Sutherland 算法{BOOL Change;double x,y;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);while(TRUE){Change=FALSE;if(0 == (RC0|RC1)){// 简取之return;}else if(0!=(RC0 & RC1)){// 简弃之return;}else{if(0==RC0)// 假如P0 点在窗口内,互换P0 和P1,保证p0 点在窗口外{//互换点的坐标值double TPointx,TPointy;TPointx=Pointx[0];TPointy=Pointy[0];Pointx[0]=Pointx[1];Pointy[0]=Pointy[1];Pointx[1]=TPointx;Pointy[1]=TPointy;//互换点的编码值unsigned int TRC;TRC=RC0;RC0=RC1;RC1=TRC;}//按左、右、下、上的次序裁剪if(RC0 & LEFT )//P0点位于窗口的左边{x=wxl;// 求交点 yy=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & RIGHT )//P0点位于窗口的右边{x=wxr;// 求交点 yy=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & BOTTOM )//P0点位于窗口的下侧{y=wyb;// 求交点 xx=Pointx[0]+(Pointx[1]-Pointx[0])*(y-Pointy[0])/(Pointy[1]-Pointy[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & TOP )//P0点位于窗口的上侧{y=wyt;// 求交点 xx=Pointx[0]+(Pointx[1]-Pointx[0])*(y-Pointy[0])/(Pointy[1]-Pointy[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(FALSE==Change){return;}}}}5.运转结果:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//绘制窗口和直线
CPen Pen3,*pOldPen3;//定义3个像素宽度的画笔
Pen3.CreatePen(PS_SOLID,3,RGB(0,0,0));
pOldPen3=MemDC.SelectObject(&Pen3);
if(TRUE==m_Draw)
{
if(m_i<2)
{
Pointx[m_i]=point.x;Pointy[m_i]=point.y;
m_i++;
}
}
CView::OnLButtonDown(nFlags, point);
}
void CTestView::OnMouseMove(UINT nFlags, CPoint point) //鼠标移动函数
MessageBox("请使用鼠标在屏幕上绘制直线,然后点击裁剪按钮进行裁剪","提示",MB_OKCANCEL);
}
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//单击鼠标左键函数
{
// TODO: Add your message handler code here and/or call default
Change=TRUE;
RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);
}
if(RC0 & RIGHT )//P0点位于窗口的右侧
{
x=wxr;//求交点y
y=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);
MemDC.LineTo(ROUND(Pointx[1]),ROUND(Pointy[1]));
}
MemDC.SelectObject(pOldPen1);
Pen1.DeleteObject();
CDC *dc=GetDC();
dc->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);
裁剪步骤:
1.若直线的两个端点的区域编码都为0,即RC1|RC2=0(二者按位相或的结果为0,即RC1=0且RC2=0),说明直线两端点都在窗口内,应“简取”。
2.若直线的两个端点的区域编码都不为0,即RC1&RC2≠0(二者按位相与的结果不为0,即RC1≠0且RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”。
编码定义规则:
第一位C1:若端点位于窗口之左侧,即X<Wxl,则C1=1,否则C1=0。
第二位C2:若端点位于窗口之右侧,即X>Wxr,则C2=1,否则C2=0。
第三位C3:若端点位于窗口之下侧,即Y<Wyb,则C3=1,否则C3=0。
第四位C4:若端点位于窗口之上侧,即Y>Wyt,则C4=1,否则C4=0。
pBitmap=Picture.SelectObject(Bitmap);
m_Attatch=TRUE;
}
m_Draw=TRUE;
m_i=0;
Invalidate(FALSE);
AfxGetMainWnd()->SetWindowText("案例10:Cohen-Sutherland直线裁剪算法");//显示标题
CPen Pen1,*pOldPen1;//定义1个像素宽度的画笔
Pen1.CreatePen(PS_SOLID,1,RGB(0,0,255));
pOldPen1=MemDC.SelectObject(&Pen1);
if(m_i>=1)
{
MemDC.MoveTo(ROUND(Pointx[0]),ROUND(Pointy[0]));
TPointx=Pointx[0];TPointy=Pointy[0];
Pointx[0]=Pointx[1];Pointy[0]=Pointy[1];
Pointx[1]=TPointx;Pointy[1]=TPointy;
//交换点的编码值
unsigned int TRC;
TRC=RC0;RC0=RC1;RC1=TRC;
}
//按左、右、下、上的顺序裁剪
if(RC0 & LEFT )//P0点位于窗口的左侧
{
x=wxl;//求交点y
y=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);
Pointx[0]=x;Pointy[0]=y;
charm_i; //第一个点还是第二个点
BOOLm_Attatch;
BOOLm_Draw;
unsigned int RC,RC0,RC1;
……..
}
2) //TestView.cpp
CTestView::CTestView()
{
//窗口位置坐标
wxl=250;wxr=850;wyb=250;wyt=450;
{
// TODO: Add your message handler code here and/or call default
if(TRUE==m_Draw)
{
if(m_i<2)
{
Pointx[m_i]=point.x;Pointy[m_i]=point.y;
Invalidate(FALSE);
}
while(TRUE)
{
Change=FALSE;
if(0 == (RC0|RC1))
{//简取之
return;
}
else if(0!=(RC0 & RC1))
{//简弃之
return;
}
else
{
if(0==RC0)//如果P0点在窗口内,交换P0和P1,保证p0点在窗口外
{
//交换点的坐标值
double TPointx,TPointy;
Pointx[0]=x;Pointy[0]=y;
Change=TRUE;
RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);
}
if(RC0 & BOTTOM )//P0点位于窗口的下侧
{
y=wyb;//求交点x
x=Pointx[0]+(Pointx[1]-Pointx[0])*(y-Pointy[0])/(Pointy[1]-Pointy[0]);
MemDC.SelectObject(pBitmap);
}
void CTestView::OnMENUClip()//裁剪菜单函数
{
Cohen();
Invalidate(FALSE);
}
unsigned int CTestView::EnCode(double LinePx,double LinePy)//端点编码函数
Pointx[0]=x;Pointy[0]=y;
Change=TRUE;
RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);
}
if(FALSE==Change)
{
return;
}
}
}
}
5.运行结果:
{//顺序左右下上
RC=0;
if(LinePx<wxl)
{
RC=RC | LEFT;
}
if(LinePx>wxr)
{
RC=RC | RIGHT;
}
if(LinePy<wyb)
{
RC=RC | BOTTOM;
}
if(LinePy>wyt)
{
RC=RC | TOP;
}
return RC;
}
void CTestView::OnMENUDrawLine()//绘制直线菜单函数
3.若直线既不满足“简取”也不满足“简弃”的条件,直线段必然与窗口相交,需要计算直线与窗口边界的交点。交点将直线分为两段,其中一段完全位于窗口外,可“简弃”。对另一段赋予交点处的区域编码,再次测试,再次求交,直至确定完全位于窗口内的直线段为止。
4.实现时,一般按固定顺序左(x=wxl)、右(x=wxr)、下(y=wyb)、上(y=wyt)求解窗口与直线的交点。
CBitmapBitmap,*pBitmap;
Bitmap.LoadBitmap(IDB_BITMAP);
CDCMemDC;
MemDC.CreateCompatibleDC(GetDC());
pBitmap=MemDC.SelectObject(&Bitmap);
MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);
}
CView::OnMouseMove(nFlags, point);
}
void CTestView::Cohen()//Cohen-Sutherland算法
{
BOOL Change;
double x,y;
RC0=EnCode(Pointx[0],Pointy[0]);
RC1=EnCode(Pointx[1],Pointy[1]);