计算机图形学---多边形裁剪与填充-计算机图形学课程设计.doc

上传人:叶*** 文档编号:35386038 上传时间:2022-08-21 格式:DOC 页数:22 大小:694.50KB
返回 下载 相关 举报
计算机图形学---多边形裁剪与填充-计算机图形学课程设计.doc_第1页
第1页 / 共22页
计算机图形学---多边形裁剪与填充-计算机图形学课程设计.doc_第2页
第2页 / 共22页
点击查看更多>>
资源描述

《计算机图形学---多边形裁剪与填充-计算机图形学课程设计.doc》由会员分享,可在线阅读,更多相关《计算机图形学---多边形裁剪与填充-计算机图形学课程设计.doc(22页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、课 程 设 计 报 告课程名称 计算机图形学 课题名称 多边形裁剪与填充 专 业 计算机科学与技术 班 级 计算机0902 学 号 姓 名 指导教师 刘长松 曹 燚 2012年 10 月 9 日湖南工程学院课 程 设 计 任 务 书课程名称 计算机图形学 课 题 多边形裁剪与填充 专业班级 计算机0902 学生姓名 学 号 指导老师 刘长松 曹 燚 审 批 任务书下达日期 2012年 9月 15 日任务完成日期 2012 年 10月 9 日一、设计内容与设计要求1设计内容:交互式地实现多边形的裁剪和填充。2设计要求:1)窗口功能设计。 2)实现鼠标画多边形与数据存储功能。 3)实现鼠标剪裁窗口

2、选择功能。4)实现多边形裁剪和填充功能。3.算法提示:多边形裁剪算法分析:基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:可见一侧,不可见一侧。用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。多边形填充算法分析:确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间

3、填色。二、进度安排第 3 周 星期一 8:0012:00星期二 8:0012:00 星期三 8:0012:00 星期四 8:0012:00 星期五 8:0012:00第 4 周 星期一 8:0012:00附:课程设计报告装订顺序:封面、任务书、目录、正文、附件(A4大小的图纸及程序清单)、评分。 正文的格式:一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。正文的内容:一、课题的主要功能;二、课题的功能模块的划分(要求画出模块图);三、主要功能的实现(至少要有一个主要模块的流程图);四、程序调试;五、总结;六、附件(所有程序的原代码,要求对程序写出必要的注释)。正文总字

4、数要求在5000字以上(不含程序原代码)。一、题目内容说明:1、交互式地实现多边形的裁剪和填充。2、功能要求:1) 窗口功能设计。 2)实现鼠标画多边形与数据存储功能。 4)实现鼠标剪裁窗口选择功能。5) 实现多边形裁剪和填充功能。二、总体设计:本程序使用MFC实现多边形的裁剪和填充绘图程序。多边形裁剪算法分析:基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,改线把平面分成两个部分:可见一侧,不可见一侧。用一条裁剪边多多边形进行裁剪,得到一个顶点序列,作为吓一条裁剪边处理过程的输入点。对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。仅

5、用一条裁剪边时,逐次多边形裁剪框图:在CGraphics类的CutRectangular(CRect)函数中实现对多边形的裁剪多边形填充算法分析:确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间填色。在CGraphics类中的FillPlogon函数中实现多边形的填充算法。三、模块设计:各个程序函数的功能,参数,变量的说明:MFC应用程序框架中类的详细解析:1MainFrm:创建窗口及窗口里的菜单、工具栏、状态栏等实现交互

6、的按钮。1)函数int CMainFrame:OnCreate(LPCREATESTRUCT lpCreateStruct)创建菜单、工具栏、状栏。2)BOOL CMainFrame:PreCreateWindow(CREATESTRUCT& cs)设置窗口的大小和初始位置。2图像裁剪View:视图,负责内存数据与用户的交互,包括数据的显示、菜单的选取,鼠标的响应。1. void CMyView:OnLButtonDown(UINT nFlags, CPoint point)对鼠标按下左键的响应,如果是自定义裁剪的区域操作就捕获鼠标按下的点,画裁剪区域,如果是自定义点坐标的操作就捕获鼠标的点画

7、多边形。2. void CMyView:OnMouseMove(UINT nFlags, CPoint point)对 鼠标 移动的响应。用捕获的点画出相应的矩形裁剪边框。画边框的时候,先用白色擦出原先的矩形边框,再用虚线画出新的举行边框3. void CMyView:OnRButtonUp(UINT nFlags, CPoint point)对鼠标放开左键的相应。如果是自定义点的坐标,就获取新的初始裁减矩形范围。4. void CMyView:OnLButtonUp(UINT nFlags, CPoint point)对鼠标放开左键的响应5. void CMyView:OnInitialUp

