计算机图形学
- 格式:doc
- 大小:676.11 KB
- 文档页数:24
第1页 共24页 直线中点Bresenham算法
一、 实验内容
给出坐标点,利用Bresenham将其绘画成一条直线。
二、 绘图的函数
void CTestView::Mbline() //Bresenham函数
void CTestView::OnMENUMbline(); //菜单函数
三、程序设计说明及源代码:
1、绘制直线的算法
1)、Bresenham 函数 (直线的扫描转换就是在屏幕像素点阵中用指定颜色点亮最佳趋近于理想直线的像素点集的过程,最著名的的Bresenham算法就是其中之一。Bresenham算法原理:每次在主位移方向上走一步,另一个方向上走不走取决于重点偏差判别式的值。本程序以X方向作为主位移方向)
void CTestView::Mbline()//Bresenham函数
{
CClientDC dc(this); //使用这种方式的菜单调用方式在VC++客户区绘制图形
COLORREF rgb=RGB(0,0,255);//定义直线颜色蓝色,分别设置R,G,B参数值,改变线条颜色
double x,y,d,k; //d=F(Xm,ym)=F(Xi+1,yi+0.5)=yi+0.5-k(Xi+1)-b构造中点判别式
x=x0;y=y0;k=(y1-y0)/(x1-x0)//起点及函数的斜率计算公式
for(x=x0;x<=x1;x++)
{
Sleep(20);//延时函数,每20毫秒画出一个像素点
dc.SetPixel(ROUND(x),ROUND(y),rgb);//设置像素点的坐标及颜色
if(d<0) //(中点在直线下方)
{
y++;
d+=1-k;
}
if(d>0) //(中点在直线上方)
{
y--;
d+=1-k;
}
Else //(中点在直线上)
d-=k;
}
2)、void CTestView::OnMENUMbline() //菜单函数
{
InputDlg dlg;
if(dlg.DoModal()==IDOK)
{ 第2页 共24页 x0=dlg.m_x0;
y0=dlg.m_y0;
x1=dlg.m_x1;
y1=dlg.m_y1;
}
AfxGetMainWnd()->SetWindowText("案例2:直线中点Bresenham算法");(线运行出来后边框显示 见图)
RedrawWindow();
Mbline();
}
四、 截图
五、 实验总结:
直线,圆和椭圆是图形设计的最基本图形。通过本次实验,我们了解了Bresenham函数,在以后利用Bresenham函数设计那些基本图形。
第3页 共24页 AET多边形有效边表填充算法
一、 实验内容
自己给出7个顶点(扩充后可以自己增加顶点和删除顶点),利用绘制多边形程序作出多边形,再利用AET函数对图形进行填充。并全面掌握ET函数。
二、 关于绘制图形的函数:
void CTestView::CreatBucket()//建立桶结点
void CTestView::Et()//构造边表
void CTestView::AddEdge(AET *NewEdge)//插入临时边表
void CTestView::EdgeOrder()//对边表进行排序
void CTestView::PolygonFill()//多边形填充
void LineFill();//用扫描线算法填充多边形
三、程序设计说明及部分源代码:
CTestView::CTestView()
{
// TODO: add construction code here//设置多边形的5个顶点
Point[0]=CPoint(300,175); //P0顶点数组的定义位于TestView.h头文件中
Point[1]=CPoint(250,300); //P1
Point[2]=CPoint(100,300); //P2
Point[3]=CPoint(225,385); //P3
Point[4]=CPoint(150,550); //P4
Point[5]=CPoint(300,450); //P5
Point[6]=CPoint(450,550); //P6
Point[7]=CPoint(375,385); //P7
Point[8]=CPoint(500,300); //P8
Point[9]=CPoint(350,300); //P9
//Point[7]=CPoint(900,450); //P7 增加节点需要增加顶点显示的个数,闭合多边形定点数 相关数据在TestView.h头文件中(number,point[])更改 修改线条定点与显示定点必须对应···}
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->Polygon(Point,10);//绘制多边形 绘制多边形的函数 point表面多边形顶点数组中每一个定点对是一个point结构,有十个顶点
//输出多边形的顶点编号
pDC->TextOut(290,160,"P0"); //文本输出函数,(X,y坐标)加上Cstring对象
pDC->TextOut(235,280,"P1");
pDC->TextOut(80,295,"P2");
pDC->TextOut(200,380,"P3"); 第4页 共24页 pDC->TextOut(140,555,"P4");
pDC->TextOut(295,460,"P5");
pDC->TextOut(450,550,"P6");
pDC->TextOut(385,385,"P7");
pDC->TextOut(500,300,"P8");
pDC->TextOut(350,280,"P9");
}
void CTestView::CreatBucket()//建立桶结点 //桶的数据结构定义在Bucket.h头文件中
CreatBucket()建立桶节点桶在TestView.h头文件中
{
int ScanMin,ScanMax;//确定扫描线的最小值和最大值 扫描线的开始扫描位置与结束扫描位置
ScanMax=ScanMin=Point[0].y;
for(int i=1;i { if(Point[i].y { ScanMin=Point[i].y;//问题3:扫描线的最小值 } if(Point[i].y>ScanMax) { ScanMax=Point[i].y;//问题4:扫描线的最大值 } } for(i=ScanMin;i<=ScanMax;i++)//建立桶结点 { if(ScanMin==i)//桶头结点 { HeadB=new Bucket;//建立桶的头结点 CurrentB=HeadB;//CurrentB为Bucket当前结点指针 CurrentB->ScanLine=ScanMin; //扫描线定义在桶的数据结构中 CurrentB->p=NULL;//没有连接边链表 (*p桶上的边表指针) CurrentB->next=NULL; } else//建立桶的其它结点 { CurrentB->next=new Bucket; //新建一个桶结点 CurrentB=CurrentB->next; //使CurrentB指向新建的桶结点 CurrentB->ScanLine=i; CurrentB->p=NULL; //没有连接边链表 CurrentB->next=NULL; } } 第5页 共24页 } void CTestView::Et()//构造边表 有效边表的数据结构定义在AET.h中 { //问题6:全面掌握Et函数 for(int i=0;i { CurrentB=HeadB;//从桶链表的头结点开始循环 int j=i+1;//边的第二个顶点,Point[i]和Point[j]构成边 if(j==Number) j=0;//保证多边形的闭合 if(Point[j].y>Point[i].y)//终点比起点高 { while(CurrentB->ScanLine!=Point[i].y)//在桶内寻找该边的yMin { CurrentB=CurrentB->next;//移到下一个桶结点 } E[i].x=Point[i].x;//计算AET表的值 有效边表节点相关的都定义在TestView.h头文件中 E[i].yMax=Point[j].y; E[i].k=double((Point[j].x-Point[i].x))/(Point[j].y-Point[i].y);//代表1/k E[i].next=NULL; //有效边表的的建立需要三个参数,x,ymax以及1/k. CurrentE=CurrentB->p;//获得桶上链接边表的地址 if(CurrentB->p==NULL)//当前桶结点上没有链接边结点 { CurrentE=&E[i];//赋边的起始地址 CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中 } else { while(CurrentE->next!=NULL)//如果当前边已连有边结点 { CurrentE=CurrentE->next;//移动指针到当前边的最后一个边节点 } CurrentE->next=&E[i];//把当前边接上去 } } if(Point[j].y { while(CurrentB->ScanLine!=Point[j].y) { CurrentB=CurrentB->next; } E[i].x=Point[j].x; E[i].yMax=Point[i].y; E[i].k=double((Point[i].x-Point[j].x))/(Point[i].y-Point[j].y);