假设线性方程:
ax + by + c = 0 (x 1 < = x <= x 2, y 1 <= y <= y 2)
dx = x 2 - x 1
dy = y 2 - y 1
当x = x 1 + 1:
ax 1 + by 1 + c = 0; (1-1)
a(x 1 + 1) + by + c = 0; (1-2)
从1-1和1-2可以得出, y = ( -c - a(x1+1) ) / b;
而中点位置为 y m = y 1 + 0.5.
而
if (y - y m >= 0) y = y 1 + 1;
else y = y 1;
所以 Sub = y - y m = ( -c - a(x1+1) ) / b - y 1 - 0.5
= -a/b-0.5
刚好 -a / b = dy / dx, 所以 Sub = y - y m = dy / dx - 0.5;
好,我们现在得到了第一个邻节点,让我们来计算第二个邻节点:
1.如果第二个邻节点是第一个邻节点的右上邻接点,则
Sub2 = (-c-a(x1+2))/b - (y1+1.5) = -2a/b - 1.5
故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 1.5 - (-a/b-0.5) = -a/b - 1.代入a/b得Dsub = dy/dx -1;
2.如果第二个邻节点是第一个邻节点的右邻接点,
Sub2 = (-c-a(x1+2))/b - (y1+0.5) = -2a/b - 0.5
故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 0.5 - (-a/b-0.5) = -a/b. 代入a/b得Dsub = dy/dx;
好,现在我们来实现Bresenham算法的代码:
//Bresenham
x=x1;
y=y1;
dx = x2-x1;
dy = y2-y1;
Sub = dy/dx-0.5; // 赋初值,下个要画的点与中点的差值
DrawPixel(x, y); // 画起点
while(x<x2)
{
x++;
if(Sub > 0) // 下个要画的点为当前点的右上邻接点
{
Sub += dy/dx - 1; //下下个要画的点与中点的差值
y++; // 右上邻接点y需增1
}
else// 下个要画的点为当前点的右邻接点
{
Sub += dy/dx;
}
// 画下个点
DrawPixel(x,y);
}
这时候发现Sub起的作用纯粹为正负判断,由于除法运算比较费时,所以我们来优化一把
Sub = dy / dx - 0.5; (2 - 1)
Dsub = dy/dx -1; (2 - 2 -1)
Dsub = dy/dx ; (2 - 2 -2)
所以全部乘以2 * dx, 为2*dy - dx, 2*dy - 2*dx, 2*dy,代码我们可以这样写:
//Bresenham
x=x1;
y=y1;
dx = x2-x1;
dy = y2-y1;
Sub = 2 * dy - dx; // 赋初值,下个要画的点与中点的差值
DrawPixel(x, y); // 画起点
while(x<x2)
{
x++;
if(Sub > 0) // 下个要画的点为当前点的右上邻接点
{
Sub += 2 * dy - 2 * dx; //下下个要画的点与中点的差值
y++; // 右上邻接点y需增1
}
else// 下个要画的点为当前点的右邻接点
{
Sub += 2 * dy;
}
// 画下个点
DrawPixel(x,y);
}
现在发现还是不是很优化,来更近一步:
int x, y, dx, dy;
int k, Sub;
dx = x1-x0;
dy = y1- y0;
Sub=-dx;
x=x0;
y=y0;
for (i=0; i<dx; i++)
{
DrawPixel (x, y, color);
x++;
Sub = Sub + 2*dy;
if (Sub>=0) { y++; Sub =Sub-2*dx;}
}
这样就优化的差不多了