关于对Bresenham画线算法的理解

来源:互联网 发布:uujuly淘宝没有店了吗 编辑:程序博客网 时间:2024/05/10 10:23
  最近一段时间想理解一下Bresenham算法,总结出以下心得.

  假设线性方程:
  ax + by + c = 0 (x1 < = x  <= x2, y1 <= y <= y2)
  dx = x2 - x1
  dy = y2 - y1

  当x = x1 + 1:
  ax1 + by1 + c = 0;            (1-1)
  a(x1 + 1) + by + c = 0;     (1-2)
  从1-1和1-2可以得出, y = (  -c - a(x1+1) ) / b;
  而中点位置为 ym = y1 + 0.5.
  而
  if (y - ym >= 0) y = y1 + 1;
  else y = y1;
 
所以 Sub = y - ym = (  -c - a(x1+1) ) / b - y1 - 0.5
                      = -a/b-0.5
  刚好 -a / b =  dy / dx, 所以 Sub = y - ym = 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;}

   }

这样就优化的差不多了

 

原创粉丝点击