Draw line--Bresenham Algorithm

Basic


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

  • 使用Bresenham算法绘制三角形边框,我们先获得取值范围在-1.0f~1.0f的三个点坐标,分别乘500。将三个点两两配对,通过Bresenham算法获得绘制直线的所有点的坐标,除以500再存在数组中,最后通过glDrawArrays(GL_POINTS, 0, length)绘制直线,三条直线组合成为一个三角形边框。
  • 绘制直线的Bresenham算法:
    p 0 = 2 Δ   y − Δ   x p_0=2\Delta\ y -\Delta\ x p0=2Δ yΔ x
    p ≤   0 p \leq\ 0 p 0          p p pi+1 = p i + 2 Δ   y p_i + 2\Delta\ y pi+2Δ y
                         y y yi+1 = y i = y_i =yi
    p > 0 p > 0 p>0           p p pi+1 = p i + 2 Δ   y − 2 Δ   x p_i + 2\Delta\ y - 2\Delta\ x pi+2Δ y2Δ x
                         y y yi+1 = y i + 1 = y_i+1 =yi+1       or       y y yi+1 = y i − 1 = y_i-1 =yi1
    x x xi+1 = x i − 1 = x_i-1 =xi1       or       x x xi+1 = x i + 1 = x_i+1 =xi+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);
      
  • 运行结果
    在这里插入图片描述

2、Bresenham算法绘制圆

  • 使用Bresenham算法绘制圆的关键在于找对p的递归关系,这方面网上有好几种递归方式,我使用了其中一种。在寻找绘制圆的坐标点时,可以只计算从y轴正方向到x轴正方向转过的八分之一圆弧,其他圆弧都可以通过这八分之一圆弧上的坐标点变换得到。
  • 绘制圆的Bresenham算法:
    p 0 = 1 − r p_0=1-r p0=1r
    p ≤   0 p \leq\ 0 p 0          p p pi+1 = p i + 2 x + 3 =p_i + 2x + 3 =pi+2x+3
                         y y yi+1 = y i = y_i =yi
    p &gt; 0 p &gt; 0 p>0           p p pi+1 = p i + 2 x − 2 y + 5 =p_i + 2x-2y+5 =pi+2x2y+5
                         y y yi+1 = y i − 1 = y_i - 1 =yi1
    x = x + 1 x=x+1 x=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);
      }
      
  • 实验结果
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值