《实验三计算机图形学多边形填充算法汇总(共17页).doc》由会员分享,可在线阅读,更多相关《实验三计算机图形学多边形填充算法汇总(共17页).doc(17页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上洛阳理工学院实验报告系别计算机与信息工程系班级B学号B姓名课程名称计算机图形学实验日期2013-11-7实验名称多边形填充算法编程成绩实验目的: 熟悉多边形填充算法,掌握MFC图形编程的基本方法和调试技巧。实验条件: 计算机;VS2008;OpenGL实验内容: 1使用MFC技术实现多边形有效边表填充算法,参考界面效果如下:/ ChildView.cpp : CChildView 类的实现#include stdafx.h#include demo.h#include ChildView.h#include #define Round(d) int(floor(d+0
2、.5)/四舍五入宏定义#ifdef _DEBUG#define new DEBUG_NEW#endif/ CChildViewCChildView:CChildView()CChildView:CChildView()BEGIN_MESSAGE_MAP(CChildView, CWnd)ON_WM_PAINT()ON_WM_CREATE()ON_COMMAND(ID_DRAW_PIC, &CChildView:OnDrawPic)END_MESSAGE_MAP()/ CChildView 消息处理程序BOOL CChildView:PreCreateWindow(CREATESTRUCT& c
3、s) if (!CWnd:PreCreateWindow(cs)return FALSE;cs.dwExStyle |= WS_EX_CLIENTEDGE;cs.style &= WS_BORDER;cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, :LoadCursor(NULL, IDC_ARROW), reinterpret_cast(COLOR_WINDOW+1), NULL);return TRUE;void CChildView:OnPaint() CPaintDC dc(this); / 用于
4、绘制的设备上下文/ TODO: 在此处添加消息处理程序代码DrawGraph();/ 不要为绘制消息而调用CWnd:OnPaint()void CChildView:ReadPoint()/点表P0.x = 50; P0.y = 100;P1.x = -150;P1.y = 300;P2.x = -250;P2.y = 50;P3.x = -150;P3.y = -250;P4.x = 0; P4.y = -50;P5.x = 100; P5.y = -250;P6.x = 300; P6.y = 150;void CChildView:DrawPolygon(CDC *pDC)/绘制多边形边
5、界CLine *line = new CLine;CP2 t;for(int i = 0; i MoveTo(pDC, Pi);t = Pi;elseline-LineTo(pDC, Pi);line-LineTo(pDC, t);/闭合多边形delete line;void CChildView:DrawGraph()/绘制图形CRect rect; /定义客户区GetClientRect(&rect); /获得客户区的大小CDC *pDC = GetDC();/定义设备上下文指针 pDC-SetMapMode(MM_ANISOTROPIC);/自定义坐标系pDC-SetWindowExt(
6、rect.Width(), rect.Height();/设置窗口比例pDC-SetViewportExt(rect.Width(), -rect.Height();/设置视区比例,且x轴水平向右,y轴垂直向上pDC-SetViewportOrg(rect.Width() / 2, rect.Height() / 2);/设置客户区中心为坐标系原点rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);/矩形与客户区重合if(!bFill)DrawPolygon(pDC);/绘制多边形elseFillPolygon(pDC);/填充多边形R
7、eleaseDC(pDC);/释放DCvoid CChildView:FillPolygon(CDC *pDC)/填充多边形for(int i = 0; i SetPoint(P1, 7);/初始化Fill对象fill-CreateBucket();/建立桶表fill-CreateEdge();/建立边表 fill-Gouraud(pDC);/填充多边形delete fill;/撤销内存int CChildView:OnCreate(LPCREATESTRUCT lpCreateStruct)if (CWnd:OnCreate(lpCreateStruct) = -1)return -1;/
8、TODO: 在此添加您专用的创建代码bFill = FALSE;ReadPoint();return 0;void CChildView:OnDrawPic()/ TODO: 在此添加命令处理程序代码COLORREF GetClr = RGB(0, 0, 0);/调色板颜色CColorDialog ccd(GetClr, CC_SOLIDCOLOR);if(IDOK = ccd.DoModal()/调用颜色对话框选取填充色GetClr = ccd.GetColor();elsereturn;bRed = GetRValue(GetClr);/获取红色分量bGreen = GetGValue(G
9、etClr);/获取绿色分量bBlue = GetBValue(GetClr);/获取蓝色分量bFill = TRUE;Invalidate(); 2使用MFC技术实现多边形边缘填充算法,参考界面效果如下:/ demoView.cpp : CdemoView 类的实现#include stdafx.h#include demo.h#include demoDoc.h#include demoView.h#include #define Round(d) int(floor(d+0.5)/四舍五入宏定义#ifdef _DEBUG#define new DEBUG_NEW#endif/ Cdemo
10、ViewIMPLEMENT_DYNCREATE(CdemoView, CView)BEGIN_MESSAGE_MAP(CdemoView, CView)/ 标准打印命令ON_COMMAND(ID_FILE_PRINT, &CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CdemoView:OnFilePrintPreview)ON_COMMAND(ID_DRAW_PIC, &CdemoView:OnDrawPic)END_MESSAG
11、E_MAP()/ CdemoView 构造/析构CdemoView:CdemoView()/ TODO: 在此处添加构造代码CdemoView:CdemoView()BOOL CdemoView:PreCreateWindow(CREATESTRUCT& cs)/ TODO: 在此处通过修改/ CREATESTRUCT cs 来修改窗口类或样式return CView:PreCreateWindow(cs);/ CdemoView 绘制void CdemoView:OnDraw(CDC* /*pDC*/)CdemoDoc* pDoc = GetDocument();ASSERT_VALID(p
12、Doc);if (!pDoc)return;/ TODO: 在此处为本机数据添加绘制代码DrawGraph();/ CdemoView 打印void CdemoView:OnFilePrintPreview()AFXPrintPreview(this);BOOL CdemoView:OnPreparePrinting(CPrintInfo* pInfo)/ 默认准备return DoPreparePrinting(pInfo);void CdemoView:OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)/ TODO: 添加额外的打印前进
13、行的初始化过程void CdemoView:OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)/ TODO: 添加打印后进行的清理过程void CdemoView:OnRButtonUp(UINT nFlags, CPoint point)ClientToScreen(&point);OnContextMenu(this, point);void CdemoView:OnContextMenu(CWnd* pWnd, CPoint point)theApp.GetContextMenuManager()-ShowPopupMenu(IDR_PO
14、PUP_EDIT, point.x, point.y, this, TRUE);void CdemoView:ReadPoint()/点表P0.x = 50; P0.y = 100;P1.x = -150;P1.y = 300;P2.x = -250;P2.y = 50;P3.x = -150;P3.y = -250;P4.x = 0; P4.y = -50;P5.x = 100; P5.y = -250;P6.x = 300; P6.y = 150;void CdemoView:DrawPolygon(CDC *pDC) for(int i = 0; i MaxX)MaxX = Pi.x;i
15、f(Pi.x MaxY)MaxY = Pi.y;if(Pi.y MinY)MinY = Pi.y;CLine *line = new CLine;CP2 t;for(int i = 0; i MoveTo(pDC, Pi);t = Pi;elseline-LineTo(pDC, Pi);line-LineTo(pDC, t);/闭合多边形line-MoveTo(pDC, CP2(MinX, MinY);/绘制包围盒line-LineTo(pDC, CP2(MinX, MaxY);line-LineTo(pDC, CP2(MaxX, MaxY);line-LineTo(pDC, CP2(MaxX
16、, MinY);line-LineTo(pDC, CP2(MinX, MinY);delete line;void CdemoView:FillPolygon(CDC *pDC) COLORREF BClr = RGB(255, 255, 255);/背景色COLORREF FClr = GetClr;/填充色int ymin, ymax;/边的最小y值与最大y值double x, y, k;/x,y当前点,k斜率的倒数for(int i = 0; i 7; i+)/循环多边形所有边int j = (i + 1) % 7;k = (Pi.x - Pj.x) / (Pi.y - Pj.y);/计
17、算/kif(Pi.y Pj.y)/得到每条边y的最大值与最小值ymin = Round(Pi.y);ymax = Round(Pj.y);x = Pi.x;/得到x|yminelseymin = Round(Pj.y);ymax = Round(Pi.y);x = Pj.x;for(y = ymin; y ymax; y+)/沿每一条边循环扫描线for(int m = Round(x); m GetPixel(m, Round(y)/如果是填充色pDC-SetPixelV(m, Round(y), BClr);/置为背景色elsepDC-SetPixelV(m, Round(y), FClr)
18、;/置为填充色x += k;/计算下一条扫描线的x起点坐标void CdemoView:DrawGraph()/绘制图形CRect rect;/定义客户区GetClientRect(&rect);/获得客户区的大小CDC *pDC = GetDC();/定义设备上下文指针 pDC-SetMapMode(MM_ANISOTROPIC);/自定义坐标系pDC-SetWindowExt(rect.Width(), rect.Height();/设置窗口比例pDC-SetViewportExt(rect.Width(), -rect.Height();/设置视区比例,且x轴水平向右,y轴垂直向上pDC
19、-SetViewportOrg(rect.Width() / 2, rect.Height() / 2);/设置客户区中心为坐标系原点rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);/矩形与客户区重合if(!bFill)DrawPolygon(pDC);/绘制多边形elseFillPolygon(pDC);/填充多边形ReleaseDC(pDC);/释放DC/ CdemoView 诊断#ifdef _DEBUGvoid CdemoView:AssertValid() constCView:AssertValid();void Cde
20、moView:Dump(CDumpContext& dc) constCView:Dump(dc);CdemoDoc* CdemoView:GetDocument() const / 非调试版本是内联的ASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CdemoDoc);return (CdemoDoc*)m_pDocument;#endif /_DEBUG/ CdemoView 消息处理程序void CdemoView:OnInitialUpdate()CView:OnInitialUpdate();/ TODO: 在此添加专用代码和/或调用基类bFill
21、= FALSE;ReadPoint();GetClr = RGB(0,0,0);MinX = MaxX = P0.x;MinY = MaxY = P0.y;void CdemoView:OnDrawPic()/ TODO: 在此添加命令处理程序代码CColorDialog ccd(GetClr, CC_SOLIDCOLOR);if(IDOK = ccd.DoModal()/调用颜色对话框选取填充色GetClr = ccd.GetColor();elsereturn;bFill = TRUE;Invalidate(FALSE); 3.使用MFC技术实现种子填充算法,参考界面效果如下:/ demo
22、View.cpp : CdemoView 类的实现#include stdafx.h#include demo.h#include demoDoc.h#include demoView.h#include #define Round(d) int(floor(d+0.5)/四舍五入宏定义#ifdef _DEBUG#define new DEBUG_NEW#endif/ CdemoViewIMPLEMENT_DYNCREATE(CdemoView, CView)BEGIN_MESSAGE_MAP(CdemoView, CView)/ 标准打印命令ON_COMMAND(ID_FILE_PRINT,
23、 &CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CdemoView:OnFilePrintPreview)ON_WM_LBUTTONDOWN()ON_COMMAND(ID_DRAW_PIC, &CdemoView:OnDrawPic)END_MESSAGE_MAP()/ CdemoView 构造/析构CdemoView:CdemoView()/ TODO: 在此处添加构造代码bFill = FALSE;SeedClr = RGB(
24、255, 0, 0);CdemoView:CdemoView()BOOL CdemoView:PreCreateWindow(CREATESTRUCT& cs)/ TODO: 在此处通过修改/ CREATESTRUCT cs 来修改窗口类或样式return CView:PreCreateWindow(cs);/ CdemoView 绘制void CdemoView:OnDraw(CDC* /*pDC*/)CdemoDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;/ TODO: 在此处为本机数据添加绘制代码DrawGra
25、ph();/ CdemoView 打印void CdemoView:OnFilePrintPreview()AFXPrintPreview(this);BOOL CdemoView:OnPreparePrinting(CPrintInfo* pInfo)/ 默认准备return DoPreparePrinting(pInfo);void CdemoView:OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)/ TODO: 添加额外的打印前进行的初始化过程void CdemoView:OnEndPrinting(CDC* /*pDC*/, C
26、PrintInfo* /*pInfo*/)/ TODO: 添加打印后进行的清理过程void CdemoView:OnRButtonUp(UINT nFlags, CPoint point)ClientToScreen(&point);OnContextMenu(this, point);void CdemoView:OnContextMenu(CWnd* pWnd, CPoint point)theApp.GetContextMenuManager()-ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);/ CdemoView
27、 诊断#ifdef _DEBUGvoid CdemoView:AssertValid() constCView:AssertValid();void CdemoView:Dump(CDumpContext& dc) constCView:Dump(dc);CdemoDoc* CdemoView:GetDocument() const / 非调试版本是内联的ASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CdemoDoc);return (CdemoDoc*)m_pDocument;#endif /_DEBUGvoid CdemoView:DrawGraph(
28、)/绘制图形CDC *pDC = GetDC();/定义设备上下文指针GetClientRect(&rect);/获得客户区的大小pDC-SetMapMode(MM_ANISOTROPIC);/自定义坐标系pDC-SetWindowExt(rect.Width(), rect.Height();/设置窗口比例pDC-SetViewportExt(rect.Width(), -rect.Height();/设置视区比例,且x轴水平向右,y轴垂直向上pDC-SetViewportOrg(rect.Width() / 2, rect.Height() / 2);/设置客户区中心为坐标系原点rect.
29、OffsetRect(-rect.Width() / 2, -rect.Height() / 2);/矩形与客户区重合CDC MemDC;/内存DCCBitmap NewBitmap, *pOldBitmap;/内存中承载图像的位图MemDC.CreateCompatibleDC(pDC);/建立与屏幕pDC兼容的MemDC NewBitmap.LoadBitmap(IDB_BITMAP1);/导入空心汉字位图pOldBitmap = MemDC.SelectObject(&NewBitmap);/将兼容位图选入MemDC MemDC.SetMapMode(MM_ANISOTROPIC);/M
30、emDC自定义坐标系MemDC.SetWindowExt(rect.Width(), rect.Height();MemDC.SetViewportExt(rect.Width(), -rect.Height();MemDC.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);pDC-BitBlt(-rect.Width() / 2, -rect.Height() / 2, rect.Width(), rect.Height(), &MemDC, -rect.Width() / 2, -rect.Height() / 2, SRCCOPY);
31、/将内存位图拷贝到屏幕if(bFill)CharFill(pDC);/填充空心汉字MemDC.SelectObject(pOldBitmap);/恢复位图NewBitmap.DeleteObject();/删除位图MemDC.DeleteDC();/删除MemDCReleaseDC(pDC);/释放DCvoid CdemoView:CharFill(CDC *pDC)/文字填充函数COLORREF BoundaryClr = RGB(0,0,0);/边界色BOOL bSpanFill;pHead = new CStackNode;/建立栈结点pHead-pNext = NULL;/栈头结点的指
32、针域总为空Push(Seed);/种子像素入栈int x, y, x0 = Round(Seed.x), y0 = Round(Seed.y);/x,y用于判断种子与图形的位置关系x = x0 - 1;while(pDC-GetPixel(x, y0) != BoundaryClr & pDC-GetPixel(x, y0) != SeedClr )/左方判断x-;if(x GetPixel(x0, y) != BoundaryClr & pDC-GetPixel(x0, y) != SeedClr)/上方判断y+;if(y = rect.Height() / 2)/到达客户区最上端Messa
33、geBox(L种子不在图形之内, L警告);return;x = x0 + 1;while(pDC-GetPixel(x, y0) != BoundaryClr & pDC-GetPixel(x, y0) != SeedClr)/右方判断x+;if(x = rect.Width() / 2)/到达客户区最右端MessageBox(L种子不在图形之内, L警告);return;y = y0 - 1;while(pDC-GetPixel(x0, y) != BoundaryClr & pDC-GetPixel(x0, y) != SeedClr)/下方判断y-;if(y pNext != NULL
34、)/如果栈不为空Pop(PopPoint);if(pDC-GetPixel(Round(PopPoint.x), Round(PopPoint.y) = SeedClr)continue;/ 分别向左和向右填充扫描线PointTemp = PopPoint;while(pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != BoundaryClr & pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != SeedClr)pDC-SetPixelV(Round(PointTemp.x),
35、 Round(PointTemp.y), SeedClr);PointTemp.x+;xright = PointTemp.x - 1;PointTemp.x = PopPoint.x - 1;while(pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != BoundaryClr & pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != SeedClr)pDC-SetPixelV(Round(PointTemp.x), Round(PointTemp.y), SeedClr);Po
36、intTemp.x-;xleft=PointTemp.x + 1;/处理上一条扫描线PointTemp.x = xleft;PointTemp.y = PointTemp.y + 1;while(PointTemp.x GetPixel(Round(PointTemp.x), Round(PointTemp.y) != BoundaryClr & pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != SeedClr)bSpanFill = TRUE;PointTemp.x+;if(bSpanFill)if(PointTemp.x = xr
37、ight & pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != BoundaryClr & pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) != SeedClr)PopPoint = PointTemp;elsePopPoint.x = PointTemp.x - 1; PopPoint.y = PointTemp.y;Push(PopPoint);bSpanFill = FALSE;while(pDC-GetPixel(Round(PointTemp.x), Round(PointTemp.y) = BoundaryClr & PointTemp.x GetPixel(Round(PointTemp.x), Round(PointTemp.y) = SeedClr & PointTemp.x xright) PointTemp.x+;/处理下一条扫描线PointTemp.x = xleft;PointTemp.y = PointTemp.y - 2;while(PointTemp.x GetPixel(Round(PointTemp.x), Round(PointTemp.y) != BoundaryClr & pDC-GetPi