【计算机图形学】画线算法——Bresenham算法(任意斜率)

   

目录

一、Bresenham算法原理

二、C语言实现


 一、Bresenham算法原理

Bresenham提出的一种精确而有效的光栅线生成算法,可用于显示线、圆和其他曲线的整数增量运算。它是目前最有效的线段生成算法。

   推导: 

 设线段端点:(x_1,y_1),(x_2,y_2),∆x和∆y为水平和垂直偏移量,m为斜率

                                                m=\frac{y_2-y_1}{x_2-x_1}=\frac{\Delta y}{\Delta x}

                当|m| <= 1时,对于给定的x增量x    

                                                \left\{\begin{matrix} &\Delta y=m \Delta x \\ &\Delta x =x_2-x_1 \end{matrix}\right.         

                当|m| >= 1时,对于给定的y增量y

                                                \left\{\begin{matrix} \Delta x = \Delta y / m\\ \Delta y=y_2-y_1 \end{matrix}\right.   

                

 (当  0<m < 1)   

假设已经确定了要显示的像素P_k(x_k , y_k),那么,需要确定下一点P_{k+1}是绘制在(x_k+1,y_k)

还是(x_k+1,y_k+1)   

                                                               

                     

根据直线的方程,直线上x_k+1处的y坐标为:

                                        f(x) = m (x_k + 1) + b

                        ​​​​​​​​​​​​​​​​​​​​​​​​​​​​                d_1=f(x_k+1)-y_k=m(x_k+1)+b -y_k

                                        d_2 = (y_k+1) - f(x_k+1) = y_k+1 - m(x_k + 1) - b 

                                        d_1 - d_2 = 2m (x_k + 1) - 2y_k + 2b

m带入d1   d2中,并变换得:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        p_k = \Delta x (d_1 - d_2) = 2x_k\Delta y - 2y_k\Delta x + c

其中,p_k为算法中k步的决策参数c为一常量,其值为2\Delta y + \Delta x (2b - 1)

那么:

                                        若p_k< 0,即d_1 < d_2,有  y_{k+1} = y_k

                                        若p_k\geq 0d_1 \geq d_2,有  y_{k+1} = y_k + 1

同理,可求得第k+1步的决策参数p_{k+1} 

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        p_{k+1} = 2x_{k+1} \Delta y +1 - 2y_{k+1}\Delta x + c

因此,有如下递推关系:

         ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​       p_{k+1}- p_k = (x_{k+1} - x_k)2\Delta y - (y_{k+1} - y_k) 2\Delta x

因为0<m<1 因此x_{k+1} = x_k + 1,带入上式得:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        p_{k+1} - p_k = 2\Delta y - 2(y_{k+1} - y_k)\Delta x

其中,y_{k+1} - y_k的值取决于p_k的值:

                                        当p_k < 0时,y_{k+1} = y_kp_{k+1} = p_k + 2\Delta y 

                                        当p_k \geq 0时, y_{k+1} = y_{k} + 1p_{k+1} = p_k + 2\Delta y - 2\Delta x

Bresenham算法描述 (0 < m < 1)

算法从线段的起始端点开始,反复计算每个点的决策参数并绘制像素。

起始端点(x_0 , y_0)处的决策参数p_0为:

          ​​​​​​​        ​​​​​​​        ​​​​​​​        d_1 = y - y_0 = m (x_0 + 1) + b - y_0 = m

                                  d_2 = (y_0+1) - y = y_0+1 - m (x_0 + 1) - b = 1 - m

                                  d_1 - d_2 = 2m - 1

                                  p_0 = (d_1 - d_2)\Delta x = (2m - 1)\Delta x = 2\Delta y - \Delta x

算法:

1、输入线段的两个端点,并将左端点存储在(x_0 , y_0)中;

2、将(x_0 , y_0)装入帧缓冲器,画出第一个点;

3、计算常量xy2y 2y – 2x,并得到决策参数的第一个值:p_0= 2\Delta y - \Delta x 

4、从k = 0开始,在沿线的每个x_k处,进行下列检测:

  若p_k < 0,下一个待画点是(x_k+1, y_k ),且p_{k+1} = p_k + 2\Delta y

  p_k\geq 0 ,下一个待画点是(x_k+1, y_k+1),且p_{k+1} = p_k+ 2\Delta y -2\Delta x

5、重复步骤4,共x次。

二、C语言实现

//Modified form https://rosettacode.org/wiki/Bitmap/Bresenhanm%27s_line_algorithm#c
void bresenham(int x0, int y0, int x1, int y1){
    int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
    int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
    int erro = (dx > dy ? dx : -dy) / 2;

    while(putpixel(x0,y0), x0 != x1 || y0 != y1){
        int e2 = erro;
        if(e2 > -dx) { erro -= dy; x0 += sx;}
        if(e2 <  dy) { erro += dx; y0 += sy;}
    } 
}

main方法

int main() {
	initgraph(640, 480);
	setbkcolor(0xC1CDC1);
	cleardevice();
	bresenham(320, 240, 0, 0, BLACK);
	bresenham(320, 240, 160, 0, BLUE);
	bresenham(320, 240, 320,0,GREEN);
	bresenham(320, 240, 480,0, CYAN);
	bresenham(320, 240, 640, 0, RED);
	bresenham(320, 240, 640, 120, MAGENTA);
	bresenham(320, 240, 640, 240, BROWN);
	bresenham(320, 240, 640, 360, LIGHTGRAY);
	bresenham(320, 240, 640, 480, DARKGRAY);
	bresenham(320, 240, 480, 480, LIGHTBLUE);
	bresenham(320, 240, 320, 480, LIGHTGREEN);
	bresenham(320, 240, 160, 480, LIGHTCYAN);
	bresenham(320, 240, 0, 480, LIGHTMAGENTA);
	bresenham(320, 240, 0, 360, YELLOW);
	bresenham(320, 240, 0, 240, BROWN);
	bresenham(320, 240, 0, 120, WHITE);
	_getch();
	return 0;
}

结果:

                                   

  • 63
    点赞
  • 307
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值