实验三计算机图形学多边形填充算法.doc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 计算机 图形学 多边形 填充 算法
- 资源描述:
-
洛阳理工学院实验报告 系别 计算机与信息工程系 班级 B120531 学号 B12053113 姓名 课程名称 计算机图形学 实验日期 2013-11-7 实验名称 多边形填充算法编程 成绩 实验目的: 熟悉多边形填充算法,掌握MFC图形编程的基本方法和调试技巧。 实验条件: 计算机;VS2008;OpenGL 实验内容: 1.使用MFC技术实现多边形有效边表填充算法,参考界面效果如下: // ChildView.cpp : CChildView 类的实现 #include "stdafx.h" #include "demo.h" #include "ChildView.h" #include <math.h> #define Round(d) int(floor(d+0.5))//四舍五入宏定义 #ifdef _DEBUG #define new DEBUG_NEW #endif // CChildView CChildView::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& cs) { 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<HBRUSH>(COLOR_WINDOW+1), NULL); return TRUE; } void CChildView::OnPaint() { CPaintDC dc(this); // 用于绘制的设备上下文 // TODO: 在此处添加消息处理程序代码 DrawGraph(); // 不要为绘制消息而调用CWnd::OnPaint() } void CChildView::ReadPoint() //点表 { P[0].x = 50; P[0].y = 100; P[1].x = -150;P[1].y = 300; P[2].x = -250;P[2].y = 50; P[3].x = -150;P[3].y = -250; P[4].x = 0; P[4].y = -50; P[5].x = 100; P[5].y = -250; P[6].x = 300; P[6].y = 150; } void CChildView::DrawPolygon(CDC *pDC) //绘制多边形边界 { CLine *line = new CLine; CP2 t; for(int i = 0; i < 7; i++) //绘制多边形 { if(i == 0) { line->MoveTo(pDC, P[i]); t = P[i]; } else { line->LineTo(pDC, P[i]); } } line->LineTo(pDC, t); //闭合多边形 delete line; } void CChildView::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->SetViewportOrg(rect.Width() / 2, rect.Height() / 2); //设置客户区中心为坐标系原点 rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2); //矩形与客户区重合 if(!bFill) DrawPolygon(pDC); //绘制多边形 else FillPolygon(pDC); //填充多边形 ReleaseDC(pDC); //释放DC } void CChildView::FillPolygon(CDC *pDC) //填充多边形 { for(int i = 0; i < 7; i++) //转储顶点坐标,y坐标取为整数 { P1[i].x = P[i].x; P1[i].y = Round(P[i].y); P1[i].c = CRGB(bRed / 255.0, bGreen / 255.0, bBlue / 255.0); } CFill *fill = new CFill; //动态分配内存 fill->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; // 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(); else return; bRed = GetRValue(GetClr); //获取红色分量 bGreen = GetGValue(GetClr); //获取绿色分量 bBlue = GetBValue(GetClr); //获取蓝色分量 bFill = TRUE; Invalidate(); } 2.使用MFC技术实现多边形边缘填充算法,参考界面效果如下: // demoView.cpp : CdemoView 类的实现 #include "stdafx.h" #include "demo.h" #include "demoDoc.h" #include "demoView.h" #include <math.h> #define Round(d) int(floor(d+0.5))//四舍五入宏定义 #ifdef _DEBUG #define new DEBUG_NEW #endif // CdemoView IMPLEMENT_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_MESSAGE_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(pDoc); 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: 添加额外的打印前进行的初始化过程 } 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_POPUP_EDIT, point.x, point.y, this, TRUE); } void CdemoView::ReadPoint() //点表 { P[0].x = 50; P[0].y = 100; P[1].x = -150;P[1].y = 300; P[2].x = -250;P[2].y = 50; P[3].x = -150;P[3].y = -250; P[4].x = 0; P[4].y = -50; P[5].x = 100; P[5].y = -250; P[6].x = 300; P[6].y = 150; } void CdemoView::DrawPolygon(CDC *pDC) { for(int i = 0; i < 7; i++) //计算多边形边界 { if(P[i].x > MaxX) MaxX = P[i].x; if(P[i].x < MinX) MinX = P[i].x; if(P[i].y > MaxY) MaxY = P[i].y; if(P[i].y < MinY) MinY = P[i].y; } CLine *line = new CLine; CP2 t; for(int i = 0; i < 7; i++) //绘制多边形 { if(i == 0) { line->MoveTo(pDC, P[i]); t = P[i]; } else { line->LineTo(pDC, P[i]); } } 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, 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 = (P[i].x - P[j].x) / (P[i].y - P[j].y); //计算/k if(P[i].y < P[j].y) //得到每条边y的最大值与最小值 { ymin = Round(P[i].y); ymax = Round(P[j].y); x = P[i].x; //得到x|ymin } else { ymin = Round(P[j].y); ymax = Round(P[i].y); x = P[j].x; } for(y = ymin; y < ymax; y++) //沿每一条边循环扫描线 { for(int m = Round(x); m < MaxX; m++) //对每一条扫描线与边的交点的右侧像素循环 { if(FClr == pDC->GetPixel(m, Round(y))) //如果是填充色 pDC->SetPixelV(m, Round(y), BClr); //置为背景色 else pDC->SetPixelV(m, Round(y), FClr); //置为填充色 } 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->SetViewportOrg(rect.Width() / 2, rect.Height() / 2); //设置客户区中心为坐标系原点 rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2); //矩形与客户区重合 if(!bFill) DrawPolygon(pDC); //绘制多边形 else FillPolygon(pDC); //填充多边形 ReleaseDC(pDC); //释放DC } // CdemoView 诊断 #ifdef _DEBUG void CdemoView::AssertValid() const { CView::AssertValid(); } void CdemoView::Dump(CDumpContext& dc) const { CView::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 = FALSE; ReadPoint(); GetClr = RGB(0,0,0); MinX = MaxX = P[0].x; MinY = MaxY = P[0].y; } void CdemoView::OnDrawPic() { // TODO: 在此添加命令处理程序代码 CColorDialog ccd(GetClr, CC_SOLIDCOLOR); if(IDOK == ccd.DoModal()) //调用颜色对话框选取填充色 GetClr = ccd.GetColor(); else return; bFill = TRUE; Invalidate(FALSE); } 3.使用MFC技术实现种子填充算法,参考界面效果如下: // demoView.cpp : CdemoView 类的实现 #include "stdafx.h" #include "demo.h" #include "demoDoc.h" #include "demoView.h" #include <math.h> #define Round(d) int(floor(d+0.5))//四舍五入宏定义 #ifdef _DEBUG #define new DEBUG_NEW #endif // CdemoView IMPLEMENT_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_WM_LBUTTONDOWN() ON_COMMAND(ID_DRAW_PIC, &CdemoView::OnDrawPic) END_MESSAGE_MAP() // CdemoView 构造/析构 CdemoView::CdemoView() { // TODO: 在此处添加构造代码 bFill = FALSE; SeedClr = RGB(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: 在此处为本机数据添加绘制代码 DrawGraph(); } // 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*/, 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_POPUP_EDIT, point.x, point.y, this, TRUE); } // CdemoView 诊断 #ifdef _DEBUG void CdemoView::AssertValid() const { CView::AssertValid(); } void CdemoView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CdemoDoc* CdemoView::GetDocument() const // 非调试版本是内联的 { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CdemoDoc))); return (CdemoDoc*)m_pDocument; } #endif //_DEBUG void CdemoView::DrawGraph()//绘制图形 { 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.OffsetRect(-rect.Width() / 2, -rect.Height() / 2); //矩形与客户区重合 CDC MemDC;//内存DC CBitmap NewBitmap, *pOldBitmap; //内存中承载图像的位图 MemDC.CreateCompatibleDC(pDC); //建立与屏幕pDC兼容的MemDC NewBitmap.LoadBitmap(IDB_BITMAP1); //导入空心汉字位图 pOldBitmap = MemDC.SelectObject(&NewBitmap);//将兼容位图选入MemDC 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); pDC->BitBlt(-rect.Width() / 2, -rect.Height() / 2, rect.Width(), rect.Height(), &MemDC, -rect.Width() / 2, -rect.Height() / 2, SRCCOPY);//将内存位图拷贝到屏幕 if(bFill) CharFill(pDC); //填充空心汉字 MemDC.SelectObject(pOldBitmap); //恢复位图 NewBitmap.DeleteObject(); //删除位图 MemDC.DeleteDC(); //删除MemDC ReleaseDC(pDC); //释放DC } void CdemoView::CharFill(CDC *pDC) //文字填充函数 { COLORREF BoundaryClr = RGB(0,0,0); //边界色 BOOL bSpanFill; pHead = new CStackNode; //建立栈结点 pHead->pNext = NULL; //栈头结点的指针域总为空 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 <= -rect.Width() / 2) { MessageBox(L"种子不在图形之内", L"警告");//到达客户区最左端 return; } } y = y0 + 1; while(pDC->GetPixel(x0, y) != BoundaryClr && pDC->GetPixel(x0, y) != SeedClr)//上方判断 { y++; if(y >= rect.Height() / 2)//到达客户区最上端 { MessageBox(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 <= -rect.Height() / 2)//到达客户区最下端 { MessageBox(L"种子不在图形之内", L"警告"); return; } } double xleft, xright;//区间最左端与最右端像素 CP2 PopPoint, PointTemp; while(pHead->pNext != NULL)//如果栈不为空 { 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), 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); PointTemp.x--; } xleft=PointTemp.x + 1; //处理上一条扫描线 PointTemp.x = xleft; PointTemp.y = PointTemp.y + 1; while(PointTemp.x < xright) { bSpanFill = FALSE; while(pDC->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 == xright && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr) PopPoint = PointTemp; else PopPoint.x = PointTemp.x - 1; PopPoint.y = PointTemp.y; Push(PopPoint); bSpanFill = FALSE; } while((pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == BoundaryClr && PointTemp.x < xright) || (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == SeedClr && PointTemp.x < xright)) PointTemp.x++; } //处理下一条扫描线 PointTemp.x = xleft; PointTemp.y = PointTemp.y - 2; while(PointTemp.x < xright) { bSpanFill = FALSE; while(pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Ro展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




实验三计算机图形学多边形填充算法.doc



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/4232953.html