数学上,理想的直线是由无数个点构成的集合,没有宽度。计算机绘制直线是在显示器所给定的有限个像素组成的矩阵中,确定最佳逼近该直线的一组像素,并且按扫描线顺序,对这些像素进行写操作,实现显示器绘制直线,即通常所用说直线的扫描转换,或称直线光栅化.

1.DDA 算法原理
知端点p0,p1,得知斜率,从端点步进画线,步长1像素,注意斜率大于小于1的区别

//点击"DDA算法生成直线"消息处理函数-使用DDA算法画一条直线 void CMyView::OnDdaline() { // TODO: Add your command handler code here CDC* pDC=GetDC(); //获得设备指针 int xa=100, ya=300, xb=300, yb=200,c=RGB(0,0,0); //定义直线的两端点,直线颜色 int x,y; float dx, dy, k; dx=( float)(xb-xa), dy=( float)(yb-ya); k=dy/dx, y=ya,x=xa; //直线斜率 if(abs(k)&gt;=0) { //以xa,ya为端点,从端点步进画线,步长1像素 for (x=xa;x<=xb;x++) {pDC->SetPixel (x, int(y+k),c); y=( int)(y+k);} } if(abs(k)&gt;=1) { for (y=ya;y<=yb;y++) {pDC->SetPixel ( int(x+0.5),y,c); x=( int)(x+1/k); } } ReleaseDC(pDC); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

2.中点画线法
当前像素点为 p,下一个像素点有两种选择,点 p1或 p2.M为p1与p2中点,Q 为理想直线与x=xp+1垂线的交点,当M在Q的下方,则P2应为下一个像素点;M在 Q 的上方,应取P1为下一点.

生成直线的重点划线法:M在Q下方,取上方点;M在Q上方,取下方候选点. F(x,y)=ax+by+c=0. a=y0-y1,b=x1-x0,c=x0y1-x1y0;

自己理解之后写出:

1: void CMyView::OnMline() 2: { 3: CDC *pDC=GetDC(); //获得设备指针 4: int x0=100,y0=300,x1=300,y1=200,c=RGB(0,0,0); //线段端点 5: float a=( float)(y0-y1),b=( float)(x1-x0); //以直线函数为F(x,y)=ax+by+c=0 6: float k=(-1)*(a/b); //斜率 7: int x=x0,y=y0; //直线当前点初始位置x,y 8: //开始逐步步进 1像素画点 9: while(x<=x1) 10: { 11: float xp=( float)(x+1),yp=( float)(y+(-1)*(a/b)); //步进 1像素之后理想点初始位置 12: float xm=( float)(x+1),ym=( float)(( int)yp+0.5); //中点初始位置 13: int delt=yp-ym; //理想位置-中点位置 差值 14: pDC->SetPixel(x,y,c); 15: if(delt&gt;0) 16: { 17: x++; 18: y=y+(-1)*(a/b)+1; 19: } 20: else if(delt<=0) 21: { 22: x++; 23: y=y+(-1)*(a/b); 24: } 25: } 26: ReleaseDC(pDC); 27: }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

书上代码为:

1: void CMyView::OnMline() 2: { 3: // TODO: Add your command handler code here 4: CDC* pDC=GetDC(); 5: int xa=300, ya=200, xb=450, yb=300,c=RGB(0,255,0); 6: float a, b, d1, d2, d, x, y; 7: a=ya-yb, b=xb-xa, d=2*a+b; 8: d1=2*a, d2=2* (a+b); 9: x=xa, y=ya; 10: pDC->SetPixel(x, y, c); 11: while (x<xb) 12: { if (d&lt;0) {x++, y++, d+=d2; } 13: else {x++, d+=d1;} 14: pDC->SetPixel(x, y, c); 15: } 16: ReleaseDC(pDC); 17: }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 把 M 代入 F(x,y)判断 F 的符号,可知 Q 点在中点 M 的上方还是下 方。
为此构造判别式:d=F(M)=F(xp+1, yp+0.5)=a(xp+1)+b(yp+0.5)+c
当 d<0,L(Q 点) 在 M 上方,取 P2为下一个像素;
当 d>0,L(Q 点)在 M 下方,取 P1为下一个像素;
当 d=0,选 P1或 P2均可,取 P1为下一个像素;