数学上,理想的直线是由无数个点构成的集合,没有宽度。计算机绘制直线是在显示器所给定的有限个像素组成的矩阵中,确定最佳逼近该直线的一组像素,并且按扫描线顺序,对这些像素进行写操作,实现显示器绘制直线,即通常所用说直线的扫描转换,或称直线光栅化.
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)>=0) {
//以xa,ya为端点,从端点步进画线,步长1像素
for (x=xa;x<=xb;x++) {pDC->SetPixel (x,
int(y+k),c); y=(
int)(y+k);} }
if(abs(k)>=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>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<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为下一个像素;