Basic


1、Bresenham算法绘制三角形边框

  • 使用Bresenham算法绘制三角形边框,我们先获得取值范围在-1.0f~1.0f的三个点坐标,分别乘500。将三个点两两配对,通过Bresenham算法获得绘制直线的所有点的坐标,除以500再存在数组中,最后通过glDrawArrays(GL_POINTS, 0, length)绘制直线,三条直线组合成为一个三角形边框。
  • 绘制直线的Bresenham算法:
    p0=2Δ yΔ xp_0=2\Delta\ y -\Delta\ x
    p 0p \leq\ 0         ppi+1 = pi+2Δ yp_i + 2\Delta\ y
                        yyi+1=yi= y_i
    p>0p > 0          ppi+1 = pi+2Δ y2Δ xp_i + 2\Delta\ y - 2\Delta\ x
                        yyi+1=yi+1= y_i+1       or      yyi+1=yi1= y_i-1
    xxi+1=xi1= x_i-1       or      xxi+1=xi+1= x_i+1
  • 代码实现
    两点确定一条直线,首先我们要确定这条直线的斜率,根据斜率分为三种情况:
    (1)斜率不存在
    (2)斜率绝对值小于等于1
    (3)斜率绝对值大于1
    • Bresenham算法

      void bresenham(int array[], int p, int i, int length, int dx, int dy, int flag)
      {
      	if (i == length)
      		return;
      	int pnext;
      	if (p <= 0)
      	{
      		array[i + 1] = array[i];
      		pnext = p + 2 * dy;
      	}
      	else
      	{
      		array[i + 1] = array[i] + flag;
      		pnext = p + 2 * dy - 2 * dx;
      	}
      	bresenham(array, pnext, i + 1, length, dx, dy, flag);
      }
      
    • 斜率不存在

      if (x_begin == x_end)									//如果斜率不存在
      {
      	if (y_begin > y_end)
      	{
      		flag = -1;							//判断在y轴的增减性
      	}
      	length = abs(y_end - y_begin) + 1;
      	for (int i = 0; i < length; ++i)
      	{
      		vertices_x[i] = x_begin;
      		vertices_y[i] = y_begin + i * flag;
      	}
      }
      
    • 斜率绝对值小于等于1
      在这种情况下,x轴方向上的变化快于y轴方向上的变化,因此,我们在x轴上取样,取样间隔为1,在y轴上量化。

      float m = float(y_end - y_begin) / float(x_end - x_begin);
      if (fabs(m) <= 1)				//如果斜率绝对值小于等于1,则在x坐标轴上采样
      {
      	flag = (x_begin > x_end) ? -1 : 1;			//判断x的增减性
      	int dy = abs(y_end - y_begin);
      	int dx = abs(x_end - x_begin);
      	length = dx + 1;
      	for (int i = 0; i < length; ++i) 			 //x坐标轴上的采样点
      	{
      		vertices_x[i] = x_begin + i * flag;
      	}
      	flag = (y_begin <= y_end) ? 1 : -1;			//判断y的增减性
      	vertices_y[0] = y_begin;
      	int p0 = 2 * dy - dx;
      	bresenham(vertices_y, p0, 0, length, dx, dy, flag);
      }
      
    • 斜率绝对值大于1
      在这种情况下,y轴方向上的变化快于x轴方向上的变化,因此,我们在y轴上取样,取样间隔为1,在x轴上量化

      flag = (y_begin > y_end) ? -1 : 1;		//判断在y轴上的增减性
      int dy = abs(y_end - y_begin);
      int dx = abs(x_end - x_begin);
      length = dy + 1;
      for (int i = 0; i < length; ++i)		//y坐标轴上的采样点
      {
      	vertices_y[i] = y_begin + i * flag;
      }
      flag = (x_begin <= x_end) ? 1 : -1;		//判断在x轴上的增减性
      vertices_x[0] = x_begin;
      int p0 = 2 * dx - dy;
      bresenham(vertices_x, p0, 0, length, dy, dx, flag);
      
  • 运行结果
    Draw line--Bresenham Algorithm

2、Bresenham算法绘制圆

  • 使用Bresenham算法绘制圆的关键在于找对p的递归关系,这方面网上有好几种递归方式,我使用了其中一种。在寻找绘制圆的坐标点时,可以只计算从y轴正方向到x轴正方向转过的八分之一圆弧,其他圆弧都可以通过这八分之一圆弧上的坐标点变换得到。
  • 绘制圆的Bresenham算法:
    p0=1rp_0=1-r
    p 0p \leq\ 0         ppi+1=pi+2x+3=p_i + 2x + 3
                        yyi+1=yi= y_i
    p&gt;0p &gt; 0          ppi+1=pi+2x2y+5=p_i + 2x-2y+5
                        yyi+1=yi1= y_i - 1
    x=x+1x=x+1
  • 代码实现
    • Bresenham算法
      void bresenham_circle(int array[], int p, int x, int y, int &index)
      {
      	if (x >= y)
      		return;
      	int pnext;
      	if (p <= 0)
      	{
      		pnext = p + 2 * x + 3;
      	}
      	else
      	{
      		pnext = p + 2 * (x - y) + 5;
      		--y;
      	}
      	array[index] = y;
      	++x;
      	++index;
      	bresenham_circle(array, pnext, x, y, index);
      }
      
  • 实验结果
    Draw line--Bresenham Algorithm

相关文章: