Bresenham 画直线算法

Bresenham's画线算法作图如下:

 Bresenham 画直线算法_第1张图片


给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。假设直线的斜率00,直线在第一象限,Bresenham算法的过程如下:
1.画起点(x1, y1).
2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。
  2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点
  2.2.否则选右下那个点。
3.画点
4.跳回第2步
5.结束
  

具体的算法如下,原理就是比较目标直线与x+1直线交点的纵坐标,哪个离交点近就去哪个

 void Bresenhamline(int x0, int y0, int x1, int y1)
{
  int x, y, dx, dy;
  float k, e;
  dx = x1 -x0;//x偏移量
  dy = y1 -y0;//y偏移量
  k = dy / dx;//斜率
  e = -0.5;
  x = x0;
  y = y0;
  for (x= x0;x < x1; x++)
  {
    printf("%d,%d\n",x,y);//需要的折线上的点
    e = e + k; 
    if (e > 0)//y超过半格就去右上的点(否则就是右下的点)
    {
      y++;
      e = e -1;
    }
  }
}


上述Bresenham算法在计算直线斜率与误差项时用到小数与除法。可以改用整数以避免除法。等式两边同时乘以2*dx, 将e统一乘以2*dx即变成了整数的Bresenhan算法了.

void DrawBresenhamline(int x0, int y0, int x1, int y1)
{ 
	int dx = x1 - x0;//x偏移量
	int dy = y1 - y0;//y偏移量
	int dx2 = dx <<1;//x偏移量乘2
	int dy2 = dy <<1;//y偏移量乘2
	int e = -dx; //e = -0.5 * 2 * dx,把e 用2 * dx* e替换
	int x = x0;//起点x坐标
	int y = y0;//起点y坐标
	for (x = x0; x < x1;x++)
	{
		printf ("%d,%d\n",x, y);
		e=e + dy2;//来自 2*e*dx= 2*e*dx + 2dy  (原来是 e = e + k)
		if (e > 0)//e是整数且大于0时表示要取右上的点(否则是右下的点) 
		{ 
		 	y++; 
			e= e - dx2;//2*e*dx = 2*e*dx - 2*dx  (原来是 e = e -1)
		}
	}
}
 

最后,包含所有象限的代码如下:

void DrawBresenhamline(int x0, int y0, int x1, int y1)
{ 
	int dx = x1 - x0;//x偏移量
	int dy = y1 - y0;//y偏移量
	int ux = dx >0 ?1:-1;//x伸展方向
	int uy = dx >0 ?1:-1;//y伸展方向
	int dx2 = dx <<1;//x偏移量乘2
	int dy2 = dy <<1;//y偏移量乘2
	if(abs(dx)>abs(dy))
	{//以x为增量方向计算
		int e = -dx; //e = -0.5 * 2 * dx,把e 用2 * dx* e替换
		int x = x0;//起点x坐标
		int y = y0;//起点y坐标
		for (x = x0; x < x1;x+=ux)
		{
			printf ("%d,%d\n",x, y);
			e=e + dy2;//来自 2*e*dx= 2*e*dx + 2dy  (原来是 e = e + k)
			if (e > 0)//e是整数且大于0时表示要取右上的点(否则是右下的点) 
			{ 
			 	y += uy; 
				e= e - dx2;//2*e*dx = 2*e*dx - 2*dx  (原来是 e = e -1)
			}
		}
	}
	else
	{//以y为增量方向计算
		int e = -dy; //e = -0.5 * 2 * dy,把e 用2 * dy* e替换
		int x = x0;//起点x坐标
		int y = y0;//起点y坐标
		for (y = y0; y < y1;y += uy)
		{
			printf ("%d,%d\n",x, y);
			e=e + dx2;//来自 2*e*dy= 2*e*dy + 2dy  (原来是 e = e + k)
			if (e > 0)//e是整数且大于0时表示要取右上的点(否则是右下的点) 
			{ 
			 	x += ux; 
				e= e - dy2;//2*e*dy = 2*e*dy - 2*dy  (原来是 e = e -1)
			}
		}
	}
}


你可能感兴趣的:(算法)