Bresenham快速画直线算法

转载博文原址:http://www.cnblogs.com/pheye/archive/2010/08/14/1799803.html

算法原理的详细描述及部分实现可参考:

http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html

    Fig. 1

   假设以(x, y)为绘制起点,一般情况下的直观想法是先求m = dy /dx(即x每增加1 y的增量),然后逐步递增x, 设新的点为x1 = x + j, y1 = round(y + j * m)。可以看到,这个过程涉及大量的浮点运算,效率上是比较低的(特别是在嵌入式应用中,DSP可以一周期内完成2次乘法,一次浮点却要上百个周期)。

       下面,我们来看一下Bresenham算法,如Fig. 1,(x, y +ε)的下一个点为(x, y + ε + m),这里ε为累加误差。可以看出,当ε+m < 0.5时,绘制(x + 1, y)点,否则绘制(x + 1, y + 1)点。每次绘制后,ε将更新为新值:

            ε = ε + m ,如果(ε + m) <0.5 (或表示为2*(ε + m) < 1)

            ε = ε + m – 1, 

其他情况将上述公式都乘以dx, 并将ε*dx用新符号ξ表示,可得

            ξ = ξ + dy, 如果2*(ξ + dy) < dx

            ξ = ξ + dy – dx, 其他情况

可以看到,此时运算已经全变为整数了。以下为算法的伪代码:

            ξ ← 0, y ← y1

            For x ← x1 to x2 do

                Plot Point at (x, y)

                If (2(ξ + dy) < dx)

                    ξ ←ξ + dy

                Else

                    y ← y + 1,ξ ←ξ + dy – dx

                End If

            End For

二、             算法的注意点:

Fig. 2

在实际应用中,我们会发现,当dy > dx 或出现 Fig.2  右图情况时时,便得不到想要的结果,这是由于我们只考虑 dx > dy   x, y 的增量均为正的情况所致。经过分析,需要考虑 8 种不同的情况,如 Fig. 3 所示:

        

(Fig. 3)

当然,如果直接在算法中对8种情况分别枚举, 那重复代码便会显得十分臃肿,因此在设计算法时必须充分考虑上述各种情况的共性,后面将给出考虑了所有情况的实现代码。

三、             算法的实现

以下代码的测试是利用Opencv 2.0进行的,根据需要,只要稍微修改代码便能适应不同环境

    void DrawLine(IplImage *img, int x1, int y1, int x2, int y2)
{
     int dx = x2 - x1;
     int dy = y2 - y1;
     int ux = ((dx > 0) << 1) - 1;//x的增量方向,取或-1
     int uy = ((dy > 0) << 1) - 1;//y的增量方向,取或-1
     int x = x1, y = y1, eps;//eps为累加误差

     eps = 0;dx = abs(dx); dy = abs(dy); 
     if (dx > dy) 
     {
         for (x = x1; x != x2; x += ux)
         {
              SetPixel(img, x, y);
              eps += dy;
              if ((eps << 1) >= dx)
              {
                   y += uy; eps -= dx;
              }
         }
     }
     else
     {
         for (y = y1; y != y2; y += uy)
         {
              SetPixel(img, x, y);
              eps += dx;
              if ((eps << 1) >= dy)
              {
                   x += ux; eps -= dy;
              }
         }
     }             
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值