您好,欢迎来到尔游网。
搜索
您的当前位置:首页计算机图形学实验二

计算机图形学实验二

来源:尔游网
实 验 报 告 课程名称 姓 名 实验名称 班级 学号 实验日期 实验成绩 交互式绘制多边形 太原工业学院

实验目的实 验 环 境 基本要求: 实 验 内 容 实 验 步 骤 利用有效边表填充算法,编程实现多边形的填充。 Visual Studio 2010 1. 了解有效边表和边表的数据结构; 2. 掌握边界像素的处理原则; 3. 掌握动态链表排序算法; 4. 使用鼠标绘制多边形,右键实现多边形的填充; 实验拓展:绘制颜色渐变的三角形和四边形。 问题分析和算法描述: 有效边表填充算法通过维护边表和有效边表,避开了扫描线与多边形所有边求交的复杂运算。填充原理是按照扫描线从小到大的移动顺序,计算当前扫描线与有效边的交点,然后把这些交点按x值递增的顺序进行排序、配对,以确定填充区间,最后用指定颜色填充区间内的所有像素,即完成填充工作。 核心代码: (1)绘制多边形以及编写右键填充: void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//左键按下函数 { // TODO: Add your message handler code here and/or call default if(Flag==TRUE) { if(Number<50) { LBDown=TRUE; p[Number]=point; if(!Number) { Number++; }

Number++; } } CView::OnLButtonDown(nFlags, point); } void CTestView::OnMouseMove(UINT nFlags, CPoint point)//鼠标移动函数 { // TODO: Add your message handler code here and/or call default if(Arrow) ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); else ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS)); CString Str;//状态栏显示鼠标位置 CMainFrame *pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;//包含MainFrm.h头文件 CStatusBar *pStatus=&pFrame->m_wndStatusBar;//需要将m_wndStatusBar属性修改为公有 if(pStatus) { Str.Format(\"%d,%d\ pStatus->SetPaneText(2,Str);//状态栏显示鼠标光标位置值 } if(LBDown) { p[Number-1]=point; if(nFlags==MK_SHIFT)//约束:测试按下了Shift键 { if(abs(p[Number-1].x-p[Number-2].x)>=abs(p[Number-1].y-p[Number-2].y)) { p[Number-1].y=p[Number-2].y;//x方向的垂线 } else { p[Number-1].x=p[Number-2].x;//y方向的垂线 } } } if(Number-1>=3) { if((abs(p[Number-1].x-p[0].x)<=5) && (abs(p[Number-1].y-p[0].y)<=5))//引力域:边长为10的正方形 { p[Number-1]=p[0]; Arrow=TRUE; LBDown=FALSE; MState=TRUE; } } Invalidate(FALSE); CView::OnMouseMove(nFlags, point); } void CTestView::OnRButtonDown(UINT nFlags, CPoint point)//右键按下函数 { // TODO: Add your message handler code here and/or call default Arrow=TRUE; LBDown=FALSE; Flag=FALSE; MState=TRUE; CTestView::OnMENUFillPolygon(); CView::OnRButtonDown(nFlags, point); } (2)填充函数 void CTestView::OnMENUFillPolygon()//填充菜单操作函数 { // TODO: Add your command handler code here COLORREF FColor;//填充颜色 CColorDialog ccd(RGB(0,0,255)); if(ccd.DoModal()==IDOK) { ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT)); FColor=ccd.GetColor(); CPoint BPoint,EPoint;//边的起点和终点 long MaxX=p[0].x;//多边形的x坐标最大值 for(long Num=0;NumMaxX) MaxX=EPoint.x; } for(Num=0;NumEPoint.y)//确保起点的y值小于终点的y值 { CPoint t;//临时对象 t=BPoint; BPoint=EPoint; EPoint=t; } double k=double(BPoint.x-EPoint.x)/(BPoint.y-EPoint.y);//计算1/k for(long y=BPoint.y;y{ long x=ROUND(double(BPoint.x)+(double(y)-double(BPoint.y))*k);//处理一条边上各个点的x起始坐标 for(;xLoadStandardCursor(IDC_ARROW)); } } void CTestView::OnUpdateMENUFillPolygon(CCmdUI* pCmdUI)//填充菜单状态控制函数 { // TODO: Add your command update UI handler code here pCmdUI->Enable((MState)?TRUE:FALSE); } (3)人机交互 void CTestView::OnMENUDrawPolygon()//绘制菜单操作函数 { // TODO: Add your command handler code here Arrow=FALSE; Flag=TRUE; Number=0; MState=FALSE; if(FALSE==Attach) { CClientDC dc(this); Picture.CreateCompatibleDC(&dc); MessageBox(\"请使用鼠标在屏幕上绘制多边形\提示\MB_ICONINFORMATION); } CBitmap NewBitmap,*OldBitmap; NewBitmap.LoadBitmap(IDB_BITMAP2); OldBitmap=Picture.SelectObject(&NewBitmap); Attach=TRUE; Invalidate(FALSE); } 运行结果:

