直线生成算法——Bresenham法
- 格式:doc
- 大小:221.50 KB
- 文档页数:6
生成直线的bresenham算法
Bresenham算法是由Jack E. Bresenham在1962年提出的一种用于生成直线图形的算法。
它可以根据两个点的坐标来计算出中间所有点的位置,即通过这两个端点可以确定出整条直线的像素点。
Bresenham算法的核心思想是,沿着已知的两个点之间的点,从起点开始向终点靠近,沿途计算斜率的误差,依据误差大小判断是选择水平方向或者垂直方向上的点,从而确定最终的直线图形。
具体步骤如下:
(1)根据两个点坐标计算出斜率dx和dy;
(2)令x0=x1, y0=y1;
(3)计算当前点处斜率误差p,公式为:p=2dy-dx;
(4)根据p的大小,决定下一步是沿水平方向还是垂直方向:
(a)p>0时,下一步沿垂直方向前进,即y++;
(b)p<=0时,下一步沿水平方向前进,即x++;
(5)重复步骤3、4,直到到达终点。
直线生成算法——Bresenham法最近的研究涉及在像素图上作直线,自己也不想花时间摸索,于是在网上找到了Bresenham的直线生成算法,有一篇博客讲得清晰明了,但是算法上有些问题,我进行了改进和移植,下面讲解Bresenham的直线生成算法时也是参考这篇博文。
1.算法简介图1算法思想:图1中,连接M点和N点的直线经过点B,由于是像素图,所以实际上B 点应该由A点或者C点代替。
当B点更靠近A点时,选择点A(x+1,y+1);当B点更靠近C点时,选择点C(x+1,y)。
因此,当ε+m < 0.5时,绘制(x + 1, y)点,否则绘制(x + 1, y + 1)点,这里ε为累加误差,表达式为:式中:表示在第n次计算时的值,表示在第n+1次计算时的值;m就是直线的斜率。
由于斜率m的值有正有负,有可能为0,也可能为∞,为了避免分别讨论这些情况,将上述公式两边都乘以dx, 并将ε*dx用ξ表示,则有式中:表示在第n次计算时的值,表示在第n+1次计算时的值;dx为起点和终点横坐标之差,dy为起点和终点纵坐标之差。
还需说明一点,由直线斜率的定义故值得注意的是,现在我们只考虑dx > dy,且x,y的增量均为正的情况,但实际上有8种不同的情况(但是算法思想不变),如图2所示如图22.算法程序前文提到的那篇博文提出了一种方法,能将这8种情况都考虑,很巧妙。
但是实际应用时发现程序运行结果不是完全对,多次检查之后将程序进行了修改。
修改后的算法VB程序如下‘**************************************************************************** Type mypos '自定义数据类型x As Integery As IntegerEnd Type‘**************************************************************************** Function Bresenham(arr() As mypos, x1, y1, x2, y2)Dim x!, y!, dx!, dy!, ux%, uy%, eps!Dim cnt%ReDim arr(100)dx = x2 - x1dy = y2 - y1If dx >= 0 Then ux = 1If dx < 0 Then ux = -1If dy >= 0 Then uy = 1If dy < 0 Then uy = -1x = x1y = y1eps = 0dx = Abs(dx): dy = Abs(dy)cnt = 0If dx >= dy ThenFor x = x1 To x2 Step uxcnt = cnt + 1If 2 * (eps + dy) < dx Theneps = eps + dyarr(cnt).x = xarr(cnt).y = yElseeps = eps + dy - dxIf cnt >= 2 Then y = y + uy 'cnt大于2才执行y = y + uy,即排除起始坐标点,否则造成错误结果arr(cnt).x = xarr(cnt).y = yEnd IfNext xElseFor y = y1 To y2 Step uycnt = cnt + 1If 2 * (eps + dx) < dy Theneps = eps + dxarr(cnt).x = xarr(cnt).y = yElseeps = eps + dx - dyIf cnt >= 2 Then x = x + ux 'cnt大于2才执行x = x + ux,即排除起始坐标点,否则造成错误结果arr(cnt).x = xarr(cnt).y = yEnd IfNext yEnd Ifarr(0).x = cnt’记录元素个数End Function如果大家有不同看法,还希望共同讨论3.程序运行结果(VB+ OpenGL)图3图4绘制y=x,0≤x≤10,图3是原程序运行结果,图4时修改后的程序运行结果,原程序运行得到的起点是(0,1),但实际应该是(0,0)图5图6绘制直线[第1个坐标为起点,第2个坐标为终点](5,5)-(15,15)、(5,10)-(15,15)、(5,15)-(15,15)、(5,20)-(15,15)、(5,25)-(15,15);(25,5)-(15,15)、(25,10)-(15,15)、(25,15)-(15,15)、(25,20)-(15,15)、(25,25)-(15,15);(5,5)-(15,15)、(10,5)-(15,15)、(15,5)-(15,15)、(20,5)-(15,15)、(25,5)-(15,15);(5,25)-(15,15)、(10,25)-(15,15)、(15,25)-(15,15)、(20,25)-(15,15)、(25,25)-(15,15);图5是原程序运行结果,图6是修改后的程序运行结果。
分别解释直线生成算法dda法,中点画线法和
bresenham法的基本原理
直线生成算法DDA法、中点画线法和Bresenham法的基本原理如下:
1. DDA直线生成算法:基于差分运算的直线生成算法。
通过将直线分割成
若干个相邻的像素点,并按照一定的步长进行逐点绘制,实现直线的绘制。
算法主要涉及到线性插值的思想,即根据已知的两点坐标,通过计算它们之间的差值,然后根据这个差值和步长来确定新的像素点的位置。
2. 中点画线法:一种线段绘制算法,从线段的起点和终点出发,按照一定的规则向终点逐步逼近,并在途中以控制变量的方式得出每个像素点的坐标,从而绘制出所需的线条。
具体实现中,通过计算线段斜率的变化情况,分为斜率小于1和大于等于1两种情况,并采用Bresenham的对称性原理,以中点的颜色来控制每个像素点的生长方向,从而获得较高的绘制效率和图像质量表现。
3. Bresenham算法:通过一系列的迭代来确定一个像素点是否应该被绘制。
对于一条从点(x1,y1)到点(x2,y2)的直线,首先计算出斜率k。
然后,通过比较每个像素点的y值到直线上的y值,来决定哪些像素点应该被绘制。
当斜率k大于等于1时,在x方向上迭代,而对于每个x值,计算出y值,并将像素点(x,y)绘制。
当斜率k小于1时,在y方向上迭代,而对于每个y值,计算出x值,并将像素点(x,y)绘制。
以上内容仅供参考,如需更多信息,建议查阅相关文献或咨询数学专业人士。
生成直线的B resenham算法从上面介绍的DDA算法可以看到,由于在循环中涉及实型数据的加减运算,因此直线的生成速度较慢。
在生成直线的算法中,B resenham算法是最有效的算法之一。
B resenham算法是一种基于误差判别式来生成直线的方法。
一、直线Bresenham算法描述:它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一个象素。
我们首先讨论m=△y/△x,当0≤m≤1且x1<x2时的B resenham算法。
从DDA直线算法可知这些条件成立时,公式(2-2)、(2-3)可写成:x i+1=x i+△x(2-2)y i+1=y i+△y(2-3)x i+1=x i+1 (2-6)y i+1=y i+m(2-7)有两种B resenham算法思想,它们各自从不同角度介绍了B resenham算法思想,得出的误差判别式都是一样的。
二、直线B resenham算法思想之一:由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(x i,y i),它是直线上点(x i,y i)的最佳近似,并且x i=x i(假设m<1),如下图所示。
那么,直线上下一个象素点的可能位置是(x i+1,y i)或(x i+1,y i+1)。
由图中可以知道,在x=x i+1处,直线上点的y值是y=m(x i+1)+b,该点离象素点(x i+1,y i)和象素点(x i+1,y i+1)的距离分别是d1和d2:这两个距离差是我们来分析公式(2-10):(1)当此值为正时,d1>d2,说明直线上理论点离(x i+1,y i+1)象素较近,下一个象素点应取(x i+1,y i+1)。
(2)当此值为负时,d1<d2,说明直线上理论点离(x i+1,y i)象素较近,则下一个象素点应取(x i+1,y i)。
1、直线生成算法1.算法分析1)DDA设直线两端点:P1(x1,y1)及 P0(x0,y0),dx=x1-x0,dy=y1-y0直线斜率:k=dy/dx直线方程: y=k*x+b有:y1=k*x1+b=k*x0+k*dx+b=y0+k*dx当dx=1时,有y1=y0+k算法复杂度:加法+取整优点:避免了y=k*x+b 方程中的浮点乘法,比直接用点斜式画线快 缺点:需浮点数加法及取整运算,不利于硬件实现.2)Midpoint当前像素点为P(xP,yP),下一个像素点有两种可选择点P1(xP+1,yP),P2(xP+1,yP+1)。
若M=(xP+1,yP+0.5)为P1与P2的中点,Q 为理想直线与x=xP+1垂线的交点。
x Pi=(xi, yi ) M Q P1 p2y当M 在Q 的上方时,应取P1为下一点;当M 在Q 的下方时,应取P2为下一点;直线段L (P0(x0,y0),P1(x1,y1)),用方程F (x,y )=ax+by+c=0表示 a=y0-y1,b=x1-x0,c=x0y1-x1y0有点与L 的关系:线上:F (x,y )=0上方:F (x,y )>0下方:F (x,y )<0判别式:d=F(M)=F(xP+1,yP+0.5)=a(xP+1)+b(yP+0.5)+cD 是xP,yP 的线性函数,可采用增量计算,提高运算效率:1)若d>=0,取P1,d1=d+a,增量为a2)若d<=,取P2,d2=d+a+b,增量为a+b可用2d 代替d 来摆脱浮点运算,写出仅含整数运算的算法3)Bresenhamy x F(x,y)=0 F(x,y)>0 F(x,y)<0 (x1,y1)(x0,y0)设直线方程为y=kx+b,有y1=y0+k(x-x0)=y0+k是否增1取决于误差项d的值,初始值d0=0X每增加1,有d=d+k令e=d-0.5,e0=-0.5,增量为k当e>=0时,取当前像素(xi,yi)的右上方像素(xi+1,yi+1),e 减小1;当e<0时,更接近于右方像素(xi+1,yi)。
Course PagePage 1 of 6课程首页 > 第二章 二维图形的生成 > 2.1 直线的生成 > 2.1.2 生成直线的Bresenham算法全部隐藏2.1.2 生成直线的Bresenham算法从上面介绍的DDA算法可以看到,由于在循环中涉及实型数据的加减运算,因此直线的生成速度较慢。
在生成直线的算法中,Bresenham算法是最有效的算法之一。
Bresenham算法是一种基于误差判别式来生成直线的方法。
一、直线Bresenham算法描述: 它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一 个象素。
我们首先讨论m=△ y/△x,当0≤m≤1且x1<x2时的Bresenham算法。
从DDA直线算法可知这些条件成立时,公式(2-2)、(2-3)可写成: xi+1=x i+1 yi+1=y i+m (2-6) (2-7)有两种Bresenham算法思想,它们各自从不同角度介绍了Bresenham算法思想,得出的误差判别式都是一样的。
二、直线Bresenham算法思想之一: 由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(xi,yi),它是直线上点(xi,yi)的最佳近似,并且xi=xi(假设 m<1),如下图所示。
那么,直线上下一个象素点的可能位置是(xi+1,yi)或(xi+1,yi+1)。
由图中可以知道,在x=xi+1处,直线上点的y值是y=m(xi+1)+b,该点离象素点(xi+1,yi)和象素点(xi+1,yi+1)的距离分别是d1和d2:d1=y-yi=m(xi+1)+b-yi d2=(yi+1)-y=(yi+1)-m(xi+1)-b 这两个距离差是 d1-d2=2m(xi+1)-2yi+2b-1(2-8) (2-9)(2-10)我们来分析公式(2-10): (1)当此值为正时,d1>d2,说明直线上理论点离(xi+1,yi+1)象素较近,下一个象素点应取(xi+1,yi+1)。
分别解释直线生成算法dda法、中点画线法和bresenham法的基本原理DDA直线生成算法、中点画线法和Bresenham法都是计算机图形学中用于生成直线的算法。
以下是这三种算法的基本原理:1.DDA直线生成算法(Digital Differential Analyzer):DDA算法是一种基于差分运算的直线生成算法。
其基本原理是,通过计算直线起点和终点之间的差值(横向差值dx 和纵向差值dy),并根据步长来决定下一个像素点的位置。
算法首先确定差值中绝对值较大的一方作为基准,步长设为1,另一方则按比例进行调整,以保持线段的斜率不变。
在实现过程中,DDA算法需要遍历每一个像素点,根据差值的正负和大小来确定新像素点的位置。
2.中点画线法:中点画线法的基本原理是,通过计算线段上当前像素点与相邻两个像素点构成的线段与理想直线的距离,来决定下一个像素点的位置。
具体实现时,设定线段的中点为M,理想直线与线段的交点为Q。
通过比较M和Q的位置关系来确定下一个像素点:若M在Q上方,则取上方的像素点为下一个点;若M在Q下方,则取下方的像素点为下一个点;若M与Q重合,则可任意选择上方或下方的像素点。
中点画线法以中点M作为判别标志,逐点生成直线。
3.Bresenham法:Bresenham算法的原理是基于直线的斜率和截距来计算每个像素点的位置。
在计算机屏幕上,每个像素点都有一个坐标值。
Bresenham算法通过计算直线上每个像素点的坐标值来绘制直线,避免了使用浮点数运算,从而提高了计算效率。
在实现过程中,Bresenham算法根据直线的斜率以及当前像素点的位置,计算出下一个像素点的位置,并逐点绘制出直线。
布雷森汉姆直线算法布雷森汉姆直线算法(Bresenham's Line Algorithm)是一种计算机图形学中常用的直线绘制算法,其通过在离散的像素格上选择最接近实际直线路径的点来实现高效绘制直线的目的。
该算法由Jack Elton Bresenham在1962年首次提出,被广泛应用于图形显示、打印机及数码扫描仪等领域。
布雷森汉姆直线算法的核心思想是利用整数运算来代替浮点运算,从而提高计算效率。
该算法通过仅使用加法、减法和位移等基本运算,不需要乘法运算和浮点数运算,从而适用于资源有限的嵌入式系统和低成本的图形设备。
算法的基本步骤如下:1. 根据起点P1(x1,y1)和终点P2(x2,y2)确定直线斜率k。
2. 如果|k|≤1,则沿x轴方向递增遍历起点P1到终点P2,并在每个像素上绘制。
若k>1,则沿y轴方向递增遍历P1到P2,绘制每个像素。
3. 对于每一步,根据递增的方向选择相应的像素。
4. 根据斜率k来决定误差累积量,调整绘制位置,保证直线的连续性。
该算法的优势在于其简单而高效的原理,使得绘制直线的速度非常快。
与传统的基于浮点运算的算法相比,布雷森汉姆直线算法的计算开销较小,而且能够得到非常接近实际直线路径的结果,几乎没有明显的视觉差异。
这使得该算法在计算资源有限的场景下非常有用,例如在嵌入式系统中,可以利用该算法绘制图形界面的边界、线条等。
然而,布雷森汉姆直线算法也存在一些局限性。
由于只考虑了整数坐标,因此绘制出来的直线可能会有些锯齿状,这在一些高精度要求的场景下可能会表现出明显的视觉噪点。
此外,该算法仅适用于绘制直线,并不能直接应用于曲线、圆等其他形状的绘制。
总之,布雷森汉姆直线算法是一种非常经典和实用的绘制直线的算法。
它通过巧妙地利用整数计算来取代浮点计算,以提高效率和减少计算资源开销。
虽然存在一些局限性,但在大多数场景下,它仍然是一种高效且精确的绘制直线的选择,对于计算机图形学的发展和应用有着重要的指导意义。
bresenham算法计算步骤Bresenham算法是一种经典的线段生成算法,其原理是利用递增的整数计算来逼近直线的路径,从而快速高效地绘制线段。
本文将详细介绍Bresenham算法的计算步骤。
1. 确定起点和终点我们需要确定线段的起点和终点的坐标。
假设起点为(x0, y0),终点为(x1, y1)。
2. 计算斜率接下来,我们需要计算线段的斜率。
斜率可以通过以下公式来计算:m = (y1 - y0) / (x1 - x0)其中m表示斜率。
3. 判断斜率绝对值是否小于1判断斜率的绝对值是否小于1,如果小于1,则说明直线在x方向上变化的幅度更大;反之,如果斜率的绝对值大于等于1,则说明直线在y方向上变化的幅度更大。
4. 计算增量根据斜率的值,我们可以计算出在每个步骤中需要增加的x和y的值。
如果斜率的绝对值小于1,则每次x增加1,y增加斜率m;反之,如果斜率的绝对值大于等于1,则每次y增加1,x增加1/斜率m。
5. 计算初始误差计算初始误差值,初始误差值为0。
初始误差用于判断应该向x方向还是y方向进行绘制。
6. 迭代绘制线段根据初始误差值和增量,使用迭代的方式来绘制线段。
具体步骤如下:- 根据初始误差值,判断当前点应该绘制在哪个像素上。
如果误差大于等于0,则绘制在下一个像素上,同时误差减去1;反之,如果误差小于0,则绘制在当前像素上。
- 根据斜率的绝对值大小,更新初始误差的值。
如果斜率的绝对值小于1,则初始误差加上y的增量;反之,如果斜率的绝对值大于等于1,则初始误差加上x的增量。
- 根据斜率的绝对值大小,更新x和y的值。
如果斜率的绝对值小于1,则x加上1;反之,如果斜率的绝对值大于等于1,则y加上1。
7. 绘制结果将线段绘制在屏幕上,直到终点被绘制到。
通过以上步骤,我们可以使用Bresenham算法快速高效地绘制直线。
这个算法的优点是计算简单、速度快,并且不需要浮点运算,因此非常适合在计算能力较弱的设备上使用。
直线生成算法——Bresenham法
最近的研究涉及在像素图上作直线,自己也不想花时间摸索,于是在网上找到了Bresenham的直线生成算法,有一篇博客讲得清晰明了,但是算法上有些问题,我进行了改进和移植,下面讲解Bresenham的直线生成算法时也是参考这篇博文。
1.算法简介
图1
算法思想:图1中,连接M点和N点的直线经过点B,由于是像素图,所以实际上B 点应该由A点或者C点代替。
当B点更靠近A点时,选择点A(x+1,y+1);当B点更靠近C点时,选择点C(x+1,y)。
因此,当ε+m < 0.5时,绘制(x + 1, y)点,否则绘制(x + 1, y + 1)点,这里ε为累加误差,表达式为:
式中:表示在第n次计算时的值,表示在第n+1次计算时的值;m就是直线的
斜率。
由于斜率m的值有正有负,有可能为0,也可能为∞,为了避免分别讨论这些情况,
将上述公式两边都乘以dx, 并将ε*dx用ξ表示,则有
式中:表示在第n次计算时的值,表示在第n+1次计算时的值;dx为起
点和终点横坐标之差,dy为起点和终点纵坐标之差。
还需说明一点,由直线斜率的定义
故
值得注意的是,现在我们只考虑dx > dy,且x,y的增量均为正的情况,但实际上有8种不同的情况(但是算法思想不变),如图2所示
如图2
2.算法程序
前文提到的那篇博文提出了一种方法,能将这8种情况都考虑,很巧妙。
但是实际应用时发现程序运行结果不是完全对,多次检查之后将程序进行了修改。
修改后的算法VB程序如下
‘**************************************************************************** Type mypos '自定义数据类型
x As Integer
y As Integer
End Type
‘**************************************************************************** Function Bresenham(arr() As mypos, x1, y1, x2, y2)
Dim x!, y!, dx!, dy!, ux%, uy%, eps!
Dim cnt%
ReDim arr(100)
dx = x2 - x1
dy = y2 - y1
If dx >= 0 Then ux = 1
If dx < 0 Then ux = -1
If dy >= 0 Then uy = 1
If dy < 0 Then uy = -1
x = x1
y = y1
eps = 0
dx = Abs(dx): dy = Abs(dy)
cnt = 0
If dx >= dy Then
For x = x1 To x2 Step ux
cnt = cnt + 1
If 2 * (eps + dy) < dx Then
eps = eps + dy
arr(cnt).x = x
arr(cnt).y = y
Else
eps = eps + dy - dx
If cnt >= 2 Then y = y + uy 'cnt大于2才执行y = y + uy,即排除起始坐标点,否则造成错误结果
arr(cnt).x = x
arr(cnt).y = y
End If
Next x
Else
For y = y1 To y2 Step uy
cnt = cnt + 1
If 2 * (eps + dx) < dy Then
eps = eps + dx
arr(cnt).x = x
arr(cnt).y = y
Else
eps = eps + dx - dy
If cnt >= 2 Then x = x + ux 'cnt大于2才执行x = x + ux,即排除起始坐标点,否则造成错误结果
arr(cnt).x = x
arr(cnt).y = y
End If
Next y
End If
arr(0).x = cnt’记录元素个数
End Function
如果大家有不同看法,还希望共同讨论
3.程序运行结果(VB+ OpenGL)
图3
图4
绘制y=x,0≤x≤10,图3是原程序运行结果,图4时修改后的程序运行结果,原程序运行得到的起点是(0,1),但实际应该是(0,0)
图5
图6
绘制直线[第1个坐标为起点,第2个坐标为终点]
(5,5)-(15,15)、(5,10)-(15,15)、(5,15)-(15,15)、(5,20)-(15,15)、(5,25)-(15,15);
(25,5)-(15,15)、(25,10)-(15,15)、(25,15)-(15,15)、(25,20)-(15,15)、(25,25)-(15,15);
(5,5)-(15,15)、(10,5)-(15,15)、(15,5)-(15,15)、(20,5)-(15,15)、(25,5)-(15,15);
(5,25)-(15,15)、(10,25)-(15,15)、(15,25)-(15,15)、(20,25)-(15,15)、(25,25)-(15,15);
图5是原程序运行结果,图6是修改后的程序运行结果。