图形学-中点Bresenham算法
- 原理
- 代码
- 例子
原理
由Bresenham提出的直线生成算法的基本原理是,每次在最大位移方向上走一步,而另一个方向是走步还是不走步取决于误差项的判别。
这时直线将平面分成三个区域:对于直线上的点,F(x,y)=0;对于直线上方的点,F(x,y)>0;对于直线下方的点,F(x,y)<0,如下图所示。
首先假设0≤k≤1,由于x是最大位移方向,因此每次在x方向上加1,y方向上或加1 或加0。假定当前点是P(xi,yi),则下一个点在pu(xi+1,yi+1)与pd(xi+1,yi)中选一。以M表示pu和pd的终点即M(xi+1,yi+0.5)。又设Q是理想直线与垂直线x=xi+1的交点。显然,若M在Q的下方,则pu(xi+1,yi+1)离直线近,应取为下一个像素,否则应取Pd(xi+1,yi)。
所以如前所述,欲判断Q在M的上方还是下方,只要把M代入F(x,y),并判断它的符号即可。
如上构造判别式,当di<0时,M在直线下方,故应取Pu。当di>0时,应取正右方的Pd。当di=0时,
两者一样合适,可以随便取一个。
所以现在根据上面的判别式对误差项进行递推。
当di<0时,取右上方像素Pu,欲判断再下一个像素应该取那个应计算
此时di的增量为1-k。
当di≥0时,取右上方像素Pd,欲判断再下一个像素应该取那个应计算
下面进行di的初值计算。显然直线的第一个像素P(x0,y0)在直线上,因此响应的di的初始值计算如下
但是这其中仍然有小数,由于我们使用的只是di的符号,因此可以用2di△x摆脱小数
这样Bresenham算法的绘图过程如下
Bresenham算法对任意斜率的直线段具有通用性,对于斜率为整且大于1的直线段,只需要交换x和y之间的规则。对于负斜率,除了一个坐标递减而另一个坐标地政外,其余程序是类似的。
代码
void MidBresenhamLine(int x0, int y0, int x1, int y1, int color)
{
int dx, dy, d, UpIncre, DownIncre, x, y;
if (x0 > x1)
{
x = x1; x1 = x0; x0 = x;
y = y1; y1 = y0; y0 = y;
}
x = x0; y = y0;
dx = x1 - x0; dy = y1 - y0;
d = dx - 2 * dy;
UpIncre = 2 * dx - 2 * dy; DownIncre = -2 * dy;
COLORREF c = RGB(250, 250, 250);
while (x <= x1)
{
putpixel(x, y, c);
x++;
if (d < 0)
{
y++;
d += UpIncre;
}
else
d += DownIncre;
}
}
例子