实验拓展:绘制颜色渐变的三角形和四边形。 void CTriangle::Draw(CDC* pDC)//画出来一个三角形 { pDC->MoveTo(point0.x,point0.y); pDC->LineTo(point1.x,point1.y); pDC->LineTo(point2.x,point2.y); pDC->LineTo(point0.x,point0.y); } void CTriangle::GouraudShader(CDC* pDC) { SortVertex();//point0点为y坐标最小的点,point1点为y坐标最大的点,point2点的y坐标位于二者之间。如果y值相同,取x最小的点 //定义三角形覆盖的扫描线条数 int nTotalScanLine = point1.y - point0.y + 1; //定义span的起点与终点数组 SpanLeft = new CPoint2[nTotalScanLine];//跨度左边数组 SpanRight = new CPoint2[nTotalScanLine];//跨度右边数组 //判断三角形与P0P1边的位置关系,0-1-2为右手系 int nDeltz = (point1.x - point0.x) * (point2.y - point1.y) - (point1.y - point0.y) * (point2.x - point1.x);//点矢量叉积的z坐标 if(nDeltz > 0)//三角形位于P0P1边的左侧 { nIndex = 0; DDA(point0, point2, TRUE); DDA(point2, point1, TRUE); nIndex = 0; DDA(point0, point1, FALSE); }

else//三角形位于P0P1边的右侧 { nIndex = 0; DDA(point0, point1, TRUE); nIndex = 0; DDA(point0, point2, FALSE); DDA(point2, point1, FALSE); } CRGBA clr; for(int y = point0.y ; y < point1.y; y++)//下闭上开 { int n = y - point0.y; for(int x = SpanLeft[n].x; x < SpanRight[n].x; x++)//左闭右开 { clr = LinearInterp(x, SpanLeft[n].x, SpanRight[n].x, SpanLeft[n].c, SpanRight[n].c); pDC->SetPixelV(x, y, RGB(clr.red * 255, clr.green * 255, clr.blue * 255)); } } if(SpanLeft) { delete []SpanLeft; SpanLeft = NULL; } if(SpanRight) { delete []SpanRight; SpanRight = NULL; } //} } void CTriangle::DDA(CPoint2 PStart, CPoint2 PEnd, BOOL bFeature) { CRGBA crColor = PStart.c; int dx = abs(PEnd.x - PStart.x); int dy = abs(PEnd.y - PStart.y); BOOL bInterChange = FALSE;//bInterChange为假,主位移方向为x方向 int e, s1, s2, temp; s1 = (PEnd.x > PStart.x) ? 1 :((PEnd.x < PStart.x) ? -1 : 0); s2 = (PEnd.y > PStart.y) ? 1 :((PEnd.y < PStart.y) ? -1 : 0);

if(dy > dx)//bInterChange为真,主位移方向为y方向 { temp = dx; dx = dy; dy = temp; bInterChange = TRUE; } e = -dx; int x = PStart.x , y = PStart.y; for(int i = 0;i < dx; i++) { if(bFeature) SpanLeft[nIndex] = CPoint2(x, y, crColor); else SpanRight[nIndex] = CPoint2(x, y, crColor); if(bInterChange) { y += s2; crColor = LinearInterp(y, PStart.y, PEnd.y, PStart.c, PEnd.c); if(bFeature) SpanLeft[++nIndex] = CPoint2(x, y, crColor); else SpanRight[++nIndex] = CPoint2(x, y, crColor); } else { x += s1; crColor = LinearInterp(x, PStart.x, PEnd.x, PStart.c, PEnd.c); } e += 2 * dy; if(e >= 0) { if(bInterChange) { x += s1; crColor = LinearInterp(y, PStart.y, PEnd.y, PStart.c, PEnd.c); } else { y += s2; crColor = LinearInterp(x, PStart.x, PEnd.x, PStart.c, PEnd.c); if(bFeature)

SpanLeft[++nIndex] = CPoint2(x, y, crColor); else SpanRight[++nIndex] = CPoint2(x, y, crColor); } e -= 2 * dx; } } } void CTriangle::SortVertex(void)//给三个点进行排序,最终给定三角形的0,1,2顶点对应的point { CPoint2 pt[3]; pt[0] = point0; pt[1] = point1; pt[2] = point2; for(int i = 0; i < 2; i++) { for(int j = i + 1;j < 3; j++) { int k = i; if(pt[k].y >= pt[j].y) k = j; if(k == j) { CPoint2 ptTemp = pt[i]; pt[i] = pt[k]; pt[k] = ptTemp; } } } point0 = pt[0]; point1 = pt[2]; point2 = pt[1]; } CRGBA CTriangle::LinearInterp(double t, double mStart, double mEnd, CRGBA cStart, CRGBA cEnd)//颜色线性插值 { CRGBA color; color = (t - mEnd) / (mStart - mEnd) * cStart + (t - mStart) / (mEnd - mStart) * cEnd; return color; }

调 试 过 程 问题:一开始右键并没有填充的功能。 解决:在右键按下的函数里面调用填充函数后便实现了。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- axer.cn 版权所有 湘ICP备2023022495号-12

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务