bresenham画线算法详解
Bresenham画线算法
Bresenham画线算法Bresenham画线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
Bresenham画法与中点法相似,都是通过每列象素中确定与理想直线最近的像素来进行直线的扫描的转换的。
通过各行、各列的象素中心构造一组虚拟网格线的交点,然后确定该列象素中与此交点最近的像素。
该算法的巧妙之处在于可以采用增量计算,使得对于每一列,只需要检查一个误差项的符号,就可以确定该列的所有对象。
根据直线的斜率确定选择变量在X方向上或在Y方向上每次递增一个单位,另一变量的增量为0或1,它取决于实际直线与最近网格点位置的距离,这一距离称为误差。
设第k步的误差为ek,选取上面象素点后的积累误差为:ek+1﹦ek﹢(m﹣1)选取下面的象素点后的积累误差为:ek+1﹦ek﹢m/* Bresenham */程序代码如下:#include <graphics.h>#include <conio.h>// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点)void Line_Bresenham(int x1, int y1, int x2, int y2, int color){int x = x1;int y = y1;int dx = abs(x2 - x1);int dy = abs(y2 - y1);int s1 = x2 > x1 ? 1 : -1;int s2 = y2 > y1 ? 1 : -1;bool interchange = false; // 默认不互换 dx、dyif (dy > dx) // 当斜率大于 1 时,dx、dy 互换{int temp = dx;dx = dy;dy = temp;interchange = true;}int p = 2 * dy - dx;for(int i = 0; i < dx; i++){putpixel(x, y, color);if (p >= 0){if (!interchange) // 当斜率 < 1 时,选取上下象素点y += s2;else // 当斜率 > 1 时,选取左右象素点x += s1;p -= 2 * dx;}if (!interchange)x += s1; // 当斜率 < 1 时,选取 x 为步长elsey += s2; // 当斜率 > 1 时,选取 y 为步长p += 2 * dy;}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_Bresenham(10, 100, 100, 478,BLUE);Line_Bresenham(10, 478, 638, 1, RED);// 按任意键退出getch();}运行结果如下:。
直线生成算法——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所示如图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是修改后的程序运行结果。
Bresenham画线算法详解及其OpenGL编程实现
Bresenham画线算法详解及其OpenGL编程实现Bresenham是由Bresenham提出的⼀种精确⽽有效地光栅线⽣成算法,该算法仅使⽤增量整数计算。
另外,它还可以⽤于显⽰其它曲线。
我们以斜率⼤于0⼩于1的线段来进⾏考虑。
以单位x间隔进⾏取样。
每次绘制了当前像素点(x k,y k)之后,需要确定下⼀个要绘制的点是(x k+1,y k)还是(x k+1,y k+1),需要判断哪⼀个点像素点更接近线路径。
在取样位置,我们使⽤d1和d2来表⽰两个像素和线路径的偏移。
在像素列位置x k+1处的直线上的y坐标可计算为:y=m(x k+1)+b那么:d1=y-y k=m(x k+1)+b-y kd2=(y k+1)-y=y k+1-m(x k+1)-b要确定那个像素点更接近于线路径,需测试这两个像素的偏移的差:d1-d2=2m(x k+1)-2y k+2b-1为了使⽤整数进⾏计算,将决策参数定义为:p k=dx*(d1-d2)=2*x k-2dx*y k+cpk和d1-d2符号相同。
其中m=dy/dx,c=2dy+dx(2b-1)。
C是常量,与像素位置⽆关且会在循环计算pk时被消除。
假如y k处的像素⽐y k+1处的像素更接近于线路径,则pk为负,绘制下⾯的像素。
反之为正,绘制上⾯的像素。
我们可以利⽤递增整数运算得到后继的决策参数值。
由k的式⼦可以得出:p k+1=2dy*x k+1-2dx*y k+1+c则:p k+1-p k=2dy(x k+1-x k)-2dx(y k+1-y k)p k+1=p k+2dy-2dx(y k+1-y k)⽽y k+1-y k取1或者0取决于p k的符号。
⽽起始像素位置(x0,y0)的参数p0可以计算得出:再分享⼀下我⽼师⼤神的⼈⼯智能教程吧。
零基础!通俗易懂!风趣幽默!还带黄段⼦!希望你也加⼊到我们⼈⼯智能的队伍中来!p0=2dy-dx由此可以得出斜率⼤于0⼩于1的Bresenham画线算法步骤如下:1、输⼊线段两个端点坐标,将左端点存储在(x0,y0)中;2、画出第⼀个点。
bresenham算法画直线例题
Bresenham算法是计算机图形学中常用的一种画直线的算法。
它的原理是利用像素点在屏幕上的排列规律,从而高效地计算出直线上的像素点。
本文将以一个具体的例题来说明Bresenham算法的原理及应用。
1. 问题描述假设我们需要在一个分辨率为800x600的屏幕上,画一条直线,起点坐标为(100, 200),终点坐标为(400, 300)。
请使用Bresenham算法计算直线上的像素点,并用符号“*”表示出来。
2. Bresenham算法原理Bresenham算法的核心思想是利用像素点的整数坐标值与直线的斜率之间的关系,从而逐个确定直线上的像素点。
具体步骤如下:- 计算直线的斜率k,即k = (y2 - y1) / (x2 - x1),其中(x1, y1)为起点坐标,(x2, y2)为终点坐标。
- 以起点坐标作为初始值,从左至右依次求解直线上各点像素的坐标。
- 对于每一个x坐标,根据斜率k的大小确定y坐标的增长方向。
3. Bresenham算法应用根据上述原理,我们来解决具体的例题。
计算直线的斜率k:k = (300 - 200) / (400 - 100) = 1/3以起点坐标(100, 200)作为初始值,从左至右依次求解直线上各点像素的坐标。
当x坐标从100递增至400时,y坐标的增长方向由斜率k来确定。
具体计算如下:- 当x=100时,y=200- 当x=101时,y=200+1/3≈200- 当x=102时,y=200+2/3≈201- ...- 当x=400时,y=300现在,我们可以得到直线上的像素点坐标,并用符号“*”表示出来。
4. 结果展示根据上述计算,我们可以得到该直线上的像素点坐标,展示如下:(100, 200) *(101, 200) *(102, 201) *...(400, 300) *通过Bresenham算法,我们成功地计算出了直线上的像素点,并用符号“*”进行了展示。
bresenham画线算法详解
给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。
假设直线的斜率0<k>0,直线在第一象限,Bresenham算法的过程如下:1.画起点(x1, y1).2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。
否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。
2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点2.2.否则选右下那个点。
3.画点4.跳回第2步5.结束具体的算法如下,原理就是比较目标直线与x+1直线交点的纵坐标,哪个离交点近就去哪个void Bresenhamline(int x0, int y0, int x1, int y1, int color){int x, y, dx, dy;float k, e;dx = x1 - x0;dy = y1 - y0;k = dy / dx;e = -0.5;x = x0;y = y0;for (x= x0;x < x1; x++){drawpixel(x, y, color);//这个是画点子函数e = e + k;if (e > 0){y++;e = e - 1;}}}上述Bresenham算法在计算直线斜率与误差项时用到小数与除法。
可以改用整数以避免除法。
等式两边同时乘以2*dx,得到2*e*dx = 2*e*dx + 2dy, 2*e*dx = 2*e*dx - 2*dx.由于算法中只用到误差项的符号,因此可作如下替换:2*e*dx.改进的Bresenham画线算法程序:将e统一乘以2*dx即变成了整数的Bresenhan算法了,^_^void InterBresenhamline (int x0, int y0, int x1, int y1, int color){int dx = x1 - x0;int dy = y1 - y0;int dx2 = dx << 1;//乘2int dy2 = dy << 1;//乘2int e = -dx;int x = x0;int y = y0;for (x = x0; x < x1; x++){drawpixel (x, y, color);e=e + dy2;if (e > 0){y++;e = e - dx2;}}}。
Bresenham算法-直线光栅化算法
Bresenham算法是计算机图形学典型的直线光栅化算法。
∙从另一个角度看直线光栅化显示算法的原理o由直线的斜率确定选择在x方向或y方向上每次递增(减)1个单位,另一变量的递增(减)量为0或1,它取决于实际直线与最近光栅网格点的距离,这个距离的最大误差为0.5。
∙1)Bresenham的基本原理o假定直线斜率k在0~1之间。
此时,只需考虑x方向每次递增1个单位,决定y方向每次递增0或1。
设直线当前点为(xi,y)直线当前光栅点为(xi,yi)则下一个直线的点应为(xi+1,y+k)下一个直线的光栅点或为右光栅点(xi+1,yi)(y方向递增量0)或为右上光栅点(xi+1,yi+1)(y方向递增量1)记直线与它垂直方向最近的下光栅点的误差为d,有:d=(y+k)–yi,且0≤d≤1当d<0.5:下一个象素应取右光栅点(xi+1,yi)当d≥0.5:下一个象素应取右上光栅点(xi+1,yi+1)如果直线的(起)端点在整数点上,误差项d的初值:d0=0,x坐标每增加1,d的值相应递增直线的斜率值k,即:d=d + k。
一旦d≥1,就把它减去1,保证d的相对性,且在0-1之间。
令e=d-0.5,关于d的判别式和初值可简化成:e的初值e0= -0.5,增量亦为k;e<0时,取当前象素(xi,yi)的右方象素(xi+1,yi);e>0时,取当前象素(xi,yi)的右上方象素(xi+1,yi+1);e=0时,可任取上、下光栅点显示。
Bresenham算法的构思巧妙:它引入动态误差e,当x方向每次递增1个单位,可根据e 的符号决定y方向每次递增 0 或 1。
e<0,y方向不递增e>0,y方向递增1x方向每次递增1个单位,e = e + k因为e是相对量,所以当e>0时,表明e的计值将进入下一个参考点(上升一个光栅点),此时须:e = e - 1∙2)Bresenham算法的实施——Rogers 版o通过(0,0)的所求直线的斜率大于0.5,它与x=1直线的交点离y=1直线较近,离y=0直线较远,因此取光栅点(1,1)比(1,0)更逼近直线;o如果斜率小于0.5,则反之;o当斜率等于0.5,没有确定的选择标准,但本算法选择(1,1)(程序)▪//Bresenham's line resterization algorithm for the first octal.▪//The line end points are (xs,ys) and (xe,ye) assumed not equal.▪// Round is the integer function.▪// x,y, ∆x, ∆y are the integer, Error is the real.▪//initialize variables▪x=xs▪y=ys▪∆x = xe -xs▪∆y = ye -ys▪//initialize e to compensate for a nonzero intercept▪Error =∆y/∆x-0.5▪//begin the main loop▪for i=1 to ∆x▪ WritePixel (x, y, value)▪if (Error ≥0) then▪ y=y+1▪ Error = Error -1▪ end if▪ x=x+1▪ Error = Error +∆y/∆x▪next i▪finish∙3)整数Bresenham算法o上述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中点画线算法
先标明这转载自/xxxxxx91116/article/details/6295714直线扫描算法之---bresenham改进算法(任何斜率,任何方向)by zxx图形学神马的全都是数学,看来以后我不能搞这个,伤脑筋,所以先把我现在懂得先记录下来吧。
不过呢,我的水平实在有限,对于算法这种东西实在难以说明白,请大家包涵。
书上讲的实在是太过简略,所以这里我把一些简单的推导过程都记录下来:1.重温bresenham未改进算法(斜率在0-1之间的直线)我想要记录的是bresenham改进算法,所以在讲解改进算法之前,我先用一个简单的例子说明一下未改进算法的思想:这是一个斜率k在0-1之间的一条直线,我就用斜率为0-1之间的直线来重温:首先,如图1所示,假设x列的像素已定,其坐标为(x,y),那么下一个坐标一定是:(x+1,y+1)或者(x+1,y)。
而是哪一个取决于d的值,如果d>0.5那么就是(x+1,y+1),如果d<0.5,那么就是(x+1,y),而d是什么呢?当然是斜率了。
(原因如下:y=kx+b当x增加1时:y=kx+k+b所以当x增加1是,y方向的增量是d。
)所以每次我们只需要让d=d+k(k是斜率)即可,当d>=1时,就让d减一,这样就保证了d在0-1之间。
当d>0.5,下一个点取(x+1,y+1)当d<0.5,下一个点取(x+1,y)然后呢,我们为了判断的方便,让e=d-0.5,这样就变成了:当e>0,下一个点取(x+1,y+1)当e<0,下一个点取(x+1,y)2.过渡,重温之后,我们就想要改进,为什么要改进呢?因为我们这里面有0.5,还有k,k里面有dx/dy,这些除法和小数都不是我们想要的,我们想要的是,只有整数,且只有加法的算法,下面就全面讨论一下改进算法。
3.改进算法篇(不同斜率,不同方向)这里,我们主要分为4个角度来说明:A.斜率在0-1只间B.斜率在1-无穷之间C.斜率在0-(-1)之间D.斜率在(-1)-负无穷之间E.两种特殊情况,两条直线。
计算机图形学--Bresenham完整算法-画直线、椭圆和圆
#include<windows.h>#include<gl/glut.h>#include"stdio.h"int m_PointNumber = 0; //动画时绘制点的数目int m_DrawMode = 1; //绘制模式 1 DDA算法画直线// 2 中点Bresenham算法画直线// 3 改进Bresenham算法画直线// 4 八分法绘制圆// 5 四分法绘制椭圆//绘制坐标线void DrawCordinateLine(void){int i = -250 ;//坐标线为黑色glColor3f(0.0f, 0.0f ,0.0f);glBegin(GL_LINES);for (i=-250;i<=250;i=i+10){glVertex2f((float)(i), -250.0f);glVertex2f((float)(i), 250.0f);glVertex2f(-250.0f, (float)(i));glVertex2f(250.0f, (float)(i));}glEnd();}//绘制一个点,这里用一个正方形表示一个点void putpixel(GLsizei x, GLsizei y){glRectf(10*x,10*y,10*x+10,10*y+10);}/////////////////////////////////////////////////////////////////////DDA画线算法 //// //// //// /////////////////////////////////////////////////////////////////////void DDACreateLine(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num) {//设置颜色glColor3f(1.0f,0.0f,0.0f);//对画线动画进行控制if(num == 1)printf("DDA画线算法:各点坐标\n");else if(num==0)return;//画线算法的实现GLsizei dx,dy,epsl,k;GLfloat x,y,xIncre,yIncre;dx = x1-x0;dy = y1-y0;x = x0;y = y0;if(abs(dx) > abs(dy)) epsl = abs(dx);else epsl = abs(dy);xIncre = (float)dx / epsl ;yIncre = (float)dy / epsl ;for(k = 0; k<=epsl; k++){putpixel((int)(x+0.5), (int)(y+0.5));if (k>=num-1) {printf("x=%f , y=%f,取整后 x=%d,y=%d\n", x, y, (int)(x+0.5),(int)(y+0.5));break;}x += xIncre;y += yIncre;if(x >= 25 || y >= 25) break;}}/////////////////////////////////////////////////////////////////////中点Bresenham算法画直线(0<=k<=1) //// //// //// /////////////////////////////////////////////////////////////////////void BresenhamLine(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num){glColor3f(1.0f,0.0f,0.0f);if(num == 1)printf("中点Bresenham算法画直线各点坐标及判别式的值\n");else if(num==0)return;//画线算法的实现GLsizei p=0;GLfloat UpIncre,DownIncre,x,y,d,k,dx,dy;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}x=x0;y=y0;dx=x1-x0;dy=y1-y0;k=dy/dx;if(k>=0&&k<=1){d=dx-2*dy;UpIncre=2*dx-2*dy;DownIncre=-2*dy;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;if(d<0){y++;d+=UpIncre;}else d+=DownIncre;}}if(k>1){d=dy-2*dx;UpIncre=2*dy-2*dx;DownIncre=-2*dx;while(y<=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y++;if(d<0){x++;d+=UpIncre;}else d+=DownIncre;}}if(k<0&&k>=-1){d=dx-2*dy;UpIncre=-2*dy;DownIncre=-2*dx-2*dy;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;if(d>0){y--;d+=DownIncre;}else d+=UpIncre;}}if(k<-1){d=-dy-2*dx;UpIncre=-2*dx-2*dy;DownIncre=-2*dx;while(y>=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y--;if(d<0){x++;d+=UpIncre;}else d+=DownIncre;}}}/////////////////////////////////////////////////////////////////////改进的Bresenham算法画直线(0<=k<=1) //// //// x1,y1 终点坐标 //// /////////////////////////////////////////////////////////////////////void Bresenham2Line(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num) {glColor3f(1.0f,0.0f,0.0f);GLsizei x,y,dx,dy,e,k;if(num == 1)printf("改进的Bresenham算法画直线各点坐标及判别式的值\n");else if(num==0)return;//画线算法的实现GLsizei p=0;if(x0>x1){x=x1;x1=x0;x0=x;y=y1;y1=y0;y0=y;}dx=x1-x0;dy=y1-y0;k=dy/dx;if(k>=0&&k<=1){e=-dx;x=x0;y=y0;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;e=e+2*dy;if(e>0){y++;e=e-2*dx;}}}if(k>1){e=-dy;x=x0;y=y0;while(y<=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y++;e=e+2*dx;if(e>0){x++;e=e-2*dy;}}}if(k<0&&k>=-1){e=-dx;x=x0;y=y0;while(x<=x1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;x++;e=e+2*dy;if(e<0){y--;e=e+2*dx;}}}if(k<-1){e=-dy;x=x0;y=y0;while(y>=y1){putpixel(x,y);if (p>=num-1) {printf("x=%d,y=%d\n", x, y);break;}p++;y--;e=e-2*dx;if(e<0){x++;e=e-2*dy;}}}}///////////////////////////////////////////////////////////Bresenham算法画圆 //// //// //// ///////////////////////////////////////////////////////////void CirclePoint(GLsizei x,GLsizei y){ putpixel(x,y);putpixel(x,-y);putpixel(y,-x);putpixel(-y,-x);putpixel(-x,-y);putpixel(-x,y);putpixel(-y,x);putpixel(y,x);}void BresenhamCircle(GLsizei x, GLsizei y, GLsizei R, GLsizei num) {glColor3f(1.0f,0.0f,0.0f);GLsizei d;x=0;y=R;d=1-R;if(num == 1)printf("Bresenham算法画圆:各点坐标及判别式的值\n");else if(num==0)return;while(x<=y){CirclePoint(x,y);if (x>=num-1) {printf("x=%d,y=%d,d=%d\n", x, y,d);break;}if(d<0)d+=2*x+3;else{d+=2*(x-y)+5;y--;}x++;}}void Bresenham2Circle(GLsizei a,GLsizei b,GLsizei num){glColor3f(1.0f,0.0f,0.0f);if(num==1)printf("Bresenham算法画椭圆:各点坐标及判别式的值\n");else if(num==0)return;GLsizei x,y;float d1,d2;x=0;y=b;d1=b*b+a*a*(-b+0.5);putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);while(b*b*(x+1)<a*a*(y-0.5)){if (x>=num-1) {printf("x=%d,y=%d,d1=%d\n", x, y,d1);break;}if(d1<=0){d1+=b*b*(2*x+3);x++;}else{d1+=b*b*(2*x+3)+a*a*(-2*y+2);x++;y--;}putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);}//while上半部分d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;while(y>0){if (x>=num-1) {printf("x=%d,y=%d,d2=%d\n", x, y,d2);break;}if(d2<=0){d2+=b*b*(2*x+2)+a*a*(-2*y+3);x++;y--;}else{d2+=a*a*(-2*y+3);y--;}putpixel(x,y); putpixel(-x,-y);putpixel(-x,y);putpixel(x,-y);}}//初始化窗口void Initial(void){// 设置窗口颜色为蓝色glClearColor(0.0f, 0.0f, 1.0f, 1.0f);}// 窗口大小改变时调用的登记函数void ChangeSize(GLsizei w, GLsizei h){if(h == 0) h = 1;// 设置视区尺寸glViewport(0,0, w, h);// 重置坐标系统glMatrixMode(GL_PROJECTION);glLoadIdentity();// 建立修剪空间的范围if (w <= h)glOrtho (-250.0f, 250.0f, -250.0f, 250.0f*h/w, 1.0, -1.0);elseglOrtho (-250.0f, 250.0f*w/h, -250.0f, 250.0f, 1.0, -1.0);}// 在窗口中绘制图形void ReDraw(void){//用当前背景色填充窗口glClear(GL_COLOR_BUFFER_BIT);//画出坐标线DrawCordinateLine();switch(m_DrawMode){case 1:DDACreateLine(0,0,20,15,m_PointNumber);break;case 2:BresenhamLine(0,0,-20,15,m_PointNumber);break;case 3:Bresenham2Line(1,1,8,6,m_PointNumber);break;case 4:BresenhamCircle(0,0,20,m_PointNumber);break;case 5:Bresenham2Circle(10,8,m_PointNumber);default:break;}glFlush();}//设置时间回调函数void TimerFunc(int value){if(m_PointNumber == 0)value = 1;m_PointNumber = value;glutPostRedisplay();glutTimerFunc(500, TimerFunc, value+1);}//设置键盘回调函数void Keyboard(unsigned char key, int x, int y) {if (key == '1') m_DrawMode = 1;if (key == '2') m_DrawMode = 2;if (key == '3') m_DrawMode = 3;if (key == '4') m_DrawMode = 4;if (key == '5') m_DrawMode = 5;m_PointNumber = 0;glutPostRedisplay();}//void main(void)int main(int argc, char* argv[]){glutInit(&argc, argv);//初始化GLUT库OpenGL窗口的显示模式glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(600,600);glutInitWindowPosition(100,100);glutCreateWindow("基本图元绘制程序);glutDisplayFunc(ReDraw);glutReshapeFunc(ChangeSize);glutKeyboardFunc(Keyboard);//键盘响应回调函数glutTimerFunc(500, TimerFunc, 1);// 窗口初始化Initial();glutMainLoop(); //启动事件处理循环return 0;}。
Bresenham画线算法
以前看到Bresenham画线算法,直接拿来用,没有去推导它,近日,参考一些资料,特整理其算法推导过程如下。
各位大虾如果知道其细节,赶紧闪过,不用浪费时间了。
基本上Bresenham画线算法的思路如下:// 假设该线段位于第一象限内且斜率大于0小于1,设起点为(x1,y1),终点为(x2,y2).// 根据对称性,可推导至全象限内的线段.1.画起点(x1,y1).2.准备画下个点。
x坐标增1,判断如果达到终点,则完成。
否则,由图中可知,下个要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点.2.1.如果线段ax+by+c=0与x=x1+1的交点的y坐标大于M点(即中点)的y坐标的话,下个点为U(x1+1,y1+1)2.2.否则,下个点为B(x1+1,y1)3.画点(U或者B).4.跳回第2步.5.结束.这里需要细化的是怎么判断下个要画的点为当前点的右邻接点还是当前点的右上邻接点.设线段方程:ax+by+c=0(x1<x<x2,y1<y<y2)令dx=x2-x1,dy=y2-y1则:斜率-a/b = dy/dx.从第一个点开始,我们有F(x,1,y1) = a*x1+b*y1+c=0下面求线段ax+by+c=0与x=x1+1的交点:由a*(x1+1)+b*y+c = 0, 求出交点坐标y=(-c-a(x1+1))/b所以交点与M的y坐标差值Sub1 = (-c-a(x1+1))/b - (y1+0.5) = -a/b-0.5,即Sub1的初始值为-a/b-0.5。
则可得条件当Sub1 = -a/b-0.5>0时候,即下个点为U.反之,下个点为B.代入a/b,则Sub1 = dy/dx-0.5.因为是个循环中都要判断Sub,所以得求出循环下的Sub表达式,我们可以求出Sub的差值的表达式.下面求x=x1+2时的Sub,即Sub2 1.如果下下个点是下个点的右上邻接点,则Sub2 = (-c-a(x1+2))/b - (y1+1.5) = -2a/b - 1.5故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 1.5 - (-a/b-0.5) = -a/b - 1.代入a/b得Dsub = dy/dx -1;2.如果下下个点是下个点的右邻接点,Sub2 = (-c-a(x1+2))/b - (y1+0.5) = -2a/b - 0.5故Sub差值Dsub = Sub2 - Sub1 = -2a/b - 0.5 - (-a/b-0.5) = -a/b. 代入a/b得Dsub = dy/dx;于是,我们有了Sub的初始值Sub1 = -a/b-0.5 = dy/dx-0.5,又有了Sub的差值的表达式Dsub = dy/dx -1 (当Sub1 > 0)或dy/dx(当Sub1 < 0).细化工作完成。
中点bresenham算法的基本原理与递推公式
中点Bresenham算法是一种用于绘制直线的光栅化算法,它可以在计算机图形学中高效地绘制直线,尤其适用于嵌入式系统和低性能设备。
本文将介绍中点Bresenham算法的基本原理和递推公式。
一、中点Bresenham算法的基本原理1.1 数值方式直线的差值算法在了解中点Bresenham算法之前,我们需要先了解数值方式直线的差值算法。
通过计算两个端点的坐标差值,可以得到直线的斜率和步长,从而在光栅化的像素网格上绘制直线。
然而,这种算法需要进行浮点数运算,对于嵌入式系统和低性能设备来说,性能较差。
1.2 中点Bresenham算法的优势中点Bresenham算法通过整数运算和递推公式来高效地绘制直线,避免了浮点数运算的开销,因此在嵌入式系统和低性能设备上具有很高的应用价值。
它利用了直线的对称性和整数坐标的特点,通过逐个像素的递推计算来实现直线的绘制。
1.3 算法的基本思想中点Bresenham算法的基本思想是从直线的起点到终点,在每一步选择最接近直线的像素作为下一个像素,从而逐步绘制整条直线。
通过比较像素的位置和理想直线的位置关系,选择最接近直线的像素进行绘制,从而得到了中点Bresenham算法的递推过程。
二、中点Bresenham算法的递推公式2.1 直线斜率的计算我们需要计算直线的斜率m。
对于给定的两个端点P1(x1, y1)和P2(x2, y2),直线的斜率可以通过以下公式计算得到:m = (y2 - y1) / (x2 - x1)2.2 中点Bresenham算法的关键递推公式中点Bresenham算法通过比较像素的位置和理想直线的位置关系,选择最接近直线的像素进行绘制。
其关键递推公式如下:对于斜率0 ≤ m ≤ 1的直线:d = 2 * (y - y0) - (x - x0)若d < 0,则选择(x, y)为下一个像素,d = d + 2 * (y1 - y0)若d ≥ 0,则选择(x, y)为下一个像素,d = d + 2 * (y1 - y0) - 2 * (x1 - x0)对于斜率m > 1的直线:d = 2 * (x - x0) - (y - y0)若d < 0,则选择(x, y)为下一个像素,d = d + 2 * (x1 - x0)若d ≥ 0,则选择(x, y)为下一个像素,d = d + 2 * (x1 - x0) - 2 * (y1 - y0)2.3 递推过程通过以上递推公式,我们可以在每一步选择最接近直线的像素进行绘制,从而逐步绘制整条直线。
bresenham算法画直线例题
bresenham算法画直线例题摘要:一、引言二、Bresenham 算法的原理1.计算机显示的直线是离散的2.用一系列离散化后的点(像素)来近似表现直线三、Bresenham 算法的实现1.第一个版本:将直线分成10 份,每一份画一个像素2.优化版本:Bresenham 算法四、Bresenham 算法的优点1.计算简单2.能够快速绘制直线五、Bresenham 算法的局限性1.直线的精度受限于像素数量六、结论正文:一、引言在计算机图形学中,绘制直线是一个基本任务。
然而,由于计算机显示的直线是离散的,我们无法直接绘制连续的直线。
为了解决这个问题,Bresenham 算法应运而生。
该算法通过用一系列离散化后的点(像素)来近似表现直线,从而实现在计算机上绘制直线。
二、Bresenham 算法的原理在计算机图形学中,绘制直线的过程实际上是将直线分成若干个离散的点,然后在屏幕上绘制这些点。
由于计算机显示的精度有限,我们无法直接绘制连续的直线,因此需要用一系列离散化后的点(像素)来近似表现直线。
Bresenham 算法是一种经典的直线绘制算法,它的基本原理是:在直线上的两个点A 和B 之间,选取一个点C,使得线段AC 和线段CB 的斜率相等。
然后,通过计算点C 的坐标,将其绘制在屏幕上。
重复这个过程,直到线段AB 的两个端点都被绘制出来。
三、Bresenham 算法的实现1.第一个版本:将直线分成10 份,每一份画一个像素在第一个版本中,我们将直线分成10 份,每一份画一个像素。
这种方法虽然简单,但是效果并不理想,因为直线中间会有很多空洞,显得不连续。
2.优化版本:Bresenham 算法为了解决这个问题,我们引入了Bresenham 算法。
该算法通过计算点C 的坐标,使得线段AC 和线段CB 的斜率相等,从而实现在计算机上绘制连续的直线。
Bresenham 算法的计算过程较为简单,能够快速绘制直线。
四、Bresenham 算法的优点Bresenham 算法具有以下优点:1.计算简单:Bresenham 算法的计算过程较为简单,容易实现。
Bresenham算法
Bresenham算法⼀ Bresenham 绘直线使⽤ Bresenham 算法,可以在显⽰器上绘制⼀直线段。
该算法主要思想如下:1 给出直线段上两个端点,根据端点求出直线在X,Y⽅向上变化速率;2 当时,X ⽅向上变化速率快于 Y ⽅向上变化速率,选择在 X ⽅向上迭代,在每次迭代中计算 Y 轴上变化;当时,Y ⽅向上变化速率快于 X ⽅向上变化速率,选择在 Y ⽅向上迭代,在每次迭代中计算 X 轴上变化;3 现在仅考虑情形,在情况下仅需要交换变量即可。
直线斜率,当 d = 0 时,为⼀条⽔平直线,当 d > 0 或 d < 0 时,需要分开讨论,如下图:⼆ Bresenham 绘圆使⽤ Bresenham 绘制圆形,只需要绘制四分之⼀圆即可,其他部分通过翻转图形即可得到。
假设圆⼼位于 (0, 0) 点,半径为 R,绘制第⼀象限四分之⼀圆形,如下图:根据图形可知,从出发,下⼀个可能的选择分别为:1)⽔平⽅向上;2)对⾓⽅向上;3)垂直⽅向上;下⾯计算,根据差值可判断⼤致圆弧位置:1)当时,圆环落在与之间,进⼀步计算圆弧到与的距离以判断应该落在哪个点上;2),由于,,上式可化简为,,将改写为得:,已知,可根据上式快速求解出,当时,下⼀点落在上,当时,下⼀点落在上;3)当时,圆环落在与之间,进⼀步计算圆弧到和的距离以判断应该落在哪个点上;4),可化简为:,将改写为得:,已知,可根据上式快速求解出,当时,下⼀点落在上,当时,下⼀点落在上;5)以上推导中,已知可以快速求解,同时,已知也可以快速推导出,以下分类讨论:a. 当时,有:,进⼀步整理得:;b. 当时,有:,进⼀步整理得:;c. 当时,有:,进⼀步整理得:。
以下给出 Bresenham 绘圆实现:1void Bresenham_Circle(PairS center, int radius, std::vector<PairS>& circle)2 {3 PairS start(0, radius);4int Delta = (start.x + 1) * (start.x + 1) +5 (start.y - 1) * (start.y - 1) - radius * radius;67 std::vector<PairS> tmp;8 tmp.push_back(start);910while (start.y > 0)11 {12int state = -1;1314if (Delta < 0)15 {16int delta = (Delta + start.y) * 2 - 1;17if (delta < 0)18 {19 start.x += 1;20 state = 0;21 }22else23 {24 start.x += 1;25 start.y -= 1;26 state = 1;27 }28 }29else30 {31int delta = (Delta - start.x) * 2 - 1;32if (delta < 0)33 {34 start.x += 1;35 start.y -= 1;36 state = 1;37 }38else39 {40 start.y -= 1;41 state = 2;42 }43 }4445if (state == 0)46 Delta = Delta + start.x * 2 + 1;47else if (state == 1)48 Delta = Delta + start.x * 2 - start.y * 2, +2;49else if (state == 2)50 Delta = Delta - start.y * 2 + 1;51else52break;5354 tmp.push_back(start);55 }5657 std::vector<PairS> tmp2;58for (int i = 0; i < tmp.size(); ++i)59 {60 PairS p(tmp[i].x, tmp[i].y);61 tmp2.push_back(p);62 }63for (int i = tmp.size() - 1; i >= 0; --i)64 {65 PairS p(tmp[i].x, -tmp[i].y);66 tmp2.push_back(p);67 }68for (int i = 0; i < tmp2.size(); ++i)69 {70 PairS p(tmp2[i].x, tmp2[i].y);71 circle.push_back(p);72 }7374for (int i = tmp2.size() - 1; i >= 0; --i)75 {76 PairS p(-tmp2[i].x, tmp2[i].y);77 circle.push_back(p);78 }7980for (int i = 0; i < circle.size(); ++i)81 {82 circle[i].x += center.x;83 circle[i].y += center.y;84 }85 }参考资料计算机图形学得算法基础 David E Rogers。
Bresenham快速画直线算法
Bresenham快速画直线算法⼀、算法原理简介:算法原理的详细描述及部分实现可参考: 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 ← y1For x ← x1 to x2 doPlot Point at (x, y)If (2(ξ + dy) < dx)ξ←ξ + dyElsey ← y + 1,ξ←ξ + dy – dxEnd IfEnd For⼆、算法的注意点:Fig. 2在实际应⽤中,我们会发现,当dy > dx或出现Fig.2 右图情况时时,便得不到想要的结果,这是由于我们只考虑dx > dy,且x, y的增量均为正的情况所致。
经过分析,需要考虑8种不同的情况,如Fig. 3所⽰:(Fig. 3)当然,如果直接在算法中对8种情况分别枚举,那重复代码便会显得⼗分臃肿,因此在设计算法时必须充分考虑上述各种情况的共性,后⾯将给出考虑了所有情况的实现代码。
实验报告(Bresenham画线算法)
实验报告(Bresenham画线算法)一、实验目得根据Bresenham画线算法,掌握绘制直线得程序设计方法。
二、实验原理为了说明算法原理,我们首先考虑斜率非负且不超过 1 得直线得光栅化过程。
设直线得起点坐标为 (x s , ys),终点坐标为(x e ,ye),则直线得方程为:因此,其隐函数表示为:其中:显然,对于直线上得点,F(x , y)等于零;对于直线下方得点,F(x , y)大于零;而对直线上方得点,F(x,y) 小于零。
假设当前选择得像素点就是 (xi , yi),那么下一步要选择得像素点可能就是 NE (xi+1,yi+1),也可能就是 E (xi+1 , yi)。
选择得原则就是瞧哪一个离直线与x= xi+1得交点最近。
运用中点法则,我们只需考察中点 M 在直线得哪一侧,即计算:F(M) = F(xi + 1, yi + 1/2) = a(xi + 1) + b( yi + 0、5) + c并确定其正负号.由于根据函数值F(xi+1, yi + 1/2) 进行判定,所以我们定义一个判定函数如下:di= 2F(xi + 1, yi +1/2)根据定义:di = 2a(xi + 1) + 2byi + b + 2c当 d i 〈0 时,M 在直线得上方,取 E 为下一个像素点;当 d 〉0时, M 在直线得下方,取NE 为下一个像素点;当 d = 0时,两者都可以选,我们约定选 E。
di 得计算需要做4次加法与两次乘法。
因此,为了有效地计算判定函数,我们需要建立关于 di得递推公式。
显然,di 得变化依赖于下一个像素点选得就是 NE 还就是 E。
当 di 〈 0 时,下一个像素点就是 E,那么:di+1=2F(xi + 2, yi + 1/2)= 2a(xi + 2) +2byi + b +2c = di + 2a当 di > 0 时,下一个像素点就是NE,则:di+1= 2F(xi+2, yi+ 1 +1/2)=2a(xi+ 2) + 2b(yi+1)+b+2c= d i + 2a + 2b由此,得到计算判定函数 di 得递推公式:因为直线上得第一个像素点就就是直线得起点(xs, ys),所以判定函数di 得初值为:d0 = 2a(xs + 1) + 2bys + b + 2c = 2dy -dx故满足条件得直线得Bresnham 算法得步骤如下:Step 1、初始化dx = xe-xs ,dy = ye - ys , x = xs , y = ys , d = 2dy -dx;Step 2、当x〈xe 时,执行下述操作:(1)画像素点(x,y);(2)求下一个像素点:x = x + 1;if (d > 0)then y= y + 1;(3)计算判定函数 d:if (d 〉 0) then d =d+ 2dy -2dx;else d = d + 2dy;Step 3、算法结束。
1.论述直线的bresenham算法的原理,方法和步骤。
论述直线的bresenham算法的原理,方法和步骤。
Bresenham算法是一种用于计算直线段的算法,它是一种基于中点画线思想的折线逼近算法。
该算法可以在二维平面中以最小的误差逼近直线。
B resenham算法的主要优点是它只需要计算整数坐标,而不需要使用浮点数计算,因此运行速度快,精度高。
Bresenham算法的原理是:从直线的一个端点开始,按照一定的方向和步长绘制一系列点,直到另一个端点为止。
这些点之间的间距逐渐减小,使得视觉效果上形成一条直线。
在这个过程中,通过计算每个点的坐标,可以得到一条近似于直线的折线。
Bresenham算法的方法如下:1. 初始化参数:设定直线的两个端点坐标(x1,y1)和(x2,y2),以及画线的方向变量k。
初始方向k等于两点横坐标之差与纵坐标之差的比值,即k = (y2 - y1) / (x2 - x1)。
2. 计算第一个点:根据初始方向k,计算第一个点的坐标。
第一个点的横坐标为x1 + k/2,纵坐标为y1。
3. 迭代计算后续点:从第二个点开始,每次迭代都将当前点的横坐标加上k,纵坐标加上1/k。
同时,检查当前点的横坐标是否超过终点坐标x2,如果是,则结束绘制。
4. 输出结果:将计算出的所有点按照顺序连接起来,形成一条折线,这条折线近似于原始直线。
Bresenham算法的步骤如下:1. 初始化参数:设置直线的两个端点坐标和方向k。
2. 计算第一个点:根据方向k,计算第一个点的坐标。
3. 迭代计算后续点:按照迭代公式,依次计算出所有点的位置。
4. 输出结果:将计算出的所有点连接起来,形成一条折线。
5. 终止条件:当计算出的点的横坐标超过终点坐标时,绘制过程结束。
通过以上方法和步骤,Bresenham算法可以高效地绘制出直线段,适用于各种图形绘制和计算场景。
在实际应用中,可以根据需要调整算法的参数和精度,以满足不同的需求。
通用整数bresenham算法
通用整数bresenham算法
Bresenham算法是一种用于在计算机屏幕上绘制直线、圆和其
他形状的算法。
在这里,我将重点介绍通用整数Bresenham算法,
用于绘制直线。
通用整数Bresenham算法是一种用于在计算机屏幕上绘制直线
的算法。
它是一种基于整数运算的算法,因此在计算机上执行速度
很快。
该算法通过在每个步骤中选择最接近直线路径的像素来绘制
直线。
该算法的基本原理是利用斜率来确定下一个要绘制的像素。
在
每一步中,根据直线斜率的大小来决定是向横坐标方向移动一个像
素还是向纵坐标方向移动一个像素。
通过适当的取整和判断,Bresenham算法能够以非常高效的方式绘制直线。
通用整数Bresenham算法的优点之一是它不需要使用浮点运算,这使得它非常适合于嵌入式系统和其他资源受限的环境。
此外,该
算法的实现比较简单,适用于各种编程语言和平台。
然而,通用整数Bresenham算法也有一些局限性。
例如,当直
线的斜率非常大或非常小的时候,该算法可能会出现绘制的直线与实际直线有所偏差。
此外,对于对角线上的像素,该算法可能不够精确。
总的来说,通用整数Bresenham算法是一种高效的直线绘制算法,特别适合于需要在计算机屏幕上绘制直线的应用程序。
它的简单性和高效性使得它成为计算机图形学中常用的算法之一。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。
假设直线的斜率0<k>0,直线在第一象限,Bresenham算法的过程如下:
1.画起点(x1, y1).
2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。
否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。
2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点
2.2.否则选右下那个点。
3.画点
4.跳回第2步
5.结束
具体的算法如下,原理就是比较目标直线与x+1直线交点的纵坐标,哪个离交点近就去哪个void Bresenhamline(int x0, int y0, int x1, int y1, int color)
{
int x, y, dx, dy;
float k, e;
dx = x1 - x0;
dy = y1 - y0;
k = dy / dx;
e = -0.5;
x = x0;
y = y0;
for (x= x0;x < x1; x++)
{
drawpixel(x, y, color);//这个是画点子函数
e = e + k;
if (e > 0)
{
y++;
e = e - 1;
}
}
}
上述Bresenham算法在计算直线斜率与误差项时用到小数与除法。
可以改用整数以避免除法。
等式两边同时乘以2*dx,得到2*e*dx = 2*e*dx + 2dy, 2*e*dx = 2*e*dx - 2*dx.由于算法中只用到误差项的符号,因此可作如下替换:2*e*dx.改进的Bresenham画线算法程序:将e统一乘以2*dx即变成了整数的Bresenhan算法了,^_^
void InterBresenhamline (int x0, int y0, int x1, int y1, int color)
{
int dx = x1 - x0;
int dy = y1 - y0;
int dx2 = dx << 1;//乘2
int dy2 = dy << 1;//乘2
int e = -dx;
int x = x0;
int y = y0;
for (x = x0; x < x1; x++)
{
drawpixel (x, y, color);
e=e + dy2;
if (e > 0)
{
y++;
e = e - dx2;
}
}
}。