中点算法用整数加法及比较代替了DDA 中的浮点数加法及取整运算,效率大大提高。假设直线的起点、终点分别为:(X 0 ,Y 0 ),(X 1 ,Y 1 ),直线将二维空间划分为三个区域: 直线方程: F(x,y)=ax+by+c=0 其中: a=-(y1-y0),b=(x1-x0),c=-B(x1-x0) 如 F(x,y)=0, 则(x,y) 在直线上 如 F(x,y)<0, 则(x,y)在直线下方 如 F(x,y)>0, 则(x,y)在直线上方 因此,可将中点 M 的坐标(Xp+1,Yp+0.5)代入直线方程,并判断其符号即可确定象素点的选取。
定义决策变量: d= F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+c 如果 d>0,则M在理想直线上方,选正右方P2点; 如果 d<0,则 M 在理想直线下方,选右上方 P1 点; 如果 d=0,则 M 在理想直线上,选 P1/ P2 点。
由于 d 是 xi 和 yi 的线性函数,可采用增量计算提高运算效率。
1.如由 pi 点确定在是正右方 P2 点(d>0).,则新的中点 M 仅在 x 方向加 1,新的 d 值为: d new =F(xi+2,yi+0.5)=a(xi+2)+b(yi+0.5)+c 而 d old =F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+c y x F(x,y)=0F(x,y)>0F(x,y)<0(x1,y1) (x0,y0) x Pi=(xi, yi) M Q P1 p2 y
d new =d old +a= d old -dy 2.如由 pi 点确定是右上方 P1 点(d<0),则新的中点 M 在 x 和 y 方向都增加 1,新的 d 值为 d new =F(xi+2,yi+1.5)=a(xi+2)+b(yi+1.5)+c 而 d old =F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+c d new =d old +a+b= d old -dy+dx 在每一步中,根据前一次第二迭中计算出的 d 值的符号,在正右方和右上方的两个点中进行选择。d 的初始值: d0=F(x0+1,y0+0.5)=F(x0,y0)+a+b/2=a+b/2=-dy+dx/2 F(x0,y0)=0,(x0,y0)在直线上。
为了消除 d 的分数,重新定义 F(x,y)=2(ax+by+c) 则每一步需要计算的 d new 是简单的整数加法 dy=y1-y0,dx=x1-x0 d0=-2dy+dx d new =d old -2*dy,当 d old >=0 d new =d old -2(dy-dx),当 d old <0 Bresenham 画线算法 :
算法原理:
与 DDA 算法相 似 ,Bresenham 画线算法也要在每列象素中找到与理想直线最逼近的象素点。
根 据 直 线的斜率来确定变量在 x 或 y 方向递增一个单位。另一个方向 y 或 x 的增量为 0 或 1,它取决于实际直线与最接近网格点位置的距离。这一距离称为误差。算法的巧妙构思,使每次只需检查误差项(增量)的符号即可。
定义决策变量:
d = d+k (0=0.5)
当 d>1 时,让 d=d-1,以保证 0<=d<1,d 0 =0 令 e = d-0.5 (0=0) 当 e >0 时, 让 e = e- 1,(重新初始化误差项)由于算法只用到误差项的符号,为了改用整数以避免除法,可以作如下替换: e = 2*e*dx 定义决策变量 e = 2*e*dx ,则 e 0 = -dx , e=e +2*dy 则下一点为: (x+1,y),( e <0) (x+1,y+1)( e >=0) 当 e >0 时, 让 e = e - dx , (重新初始化误差项) 实验环境 硬件平台:PC 软件(推荐):Windows 平台,Visual C++,matlab 实验步骤 1. 掌握算法原理; 2. 依据算法,编写源程序并进行调试; 3. 对运行结果进行保存与分析; 4. 把源程序以文件的形式提交; 5. 按格式书写实验报告。
实验内容 实验源程序如下:
void CLineDlg::OnRadioPlus() //缺省选择 { // TODO: Add your control notification handler code here Algorithm=0;//算法选择 } void CLineDlg::OnRadio() {
// TODO: Add your control notification handler code here Algorithm=2; } void CLineDlg::OnRadio1() { // TODO: Add your control notification handler code here Algorithm=1; } void CLineDlg::OnLinedraw() { // TODO: Add your control notification handler code here CWnd* pWnd=GetDlgItem(IDC_STATIC); CDC* pControlDC=pWnd->GetDC(); pWnd->Invalidate(); pWnd->UpdateWindow(); pControlDC->SetViewportOrg(0,0); pControlDC->MoveTo(0,0); pControlDC->LineTo(0,335); pControlDC->MoveTo(0,0); pControlDC->LineTo(400,0); int i,j; for(i=0;i<=400;i+=10) for(j=0;j<=335;j++) pControlDC->SetPixel(i,j,RGB(200,200,200)); for(i=0;i<=335;i+=10) for(j=0;j<=400;j++) pControlDC->SetPixel(j,i,RGB(200,200,200)); int x1,y1,x0,y0; UpdateData(true);
x1=m_x1; x0=m_x0; y1=m_y1; y0=m_y0; switch (Algorithm) { case 0: { int a,b,d1,d2,d,x,y; float dy,dx,m; dx=float(x1-x0); dy=float(y1-y0); m=dy/dx; if(m<=1) { a=y0-y1;b=x1-x0;d=2*a+b; d1=2*a;d2=2*(a+b); x=x0;y=y0; pControlDC->SetPixel(x,y,RGB(0,255,0)); while(xSetPixel(x,y,RGB(0,255,0)); } } else {
a=x0-x1;b=y1-y0;d=2*a+b; d1=2*a;d2=2*(a+b); x=y0;y=x0; pControlDC->SetPixel(x,y,RGB(0,255,0)); while(xSetPixel(y,x,RGB(0,255,0)); } } break; } case 1: { float dy,dx,m; dx=float(x1-x0); dy=float(y1-y0); m=dy/dx; if(m<=1) { int x; float y; y=float(y0); for(x=x0;x<=x1;x++) { pControlDC->SetPixel(x,(int)(y+0.5),RGB(0,0,255)); y=y+m;
} } else { int y; float x; x=float(x0); for(y=y0;y<=y1;y++) { pControlDC->SetPixel((int)(x+0.5),y,RGB(0,0,255)); x=x+1/m; } } break; } case 2: { int x,y,dx,dy,e,i; float d1y,d1x,m; d1x=float(x1-x0); d1y=float(y1-y0); m=d1y/d1x; if(m<=1) { dx=x1-x0;dy=y1-y0;e=-dx; x=x0;y=y0; for(i=0;i<=dx;i++) { pControlDC->SetPixel(x,y,RGB(255,0,0));
x++;e=e+2*dy; if(e>=0){y++;e=e-2*dx;} } } else { dx=y1-y0;dy=x1-x0;e=-dy; x=y0;y=x0; for(i=0;i<=dx;i++) { pControlDC->SetPixel(y,x,RGB(255,0,0)); x++;e=e+2*dy; if(e>=0){y++;e=e-2*dx;} } } break; } } } void CLineDlg::OnDelete() { // TODO: Add your control notification handler code here Invalidate();//清除作图区的线 }
实验结果 1.DDA 画线结果为:
2.中点画线结果为:
3.Bresenham 画线结果为:
4. 点击清除结果为:
实验总结 通过实验更加熟悉 MFC 的运用,对 DDA、中点算法和 Bresenham 算法原理有了更加清楚的了解。它们各自有自己的特点,Bresenham 算法不用计算斜率,所以不做除法;DDA 算法是浮点数运算,不易硬件实现;中点画线法只有整数运算,不含乘除法。因为基础知识不扎实,实验过程中遇到不少问题。明白要多动手实践才能学好。
指导教师意见 签名:
年 月 日