1. 直线的扫描转换
1.1 DDA算法
增量算法,每一步都需要进行舍入取整,不利于硬件实现
使用C++代码:
void DDALine(int x0,int y0,int x1,int y1)
{
int dx,dy,epsl,k;
float x,y,xIncre,yIncre;
dx=x1-x0;
dy=y1-y0;
x=x0;
y=y0;
if(abs(dx)>abs(dy)) //abs()函数为取绝对值函数
espl=abs(dx);
else
espl=abs(dy);
xIncre=(float)dx/(float)epsl;
yIncre=(float)dy/(float)epsl;
for(k=0;k<=epsl;k++)
{
putpixel(int(x+0.5),int(y+0.5); //画点
x+=xIncre;
y+=yIncre; //寻找下一个点
}
}
1.2 中点Bresenham算法
每次在最大位移方向上走一步,另一个方向是否走步取决于误差项的判别
当0<k<1时,代码如下:
void MidBresenhamLine(int x0,int y0,int x1,int y1,int color)
{
int dx,dy,d,UpIncre,DownIncre,x,y;
if(x0<x1)
{
Swap(x0,x1);
Swap(y0,y1);
}
x=x0; y=y0;
dx=x1-x0;
dy=y1-y0;
d=dx-2*dy //消除浮点运算
UpIncre=2*dx-2*dy;
DownIncre=-2*dy;
while(x<=x1)
{
putpixel(x,y,color);
x++;
if(d<0)
{
y++;
d+=UpIncre;
}
else
d+=DownIncre;
}
}
1.3 Bresenham算法
在误差项上进行替换
仍旧是0<k<1时的代码示例:
void BresenhamLine(int x0, int y0; int x1, int y1)
{
int x, y, dx, dy, e;
dx = x1 - x0;
dy = y1 - y0;
e = -dx; x = x0; y = y0;
while (x <= x1)
{
putpixel(x, y, color);
x++;
e = e + 2 * dy;
if (e > 0)
{
y++;
e = e - 2 * dx;
}
}
}
2. 圆的扫描转换
2.1 八分法画圆
只要扫描转换圆的八分之一即可根据圆的对称性画出整个圆。
八分法画圆程序(以原点为坐标):
void Circle(int x, int y, int color)
{
putpixel(x, y, color);
putpixel(-x, y, color);
putpixel(x, -y, color);
putpixel(-x, -y, color);
putpixel(y, x, color);
putpixel(-y, x, color);
putpixel(y, -x, color);
putpixel(-y, -x, color);
}
以任意点为原点时:
void Circle(int x0,int y0,int x, int y, int color)
{
putpixel(x0+x, y0+y, color);
putpixel(x0-x, y0+y, color);
putpixel(x0+x, y0-y, color);
putpixel(x0-x, y0-y, color);
putpixel(y0+y, x0+x, color);
putpixel(y0-y, x0+x, color);
putpixel(y0+y, x0-x, color);
putpixel(y0-y, x0-x, color);
}
2.2 中点Bresenham画圆算法
步骤如下:
① 输入圆的半径R
② 计算初始值 d=1-R, x=0, y=R
③ 绘制点(x,y)及其在八分圆中的另外7个对称点
④ 判断d的符号。若d<0,则先将d更新为d+2x+3,再将(x,y)更新为(x+1,y);否则,先将d更新为d+2(x-y)+5;再将(x,y)更新为(x+1.y-1)
⑤ 当x<y时,重复步骤③和④;否则结束。
代码如下:
void MidBresenhamCircle(int r, int color)
{
int x, y, d;
x = 0; y = r; d = 1 - r;
while (x <= y) //判断是否结束
{
Circle(x, y, color);//调用八分法画圆
if (d < 0)
d += 2 * x + 3;
else
{
d += 2 * (x - y) + 5;
y--;
}
x++;
}
}
3. 椭圆的扫描转换
3.1 椭圆的中点Bresenham算法
与圆的扫描转换方法类似,但是需要判断切线的斜率
代码如下:
void Ellipse(int x, int y, int color) //四分法画椭圆
{
putpixel(x, y, color);
putpixel(-x, y, color);
putpixel(x, -y, color);
putpixel(-x, -y, color);
}
void MidBresenhamEllipse(int a, int b, int color)
{
int x, y;
float d1, d2;
x = 0; y = b;
d1 = b * b + a * a * (-b + 0.25);
Ellipse(x, y, color); //调用四分法画圆
while (b * b * (x + 1) < a * a * (y - 0.5)) //椭圆上半部分
{
if (d1 <= 0)
{
d1 += b * b * (2 * x + 3);
x++;
}
else
{
d1 += b * b * (2 * x + 3) + a * a * (-2 * y + 2);
x++;
y--;
}
Ellipse(x, y, color);
}
//椭圆的下半部分
d2 = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * (y - 1) - a * a * b * b;
while (y > 0)
{
if (d2 <= 0)
{
d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
x++;
y--;
}
else
{
d2 += a * a * (-2 * y + 3);
y--;
}
Ellipse(x, y, color);
}
}