计算机图形学多边形裁剪与填充计算机图形学课程设计.docx
《计算机图形学多边形裁剪与填充计算机图形学课程设计.docx》由会员分享,可在线阅读,更多相关《计算机图形学多边形裁剪与填充计算机图形学课程设计.docx(30页珍藏版)》请在冰豆网上搜索。
计算机图形学多边形裁剪与填充计算机图形学课程设计
课程设计报告
课程名称计算机图形学
课题名称多边形裁剪与填充
专业计算机科学与技术
班级计算机0902
学号
姓名
指导教师刘长松曹燚
2012年10月9日
湖南工程学院
课程设计任务书
课程名称计算机图形学
课题多边形裁剪与填充
专业班级计算机0902
学生姓名
学号
指导老师刘长松曹燚
审批
任务书下达日期2012年9月15日
任务完成日期2012年10月9日
一、设计内容与设计要求
1.设计内容:
交互式地实现多边形的裁剪和填充。
。
2.设计要求:
1)窗口功能设计。
2)实现鼠标画多边形与数据存储功能。
3)实现鼠标剪裁窗口选择功能。
4)实现多边形裁剪和填充功能。
3.算法提示:
多边形裁剪算法分析:
基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:
可见一侧,不可见一侧。
用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。
对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。
多边形填充算法分析:
确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax),从y=ymin到y=ymax,每次用一条扫描进行填充。
对一条扫描线填充的过程可分为四个步骤:
a.求交b.排序c.交点配对d.区间填色。
二、进度安排
第3周星期一8:
00——12:
00
星期二8:
00——12:
00
星期三8:
00——12:
00
星期四8:
00——12:
00
星期五8:
00——12:
00
第4周星期一8:
00——12:
00
附:
课程设计报告装订顺序:
封面、任务书、目录、正文、附件(A4大小的图纸及程序清单)、评分。
正文的格式:
一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。
正文的内容:
一、课题的主要功能;二、课题的功能模块的划分(要求画出模块图);三、主要功能的实现(至少要有一个主要模块的流程图);四、程序调试;五、总结;六、附件(所有程序的原代码,要求对程序写出必要的注释)。
正文总字数要求在5000字以上(不含程序原代码)。
一、题目内容说明:
1、交互式地实现多边形的裁剪和填充。
2、功能要求:
1)窗口功能设计。
2)实现鼠标画多边形与数据存储功能。
4)实现鼠标剪裁窗口选择功能。
5)实现多边形裁剪和填充功能。
二、总体设计:
本程序使用MFC实现多边形的裁剪和填充绘图程序。
多边形裁剪算法分析:
基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,改线把平面分成两个部分:
可见一侧,不可见一侧。
用一条裁剪边多多边形进行裁剪,得到一个顶点序列,作为吓一条裁剪边处理过程的输入点。
对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。
仅用一条裁剪边时,逐次多边形裁剪框图:
在CGraphics类的CutRectangular(CRect)函数中实现对多边形的裁剪
多边形填充算法分析:
确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax),从y=ymin到y=ymax,每次用一条扫描进行填充。
对一条扫描线填充的过程可分为四个步骤:
a.求交b.排序c.交点配对d.区间填色。
在CGraphics类中的FillPlogon函数中实现多边形的填充算法。
三、模块设计:
各个程序函数的功能,参数,变量的说明:
MFC应用程序框架中类的详细解析:
1.MainFrm:
创建窗口及窗口里的菜单、工具栏、状态栏等实现交互的按钮。
1)函数intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct){}创建菜单、工具栏、状栏。
2)BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)设置窗口的大小和初始位置。
2.图像裁剪View:
视图,负责内存数据与用户的交互,包括数据的显示、菜单的选取,鼠标的响应。
1.voidCMyView:
:
OnLButtonDown(UINTnFlags,CPointpoint){}对鼠标按下左键的响应,如果是自定义裁剪的区域操作就捕获鼠标按下的点,画裁剪区域,如果是自定义点坐标的操作就捕获鼠标的点画多边形。
2.voidCMyView:
:
OnMouseMove(UINTnFlags,CPointpoint){}对鼠标移动的响应。
用捕获的点画出相应的矩形裁剪边框。
画边框的时候,先用白色擦出原先的矩形边框,再用虚线画出新的举行边框
3.voidCMyView:
:
OnRButtonUp(UINTnFlags,CPointpoint){}对鼠标放开左键的相应。
如果是自定义点的坐标,就获取新的初始裁减矩形范围。
4.voidCMyView:
:
OnLButtonUp(UINTnFlags,CPointpoint){}对鼠标放开左键的响应
5.voidCMyView:
:
OnInitialUpdate(){}初始化裁剪区域和在窗口中画一个矩形和一个五角星。
6.voidCMyView:
:
OnDraw(CDC*pDC){}重画窗口,用voidCMyView:
:
OnInitialUpdate{}来启动它,通过消息映射表处理菜单、工具条、快捷键和其他用户消息。
定义裁剪矩形区域,并赋值。
当自定义多边形坐标时,在各个点坐标处画一个小圆,以显示点的位置。
画出多边形。
3.图像裁剪DOC:
文档,负责内存数据与磁盘的交互。
1、voidCMyDoc:
:
OnFillployon(){}
2、voidCMyDoc:
:
OnUpdateFillployon(CCmdUI*pCmdUI){}
3、voidCMyDoc:
:
OnCutRect(){}
4、voidCMyDoc:
:
OnUpdateCutRect(CCmdUI*pCmdUI){}
4.CGraphics:
实现多边形的填充和裁剪。
1、构造函数CGraphics():
PointCount(10),Point(NULL){}初始化五角星的顶点坐标。
2、析构函数~CGraphics(){}删除动态生成的Point指针。
3、boolDrawPloyon(CDC*);在指定设备中画多边形。
4、boolFillPloyon(CDC*);填充多边形。
5、boolInterCross(CPoint,CPoint,CPoint,CPoint,CPoint&);判断两条线段是否相交。
6、boolCutRect(CRect);对多边形进行裁剪。
7、boolIsInSquareRgn(CRect,CPoint,int);对多边形裁剪时,判断线段断点是否在可视一侧。
8、boolSortArray(int*,int);冒泡排序。
四、详细设计:
1、创建窗口、菜单、工具栏、状栏的函数。
intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
if(CFrameWnd:
:
OnCreate(lpCreateStruct)==-1)
return-1;
if(!
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failedtocreatetoolbar\n");
return-1;//failtocreate
}
if(!
m_wndStatusBar.Create(this)||
!
m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failedtocreatestatusbar\n");
return-1;//failtocreate
}
//TODO:
Deletethesethreelinesifyoudon'twantthetoolbarto
//bedockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return0;
}
2、鼠标按下左键的响应函数
voidCMyView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//对鼠标按下左键的相应
CScrollView:
:
OnLButtonDown(nFlags,point);
if(m_bDefineRect)
{
//如果是自定义裁减的区域的操作
SetCapture();//捕获鼠标
m_bCaptured=TRUE;
CDC*dc=GetDC();
CRectrect(TopLeft,BottomRight);
dc->SelectStockObject(WHITE_PEN);
dc->Rectangle(rect);
InvalidateRect(rect,false);
TopLeft=point;
:
:
SetCursor(:
:
LoadCursor(NULL,IDC_CROSS));//设置鼠标样子为十字形的
}
if(m_bDefinePointV)
{
//如果是自定义点坐标的操作
PointArray.Add(point);
CRectellipseRect;
ellipseRect.top=point.y-5;
ellipseRect.bottom=point.y+5;
ellipseRect.left=point.x-5;
ellipseRect.right=point.x+5;
InvalidateRect(ellipseRect,true);
}
}
3、鼠标移动时的响应函数
voidCMyView:
:
OnMouseMove(UINTnFlags,CPointpoint)
{
CScrollView:
:
OnMouseMove(nFlags,point);
//对鼠标移动时的相应
if(m_bCaptured)
{
//画出相应的矩形裁减边框
CDC*dc=GetDC();
CRectrect(TopLeft,BottomRight);
dc->SelectStockObject(WHITE_PEN);
dc->Rectangle(rect);//用白色擦除原先的矩形边框
InvalidateRect(rect,false);
BottomRight=point;
CRectnewrect(TopLeft,BottomRight);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(0,0,0));
dc->SelectObject(pen);
dc->Rectangle(newrect);//用虚线画出新的矩形边框
}
}
voidCMyView:
:
OnLButtonUp(UINTnFlags,CPointpoint)
{
CScrollView:
:
OnLButtonUp(nFlags,point);
//对鼠标放开左键的响应
if(m_bCaptured)
{
:
:
ReleaseCapture();
m_bCaptured=false;
m_bDefineRect=false;
}
}
voidCMyView:
:
OnViewDefineRect()
{
//设置是否自定义裁减区域
m_bDefineRect=true;
}
voidCMyView:
:
OnEditDefinePoint()
{
//设置是否自定义点的坐标
m_bDefinePointV=true;
}
4、放开鼠标右键的响应
voidCMyView:
:
OnRButtonUp(UINTnFlags,CPointpoint)
{
////对鼠标放开右键的相应
CScrollView:
:
OnRButtonUp(nFlags,point);
if(m_bDefinePointV)
{
CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_grahics.PointCount=PointArray.GetSize();
if(pDoc->m_grahics.Point)
deletepDoc->m_grahics.Point;
pDoc->m_grahics.Point=newCPoint[pDoc->m_grahics.PointCount];
for(inti=0;im_grahics.PointCount;i++)
pDoc->m_grahics.Point[i]=PointArray.GetAt(i);//对Point点坐标重新赋值
PointArray.RemoveAll();
m_bDefinePointV=false;
CRectrect;
this->GetClientRect(rect);
InvalidateRect(rect);
//获取新的初始裁减矩形范围
intminX=pDoc->m_grahics.Point[0].x,minY=pDoc->m_grahics.Point[0].y;
intmaxX=pDoc->m_grahics.Point[0].x,maxY=pDoc->m_grahics.Point[0].y;
for(i=1;im_grahics.PointCount;i++)
{
if(minX>pDoc->m_grahics.Point[i].x)
minX=pDoc->m_grahics.Point[i].x;
if(minY>pDoc->m_grahics.Point[i].y)
minY=pDoc->m_grahics.Point[i].y;
if(maxXm_grahics.Point[i].x)
maxX=pDoc->m_grahics.Point[i].x;
if(maxYm_grahics.Point[i].y)
maxY=pDoc->m_grahics.Point[i].y;
}
TopLeft=CPoint(minX,minY);
BottomRight=CPoint(maxX,maxY);
}
}
5、初始化函数
voidCMyView:
:
OnInitialUpdate()
{
CScrollView:
:
OnInitialUpdate();
CSizesizeTotal;
sizeTotal.cx=sizeTotal.cy=100;
SetScrollSizes(MM_TEXT,sizeTotal);
CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//设置初始的裁减区域
intminX=pDoc->m_grahics.Point[0].x,minY=pDoc->m_grahics.Point[0].y;
intmaxX=pDoc->m_grahics.Point[0].x,maxY=pDoc->m_grahics.Point[0].y;
for(inti=1;im_grahics.PointCount;i++)
{
if(minX>pDoc->m_grahics.Point[i].x)
minX=pDoc->m_grahics.Point[i].x;
if(minY>pDoc->m_grahics.Point[i].y)
minY=pDoc->m_grahics.Point[i].y;
if(maxXm_grahics.Point[i].x)
maxX=pDoc->m_grahics.Point[i].x;
if(maxYm_grahics.Point[i].y)
maxY=pDoc->m_grahics.Point[i].y;
}
TopLeft=CPoint(minX,minY);
BottomRight=CPoint(maxX,maxY);
}
6、重画窗口的函数,是MFC自动生成的,我们可以在里面添加自己的代码,用来实现消息映射表处理菜单、工具条、快捷键和其他用户消息。
voidCMyView:
:
OnDraw(CDC*pDC)
{
CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
intleft,top,right,buttom;
left=min(TopLeft.x,BottomRight.x);
right=max(TopLeft.x,BottomRight.x);
top=min(TopLeft.y,BottomRight.y);
buttom=max(TopLeft.y,BottomRight.y);
CRectrect(left,top,right,buttom);
//定义裁减矩形区域,并赋值
CPenpenDot,penSolid;
penDot.CreatePen(PS_DOT,1,RGB(0,0,0));
pDC->SelectObject(penDot);
pDC->Rectangle(rect);
//用虚线画出裁减矩形区域
penSolid.CreatePen(PS_SOLID,1,RGB(0,0,0));
pDC->SelectObject(penSolid);
if(PointArray.GetSize())
{
//当自定义多边形点坐标时,在各个点坐标处画一个小圆,以显示点的位置
inti;
for(i=0;i{
pDC->MoveTo(PointArray.GetAt(i));
CRectellipseRect;
ellipseRect.top=PointArray.GetAt(i).y-5;
ellipseRect.bottom=PointArray.GetAt(i).y+5;
ellipseRect.left=PointArray.GetAt(i).x-5;
ellipseRect.right=PointArray.GetAt(i).x+5;
pDC->Ellipse(ellipseRect);
}
}
if(pDoc->bCutRect)
{
//判断是否裁减,若是,则根据裁减区域进行裁减
pDoc->m_grahics.CutRect(rect);
pDoc->bCutRect=false;
}
pDoc->m_grahics.DrawPloyon(pDC);
//画出多边形
if(pDoc->bFillPloyon)
{
//判断是否填充,根据需要进行相应的操作
pDoc->m_grahics.FillPloyon(pDC);
pDoc->bFillPloyon=false;
}
}
7、在指定的pDC设备中,画多边形
boolCGraphics:
:
DrawPloyon(CDC*pDC)
{
if(PointCount<3)
returnfalse;
//若多边形小于三个点则返回
pDC->MoveTo(Point[0]);
for(inti=1;i{
pDC->LineTo(Point[i]);
}
pDC->LineTo(Point[0]);
//在pDC中画出多边形
returntrue;
}
8、填充多边形函数,重量级的函数
//在指定的pDC设备中,填充多边形
boolCGraphics:
:
FillPloyon(CDC*pDC)
{
if(PointCount<3)
returnfalse;
//若多边形小于三个点则返回
intminX=Point[0].x,minY=Point[0].y;
intmaxX=Point[0].x,maxY=Point[0].y;
for(inti=1;i{
if(minX>Point[i].x)
minX=Point[i].x;
if(minY>Point[i].y)
minY=Point[i].y;
if(maxXmaxX=Point[i].x;
if(maxYmaxY=Point[i].y;
}
//获取多边形中所有坐标点的最大值和最小值,作为扫描线循环的范围
CUIntArraymyArray;
intx,y;
for(y=minY;y{
//扫描线从minY开始到maxY
for(i=0;i{
//对每条边进行循环
CPo