收藏 分销(赏)

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

上传人:可**** 文档编号:4232953 上传时间:2024-08-28 格式:DOC 页数:17 大小:125.50KB 下载积分:10 金币
下载 相关 举报
实验三计算机图形学多边形填充算法.doc_第1页
第1页 / 共17页
实验三计算机图形学多边形填充算法.doc_第2页
第2页 / 共17页


点击查看更多>>
资源描述
洛阳理工学院实验报告 系别 计算机与信息工程系 班级 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
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服