Bresenham算法理解

来源:互联网 发布:淘宝差评有什么后果 编辑:程序博客网 时间:2024/06/05 09:48

Bresenham

bresenham算法是计算机图形学中为了“显示器(屏幕或打印机)系由像素构成”的这个特性而设计出来的算法,使得在求直线各点的过程中全部以整数来运算,因而大幅度提升计算速度。

实现代码

这篇文章主要对下面的代码进行解释,如果能够理解下面的代码,完全可以跳过这篇文章。

// 来源:https://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#Cvoid line(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 err = (dx>dy ? dx : -dy)/2, e2;  for(;;){    setPixel(x0,y0);    if (x0==x1 && y0==y1) break;    e2 = err;    if (e2 >-dx) { err -= dy; x0 += sx; }    if (e2 < dy) { err += dx; y0 += sy; }  }}

直线方程

众所周知,最基本的斜截式直线方程为y=kx+b(k,b)。这个方程存在的缺点是无法表示直线x=α,所以用一个新的方程来代替Ax+By+C=0

Bresenham

Bresenham画直线的算法主要步骤是判断下一点的位置。维基百科中有一张图比较形象
Bresenham图
图中,每一个点代表的是一个像素,假定我们有直线f(x,y)且当前坐标为(x,y),判断下一个点的y轴坐标步骤为(如果要确定x轴坐标也类似):

Created with Raphaël 2.1.0起始坐标(x,y)计算f(x+1, y)中y的值nyny - y < 1yEndy+1yesno

代码理解

如上面所述,我们现在能够判断直线的下一个像素点在那里了,但是Bresenham算法的优点还没有体现:我们还需要计算浮点数。为了避免浮点数计算,我们要更深入地发现划线的规律。

这里我们只考虑x1<x2y1<y2的情况,实际上我们也只需要考虑这种情况,正如前面代码所写的sx, sy,通过这两个变量我们便能控制要画的直线方向是正确的。

  • Bresenham的输入为两个点(x1,y1),(x2,y2)。根据这两个点,我们能够计算出两点之间的“距离“。这里的距离用的是绝对值,对应的是代码里的dx, dy
    Δx=|x1x2|Δy=|y1y2|

    根据斜截式y=kx+b,我们有y=ΔyΔxx+b,进而有
    ΔyxΔxy+C=0

    在这条公式中:
    x+1y+ΔyΔxy+1x+ΔxΔy
  • 实际上,用于判断下一个点的位置的就是ΔyΔxΔxΔy。这两个值变化的根本目的是使上面的方程成立,根据这一点,我们直接引入一个变量err避免整数运算(对应代码中的erre2
    ΔyxΔxy+C+err=0x+1errΔyy+1err+Δx
  • 现在我们已经能够将 errx,y 联系起来,但是还有一个很重要的问题没有解决:判断增加x轴坐标还是增加y轴坐标
    首先假设我们在起始坐标(x,y),当前的err也是正确的,现在需要判断下一个点的坐标。
    根据传统的Bresenham算法:
    (x+ΔxΔy)(x+1)>0ΔxΔy>0x+1(y+ΔyΔx)(y+1)>0ΔyΔx>0y+1

    我们更关注中间的部分,结合上一点所说的errΔx,Δy的关系对其进行变形
    ΔxΔy>0Δy>ΔxΔyΔx>0+Δx<Δy
  • 从上面的公式看来似乎是与err有点关系了,但是还不明确,那是因为我们的推到基于起始点,倘若基于的不是起始点,那么该公式应当为
    ΔxΔy>0εΔy>ΔxΔyΔx>0ε+Δx<Δy

    ε为一个累加值,其来源与当前点(x,y)和起始点(x0,y0)的相对位置有关,个人理解是:每一次x+1y+1都会让原来的直线平移,这个平移便会造成误差,而这个误差会随着程序的进行而不断累加,而这个累加值对应的正是err
  • 现在我们就有能力将err和程序中的err联系起来了。
    if后的条件与上面的公式对应,而errε不同。不同之处是:err是已经计算好的εΔyε+Δx。我们可以这样思考:在某一个点(x,y)处,我们已经计算得到了正确的、可以用于判断的err,当我们选择下一个点时,我们可以顺便把下一个点的err给计算了,这就是代码中err -= dy; err += dx;蕴含的意思。
if (e2 >-dx) { err -= dy; x0 += sx; }if (e2 < dy) { err += dx; y0 += sy; }
  • 至此,Bresenham算法理解完成。
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 拐枣什么时候成熟 拐枣木 拐枣的吃法 拐枣酒的功效与作用 拐枣酒的功效 金钩梨 金钩子 梨枣 鸡爪子 鸡爪梨 拐棍 拐棍舞 金拐棍计算器 拐棍棒棒糖 拐棍糖 拐棍鱼 残疾人拐棍 拄拐棍 拐棍头 拐棍糖机器 拐点 拐点定义 刘易斯拐点 拐点的定义 拐点怎么求 函数拐点 驻点和拐点 历史的拐点 拐点坐标 路易斯拐点 如何求拐点 拐点和驻点的区别 中国人口拐点 成交量拐点选股 拐点是点还是坐标 函数拐点的定义 成交量拐点选股公式 科二s弯的四个拐点图解 拐角 拐角码头