8、date()初始化裁剪区域和在窗口中画一个矩形和一个五角星。6. void CMyView:OnDraw(CDC* pDC)重画窗口,用voidCMyView:OnInitialUpdate来启动它,通过消息映射表处理菜单、工具条、快捷键和其他用户消息。定义裁剪矩形区域,并赋值。当自定义多边形坐标时,在各个点坐标处画一个小圆,以显示点的位置。画出多边形。3图像裁剪DOC:文档,负责内存数据与磁盘的交互。1、 void CMyDoc:OnFillployon()2、 void CMyDoc:OnUpdateFillployon(CCmdUI* pCmdUI)3、 void CMyDoc:OnCu

9、tRect()4、 void CMyDoc:OnUpdateCutRect(CCmdUI* pCmdUI)4.CGraphics:实现多边形的填充和裁剪。1、 构造函数CGraphics():PointCount(10),Point(NULL)初始化五角星的顶点坐标。2、 析构函数CGraphics()删除动态生成的Point指针。3、 bool DrawPloyon(CDC*);在指定设备中画多边形。4、 bool FillPloyon(CDC*);填充多边形。5、 bool InterCross(CPoint,CPoint,CPoint,CPoint,CPoint&);判断两条线段是否相交

10、。6、 bool CutRect(CRect);对多边形进行裁剪。7、 bool IsInSquareRgn(CRect,CPoint,int);对多边形裁剪时,判断线段断点是否在可视一侧。8、 bool SortArray(int*,int);冒泡排序。四、详细设计:1、创建窗口、菜单、工具栏、状栏的函数。int CMainFrame:OnCreate(LPCREATESTRUCT lpCreateStruct)if (CFrameWnd:OnCreate(lpCreateStruct) = -1)return -1;if (!m_wndToolBar.CreateEx(this, TBST

11、YLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) |!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)TRACE0(Failed to create toolbarn);return -1; / fail to createif (!m_wndStatusBar.Create(this) |!m_wndStatusBar.SetIndicators(indicators, sizeof(indicato

12、rs)/sizeof(UINT)TRACE0(Failed to create status barn);return -1; / fail to create/ TODO: Delete these three lines if you dont want the toolbar to/ be dockablem_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);return 0; 2、鼠标按下左键的响应函数void CMyView:OnLB

13、uttonDown(UINT nFlags, CPoint point) /对鼠标按下左键的相应CScrollView:OnLButtonDown(nFlags, point);if(m_bDefineRect) /如果是自定义裁减的区域的操作SetCapture();/捕获鼠标m_bCaptured = TRUE;CDC *dc=GetDC();CRect rect(TopLeft,BottomRight);dc-SelectStockObject(WHITE_PEN);dc-Rectangle(rect);InvalidateRect(rect,false);TopLeft = point

14、;:SetCursor(:LoadCursor(NULL, IDC_CROSS);/设置鼠标样子为十字形的if(m_bDefinePointV)/如果是自定义点坐标的操作PointArray.Add(point);CRect ellipseRect;ellipseRect.top = point.y - 5;ellipseRect.bottom = point.y + 5;ellipseRect.left = point.x - 5;ellipseRect.right = point.x + 5;InvalidateRect(ellipseRect,true);3、鼠标移动时的响应函数void

15、 CMyView:OnMouseMove(UINT nFlags, CPoint point) CScrollView:OnMouseMove(nFlags, point);/对鼠标移动时的相应if (m_bCaptured) /画出相应的矩形裁减边框CDC *dc=GetDC();CRect rect(TopLeft,BottomRight);dc-SelectStockObject(WHITE_PEN);dc-Rectangle(rect);/用白色擦除原先的矩形边框InvalidateRect(rect,false);BottomRight=point;CRect newrect(Top

16、Left,BottomRight);CPen pen;pen.CreatePen(PS_DOT,1,RGB(0,0,0);dc-SelectObject(pen);dc-Rectangle(newrect);/用虚线画出新的矩形边框 void CMyView:OnLButtonUp(UINT nFlags, CPoint point) CScrollView:OnLButtonUp(nFlags, point);/对鼠标放开左键的响应 if (m_bCaptured) :ReleaseCapture(); m_bCaptured = false;m_bDefineRect = false;vo

17、id CMyView:OnViewDefineRect() /设置是否自定义裁减区域m_bDefineRect = true;void CMyView:OnEditDefinePoint() /设置是否自定义点的坐标m_bDefinePointV = true;4、放开鼠标右键的响应void CMyView:OnRButtonUp(UINT nFlags, CPoint point) /对鼠标放开右键的相应CScrollView:OnRButtonUp(nFlags, point);if(m_bDefinePointV)CMyDoc* pDoc = GetDocument();ASSERT_V

18、ALID(pDoc);pDoc-m_grahics.PointCount=PointArray.GetSize();if(pDoc-m_grahics.Point)delete pDoc-m_grahics.Point;pDoc-m_grahics.Point = new CPointpDoc-m_grahics.PointCount;for(int i=0;im_grahics.PointCount;i+)pDoc-m_grahics.Pointi=PointArray.GetAt(i);/对Point点坐标重新赋值PointArray.RemoveAll();m_bDefinePointV

19、=false;CRect rect;this-GetClientRect(rect);InvalidateRect(rect);/获取新的初始裁减矩形范围int minX = pDoc-m_grahics.Point0.x , minY = pDoc-m_grahics.Point0.y;int maxX = pDoc-m_grahics.Point0.x , maxY = pDoc-m_grahics.Point0.y;for(i=1;im_grahics.PointCount;i+)if(minX pDoc-m_grahics.Pointi.x)minX = pDoc-m_grahics.

20、Pointi.x;if(minY pDoc-m_grahics.Pointi.y)minY = pDoc-m_grahics.Pointi.y;if(maxX m_grahics.Pointi.x)maxX = pDoc-m_grahics.Pointi.x;if(maxY m_grahics.Pointi.y)maxY = pDoc-m_grahics.Pointi.y;TopLeft = CPoint(minX,minY);BottomRight = CPoint(maxX,maxY);5、初始化函数void CMyView:OnInitialUpdate()CScrollView:OnI

21、nitialUpdate();CSize sizeTotal;sizeTotal.cx = sizeTotal.cy = 100;SetScrollSizes(MM_TEXT, sizeTotal);CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/设置初始的裁减区域int minX = pDoc-m_grahics.Point0.x , minY = pDoc-m_grahics.Point0.y;int maxX = pDoc-m_grahics.Point0.x , maxY = pDoc-m_grahics.Point0.y;for(in

22、t i=1;im_grahics.PointCount;i+)if(minX pDoc-m_grahics.Pointi.x)minX = pDoc-m_grahics.Pointi.x;if(minY pDoc-m_grahics.Pointi.y)minY = pDoc-m_grahics.Pointi.y;if(maxX m_grahics.Pointi.x)maxX = pDoc-m_grahics.Pointi.x;if(maxY m_grahics.Pointi.y)maxY = pDoc-m_grahics.Pointi.y;TopLeft = CPoint(minX,minY)

23、;BottomRight = CPoint(maxX,maxY);6、重画窗口的函数,是MFC自动生成的,我们可以在里面添加自己的代码,用来实现消息映射表处理菜单、工具条、快捷键和其他用户消息。void CMyView:OnDraw(CDC* pDC)CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data hereint left,top,right,buttom;left=min(TopLeft.x,BottomRight.x);right=max(TopLeft.x,Bott

24、omRight.x);top=min(TopLeft.y,BottomRight.y);buttom=max(TopLeft.y,BottomRight.y);CRect rect(left,top,right,buttom);/定义裁减矩形区域,并赋值CPen penDot,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(

25、penSolid);if(PointArray.GetSize()/当自定义多边形点坐标时,在各个点坐标处画一个小圆,以显示点的位置int i;for(i=0;iMoveTo(PointArray.GetAt(i);CRect ellipseRect;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

26、).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设备中,画多边形bool CGraphics:DrawPloyon(CDC*

27、pDC)if(PointCount MoveTo(Point0);for(int i=1;iLineTo(Pointi);pDC-LineTo(Point0);/在pDC中画出多边形return true;8、填充多边形函数,重量级的函数/在指定的pDC设备中,填充多边形bool CGraphics:FillPloyon(CDC* pDC)if(PointCount 3)return false;/若多边形小于三个点则返回int minX = Point0.x , minY = Point0.y;int maxX = Point0.x , maxY = Point0.y;for(int i=1

28、;i Pointi.x)minX = Pointi.x;if(minY Pointi.y)minY = Pointi.y;if(maxX Pointi.x)maxX = Pointi.x;if(maxY Pointi.y)maxY = Pointi.y;/获取多边形中所有坐标点的最大值和最小值,作为扫描线循环的范围CUIntArray myArray;int x,y;for(y=minY;ymaxY;y+)/扫描线从minY开始到maxYfor(i=0;i PointCross.y) & (PointafterI.y PointCross.y)myArray.Add(PointCross.x)

29、;myArray.Add(PointCross.x);/边顶点的y值大于交点的y值,x坐标取两次elseif(PointbeforeI.y - PointCross.y) * (PointafterI.y - PointCross.y) 0)myArray.Add(PointCross.x);/边顶点的y值在交点的y值之间,即一个顶点的y值大于交点的y值,而另一个小于,相应的x坐标取一次elseif(PointCross.y=PointafterI.y)myArray.Add(PointCross.x); else if(PointCross=PointbeforeI)continue;els

30、emyArray.Add(PointCross.x);/当交点不在线段的顶点时,x坐标只取一次int *scanLineX,num=myArray.GetSize();scanLineX = new intnum;for(i=0;inum;i+)scanLineXi=myArray.GetAt(i);/获取扫描线x值,以构成填充区间myArray.RemoveAll();SortArray(scanLineX,num);/对scanLine(扫描线x坐标进行排序)for(i=0;i=num)break;for(x=scanLineXi;xSetPixelV(CPoint(x,y),RGB(25

31、5,0,0);/将填充区间相应点的颜色设置成红色 Sleep(1);/CPU暂停1ms,以体现出多边形是以扫描线的方式,一条一条的填充的delete scanLineX;return true;9、裁剪多边形的函数,重量级的函数bool CGraphics:CutRect(CRect rect)CPoint rectPoint4;rectPoint0.x = rect.left;rectPoint0.y = rect.top;rectPoint1.x = rect.right;rectPoint1.y = rect.top;rectPoint3.x = rect.left;rectPoint3

32、.y = rect.bottom;rectPoint2.x = rect.right;rectPoint2.y = rect.bottom;/获取裁减矩形的四个点的坐标,第一个点为左上,第二个点为右上,第三个点为右下,第四个点为左下int i;CArray myArray;/裁减后,保存的多边形的依次各点的坐标for(int rectNum=0;rectNum4;rectNum+)/对裁减矩形的四条边进行循环for(i=0;iPointCount;i+)/对每条边进行循环CPoint PointCross;int beforeI=BeforeIndex(i),afterI=AfterIndex

33、(i);int afterrectNum = (rectNum = 3)?0:rectNum+1);/判断是否跟线段相交if(InterCross(PointbeforeI,Pointi,rectPointrectNum,rectPointafterrectNum,PointCross)if(PointCross=Pointi)myArray.Add(Pointi);/交点在线段上,直接添加点坐标在保存多边形的数组中else if(PointCross=PointbeforeI)if(IsInSquareRgn(rect,Pointi,rectNum)myArray.Add(Pointi);/

34、判断是否可视,若是,则添加点坐标elsemyArray.Add(PointCross);/跟线段相交,但交点不在顶点上,添加交点坐标if(IsInSquareRgn(rect,Pointi,rectNum)myArray.Add(Pointi);/判断是否可视,若是,则添加点坐标elseif(IsInSquareRgn(rect,Pointi,rectNum)myArray.Add(Pointi);/线段不相交,但需判断是否可视,若是,则添加点坐标PointCount=myArray.GetSize();if(Point)delete Point;Point = new CPointPoint

35、Count;for(i=0;i=0) & (objectP1.x-x)*(x-objectP2.x)=0)/判断交点是不是在该两条线段上coordinate.x = objectP1.x;coordinate.y = (int)(y+0.5);return true;return false;elseif(scanP1.x = scanP2.x)/当第二条线段斜率不存在是的,处理办法double x,y;x = scanP1.x;y = (objectP1.y-objectP2.y)*1.0/(objectP1.x-objectP2.x)*(scanP1.x-objectP1.x)+objectP1.y;y = (float)(int)(y+0.5);if(objectP1.y-y)*(y-objectP2.y)=0) & (objectP1.x-x)*(x-objectP2.x)=0)/判断交点是不是在该两条线段上coordinate.x = scanP1.x;coordinate.y = (int)(y+0.5);return true;return false;else/两条线段斜率都存在时的处理办法double k1,k2;k1 = ( objectP1.y - objectP2.y ) * 1.0

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 初中资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