Bresenham算法
任意斜率bresenham算法
任意斜率bresenham算法Bresenham算法是一种经典的计算机图形学算法,用于在计算机屏幕上绘制直线。
它的主要特点是高效快速,并且不需要浮点数运算。
本文将介绍任意斜率下的Bresenham算法原理及实现方法。
一、原理介绍Bresenham算法的核心思想是利用整数计算代替浮点数计算,从而提高计算速度。
算法的基本原理是通过在直线路径上的每个像素点处做决策,选择最接近直线路径的像素点来绘制线段。
二、实现步骤1. 输入起点坐标(x0, y0)和终点坐标(x1, y1);2. 计算斜率的绝对值的倒数:dx = x1 - x0,dy = y1 - y0,abs(dx) > abs(dy)时,倒数为1/abs(dx),否则为1/abs(dy);3. 初始化误差项:e = -1/2;4. 初始化绘制点坐标:x = x0,y = y0;5. 进行循环,直到绘制到终点坐标:- 绘制当前点(x, y);- 更新误差项:e = e + abs(dy/dx);- 若误差项大于等于1,则纵坐标y加1,并更新误差项:e = e - 1;- 横坐标x加1;6. 绘制终点坐标。
三、代码实现下面是使用C语言实现任意斜率Bresenham算法的代码示例:```c#include <stdio.h>void drawLine(int x0, int y0, int x1, int y1) {int dx = x1 - x0;int dy = y1 - y0;int stepx = (dx > 0) ? 1 : -1;int stepy = (dy > 0) ? 1 : -1;dx = abs(dx);dy = abs(dy);int e = 0;int x = x0;int y = y0;if (dx > dy) {for (int i = 0; i <= dx; i++) {// 绘制当前点(x, y)if (e >= 0) {y += stepy;e -= dx;}x += stepx;e += dy;}} else {for (int i = 0; i <= dy; i++) { // 绘制当前点(x, y)if (e >= 0) {x += stepx;e -= dy;}y += stepy;e += dx;}}}int main() {int x0 = 0, y0 = 0;int x1 = 10, y1 = 5;drawLine(x0, y0, x1, y1);return 0;}```四、实例分析以起点坐标(0, 0)和终点坐标(10, 5)为例,通过Bresenham算法计算得到的直线路径如下图所示:```(0,0) (1,0) (2,1) (3,1) (4,2) (5,2) (6,3) (7,3) (8,4) (9,4) (10,5)```五、总结Bresenham算法是一种高效快速绘制直线的算法,通过利用整数计算代替浮点数计算,避免了浮点数运算的开销。
分别解释直线生成算法dda法,中点画线法和bresenham法的基本原理
分别解释直线生成算法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)绘制。
以上内容仅供参考,如需更多信息,建议查阅相关文献或咨询数学专业人士。
bresenham圆生成算法
bresenham圆生成算法Bresenham圆生成算法是一种经典的计算机图形学算法,用于在计算机屏幕上绘制圆形。
该算法是由美国计算机科学家Jack E. Bresenham于1965年发明的。
这个算法非常简单,但是它却非常有效,因为它只需要使用整数运算。
Bresenham圆生成算法的基本思想是使用一个叫做“决策参数”的变量来决定下一个像素点的位置。
该变量根据当前像素点到圆心的距离和半径之间的差异进行调整。
如果该差异小于0,则移动到右上方的像素点;否则,移动到右上方和正上方之间的像素点。
具体来说,Bresenham圆生成算法可以通过以下步骤来实现:1. 输入圆心坐标和半径。
2. 初始化x和y坐标为0,并计算出初始决策参数d=3-2r。
3. 在每个步骤中,检查当前像素点是否在圆内。
如果是,则将该像素点绘制出来;否则,不绘制。
4. 计算下一个像素点的位置。
如果d小于0,则移动到右上方;否则,移动到右上方和正上方之间。
5. 更新决策参数d。
Bresenham圆生成算法的优点是它非常快速和有效。
它只需要使用整数运算,因此可以在计算机上非常快速地执行。
此外,该算法还可以轻松地扩展到三维空间中的球体和其他形状。
尽管Bresenham圆生成算法已经有几十年的历史了,但它仍然是计算机图形学中最常用的算法之一。
它被广泛应用于游戏开发、计算机辅助设计、虚拟现实等领域。
此外,该算法还被用于许多其他领域,如数字信号处理和图像处理。
总之,Bresenham圆生成算法是一种简单而有效的计算机图形学算法。
它可以快速地绘制出圆形,并且可以轻松地扩展到其他形状。
尽管这个算法已经有几十年的历史了,但它仍然是计算机图形学中最常用的算法之一,并且在许多其他领域也得到了广泛应用。
直线的Bresenham算法
直线的Bresenham算法本算法由Bresenham在1965年提出。
设直线从起点(x1, y1)到终点(x2, y2)。
直线可表示为方程y=mx+b。
其中b = y1 - m * x1,我们的讨论先将直线方向限于1a象限(图2.1.1)在这种情况下,当直线光栅化时,x每次都增加1个单元,即xi+1=xi+1而y的相应增加应当小于1。
为了光栅化,yi+1只可能选择如下两种位置之一(图2.1.2)。
图2.1.2 yi+1的位置选择yi-1=yi 或者yi+1=yi+1选择的原则是看精确值y与yi及yi+1的距离d1及d2的大小而定。
计算式为:y=m(xi+1)+b (2.1.1)d1=y-yi (2.1.2)d2=yi+1-y (2.1.3)如果d1-d2>0,则yi+1=yi+1,否则yi+1=yi。
因此算法的关键在于简便地求出d1-d2的符号。
将式(2.1.1)、(2.1.2)、(2.1.3)代入d1-d2,得用dx乘等式两边,并以Pi=dx(d1-d2)代入上述等式,得Pi=2xidy-2yidx+2dy+dx(2b-1) (2.1.4)d1-d2是我们用以判断符号的误差。
由于在1a象限,dx总大于0,所以Pi仍旧可以用作判断符号的误差。
Pi+1为:Pi+1=Pi+2dy-2dx(yi+1-yi) (2.1.5)误差的初值P1,可将x1, y1,和b代入式(2.1.4)中的xi, yi而得到:P1=2dy-dx综述上面的推导,第1a象限内的直线Bresenham算法思想如下:1、画点(x1, y2); dx=x2-x1; dy=y2-y1;计算误差初值P1=2dy-dx; i=1;2、求直线的下一点位置:xi+1=xi+1;if Pi>0 则yi+1=yi+1;否则yi+1=yi;3、画点(xi+1, yi-1);4、求下一个误差Pi+1;if Pi>0 则Pi+1=Pi+2dy-2dx;否则Pi+1=Pi+2dy;5、i=i+1; if i<dx+1则转2;否则end。
Bresenham算法
Bresenham算法1 算法原理基本原理从某处摘得:设直线⽅程为y i+1=y i+k(x i+1-x i)+k。
假设列坐标象素已经确定为x i,其⾏坐标为y i。
那么下⼀个象素的列坐标为x i+1,⽽⾏坐标要么为y i,要么递增1为y i+1。
是否增1取决于误差项d的值。
误差项d的初值d0=0,x坐标每增加1,d的值相应递增直线的斜率值k,即d=d+k。
⼀旦d≥1,就把它减去1,这样保证d在0、1之间。
当d≥0.5时,直线与垂线x=x i+1交点最接近于当前象素(x i,y i)的右上⽅象素(x i+1,y i+1);⽽当d<0.5时,更接近于右⽅象素(x i+1,y i)。
为⽅便计算,令e=d-0.5,e的初值为-0.5,增量为k。
当e≥0时,取当前象素(x i,y i)的右上⽅象素(x i+1,y i+1);⽽当e<0时,取(x i,y i)右⽅象素(x i+1,y i)。
由于显⽰直线的像素点只能取整数值坐标,可以假设直线上第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。
d1 = Y - Y i = m(X i+1)+b - Y i; (1) d2 = (Y i+1) - Y = (Y i+1) - m(X i+1) - b; (2) 两个距离的差是: d1-d2 = 2m(X i+1) - 2Y i + 2b -1; (3) 对于公式(3): a:当此值为正时,d1>d2,说明直线上理论点离(X i+1,Y i+1)像素较近,下⼀个像素点应取(X i+1,Y i+1); b:当此值为负时,d1<d2,说明直线上理论点离(X i+1,Y i)像素较近,下⼀个像素点赢取(X i+1,Y i); c:当此值为零时,d1=d2,说明直线上理论点离上、下两个像素点的距离相等,取那个点都⾏,假设算法规定这种情况下取(X i+1,Y i+1)作为下⼀个像素点。
生成圆的bresenham算法原理描述详细
生成圆的bresenham算法原理描述详细Bresenham算法是计算机图形学中非常重要的算法之一,可以生成各种形状的图像。
其中,生成圆形图像的Bresenham算法也是应用比较广泛的算法之一。
本文将详细描述生成圆的Bresenham算法原理。
1. 圆的数学表示圆是一个几何图形,其数学表示为:x² + y² = r²,其中,x、y是圆上点的坐标,r是圆的半径。
因此,生成圆的Bresenham算法需要计算出符合该数学表示的所有点的坐标。
2. Bresenham算法的核心思想Bresenham算法的核心思想是利用对称性和递推式来快速计算出每个点的坐标。
对于圆而言,其有四分之一的区域可以通过对称性计算出来,而另外四分之三的区域可以通过递推式来得出。
3. 圆的对称性对于圆而言,其具有对称性,即当坐标为(x,y)在圆上时,也必然存在(y,x)、(y,-x)、(x,-y)、(-x,-y)、(-y,-x)、(-y,x)、(-x,y)在圆上的点,也就是说,直接通过圆的对称性可以得到大约四分之一的在圆上的点。
4. 圆的递推式对于圆的另外四分之三的部分,我们可以使用递推式来获得。
根据圆的坐标表示式x² + y² = r²,我们可以得到下届式:x² + y² - r² = 0根据这个方程,可以计算出下一个点的坐标为:x + 1, y 或 x + 1, y - 1如果采用当前点(x,y)的对称点来计算,比如(y,x),那么坐标可以改成:y + 1, x 或 y + 1, x - 1通过这种方式,就可以逐个计算出每个点的坐标了。
5. 算法步骤生成圆的Bresenham算法的步骤如下:1)确定圆的中心点的坐标和半径;2)以圆心为原点建立坐标系,以x轴为基准线向右,y轴向上;3)通过圆的对称性计算出直径上的点的坐标;4)使用递推式计算出剩余的坐标;5)根据得到的坐标渲染圆的边缘。
画圆形(Bresenham算法)
画圆形(Bresenham算法)下⾯先简要介绍常⽤的画圆算法(Bresenham算法),然后再具体阐述笔者对该算法的改进。
⼀个圆,如果画出了圆上的某⼀点,那么可以利⽤对称性计算余下的七段圆弧:Plot(x,y),Plot(y,x),Plot(y,-x),Plot(x,-y),Plot(-x,-y),Plot(-y,-x),Plot(-y,x),Plot(-x,y)。
1、Bresenham 画圆算法。
Bresenham算法的主要思想是:以坐标原点(0,0)为圆⼼的圆可以通过0度到45°的弧计算得到,即x从0增加到半径,然后利⽤对称性计算余下的七段圆弧。
当x从0增加到时,y从R递减到。
设圆的半径为R,则圆的⽅程为:f(x,y)=(x+1)2+y2-R2=0 (1)假设当前列(x=xi列)中最接近圆弧的像素已经取为P(xi,yi),根据第⼆卦限1/8圆的⾛向,下⼀列(x=xi+1列)中最接近圆弧的像素只能在P的正右⽅点H(xi+1,yi)或右下⽅点L(xi+1,yi-1)中选择,如图1所⽰。
Bresenham画圆算法采⽤点T(x,y)到圆⼼的距离平⽅与半径平⽅之差D(T)作为选择标准,即D(T)=(x+1)2+y2-R2 (2)通过⽐较H、L两点各⾃对实圆弧上点的距离⼤⼩,即根据误差⼤⼩来选取,具有最⼩误差的点为绘制点。
根据公式(2)得:对H(xi+1,yi)点有:D(H)=(xi+1)2+yi2-R2;对L(xi+1,yi-1)点有:D(L)=(xi+1)2+(yi-1)2-R2;根据Bresenham画圆算法,则选择的标准是:如果|D(H)|<|D(L)|,那么下⼀点选取H(xi+1,yi);如果|D(H)|>|D(L)|,那么下⼀点选取L(xi+1,yi-1);如果|D(H)|=|D(L)|,那么下⼀点可以取L(xi+1,yi-1),也可以选取H(xi+1,yi),我们约定选取H(xi+1,yi)。
任意斜率bresenham算法
任意斜率bresenham算法Bresenham算法是一种用于计算线段上像素点的算法,它的特点是具有高效和简单的特点,特别适合在计算机图形学中使用。
它可以根据给定的斜率,通过递增的方式计算出线段上的所有像素点。
本文将详细介绍Bresenham算法的原理和具体实现步骤。
一、Bresenham算法的原理Bresenham算法的核心思想是通过递增的方式计算出线段上的所有像素点,以实现高效的绘制线段的目的。
它基于以下两个关键观察:1. 如果直线斜率大于1,则将直线沿y轴方向递增,否则沿x轴方向递增。
2. 对于每个递增的步骤,根据当前像素点的位置和理想的线段位置之间的距离,选择最接近理想位置的像素点。
二、Bresenham算法的实现步骤Bresenham算法的实现步骤如下:1. 根据起点和终点的坐标,计算出线段的斜率。
如果斜率大于1,则将直线沿y轴方向递增,否则沿x轴方向递增。
2. 根据起点的坐标,计算出第一个像素点的位置,并将其绘制出来。
3. 计算出理想位置和当前像素点位置之间的距离,并记录下来。
4. 根据距离的大小,判断下一个像素点的位置。
如果距离小于等于0.5,则选择当前像素点的下一个位置作为下一个像素点;否则选择当前像素点的下一个位置的上方或右方作为下一个像素点。
5. 重复步骤4,直到绘制到终点的像素点为止。
三、Bresenham算法的优势相比于其他绘制线段的算法,Bresenham算法具有以下优势:1. 算法简单:Bresenham算法只需要进行简单的递增和判断操作,而没有复杂的计算和判断过程。
2. 高效性:Bresenham算法通过选择最接近理想位置的像素点,减少了不必要的计算和绘制,从而提高了绘制线段的效率。
3. 精度高:Bresenham算法通过选择最接近理想位置的像素点,可以实现精确绘制线段,避免了像素点之间的缺失或重叠现象。
四、Bresenham算法的应用领域Bresenham算法在计算机图形学中有着广泛的应用,特别是在线段绘制和扫描转换等方面。
Bresenham画椭圆算法
这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步。
算法步骤:(1) 输入椭圆的长半轴a和短半轴b。
(2) 计算初始值d = b*b + a * a * (-b + 0.25), x = 0, y = b。
(3) 绘制点(x, y)及其在四分象限上的另外3个对称点。
(4) 判断d的符号。
若d <= 0,则先将d更新为d + b * b * (2 * x + 3),再将(x, y)更新为(x+1, y);否则先将d更新为d + b * b * (2 * x + 3) + a * a (-2 * y + 2),再将(x, y)更新为(x+1, y-1)。
(5) 当b*b * (x+1) < a * a * (y - 0.5)时,重复步骤(3)和(4),否则转到步骤(6)。
(6) 用上半部分计算的最后点(x, y)来计算下半部分中d的初值: d = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * (y - 1) - a * a * b * b。
(7) 绘制点(x, y)及其在四分象限上的另外3个对称点。
(8) 判断d的符号。
若d <= 0,则先将d更新为d + b * b * (2 * xi + 2) + a *a * (-2 * yi + 3), 再将(x, y)更新为(x+1, y-1);否则先将d更新为d + a * a * (-2 * yi + 3),再将(x, y)更新为(x, y-1)。
(9) 当y >= 0,重复步骤(7)和(8),否则结束。
下面是算法:#include <GL/freeglut.h>void init (void){glClearColor (0.0f, 0.0f, 0.0f, 1.0f);}void drawEllipse (int a, int b, int xLoc, int yLoc){glPushMatrix ();int x, y;float d1, d2, aa, bb;aa = a * a;bb = b * b;d1 = bb + aa * (-b + 0.25);glTranslatef ((GLfloat) xLoc, (GLfloat) yLoc, 0.0f);x = 0;y = b;glBegin (GL_POINTS);glVertex2i ( x, y);glVertex2i (-x, y);glVertex2i (-x, -y);glVertex2i ( x, -y);while (bb * (x + 1) < aa * (y - 0.5)){if (d1 <= -0.000001){d1 += bb * ((x << 1) + 3);}else{d1 += bb * ((x << 1) + 3) + aa * (2 - (y << 1));-- y;}++ x;glVertex2i ( x, y);glVertex2i (-x, y);glVertex2i (-x, -y);glVertex2i ( x, -y);}d2 = bb * (0.25 * x) + aa * (1 - (y << 1));while (y > 0){if (d2 <= -0.000001){++ x;d2 += bb * ((x + 1) << 1) + aa * (3 - (y << 1));}else{d2 += aa * (3 - (y << 1));}-- y;glVertex2i ( x, y);glVertex2i (-x, -y);glVertex2i (-x, y);glVertex2i ( x, -y);}glEnd ();glPopMatrix ();}void display (void){glClear (GL_COLOR_BUFFER_BIT);glLoadIdentity ();glColor3f (1.0f, 0.0f, 0.0f);// draw a ellipsedrawEllipse (200, 300, 50, 50);glutSwapBuffers ();}void reshape (int w, int h){glViewport (0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode (GL_PROJECTION);glLoadIdentity ();if (w <= h){gluOrtho2D (-600.0, 600.0, -600.0 * (GLfloat) h / (GL float) w, 600.0 * (GLfloat) h / (GLfloat) w);}else{gluOrtho2D (-600.0 * (GLfloat) w / (GLfloat) h,600.0 * (GLfloat) w / (GLfloat) h, -600.0, 600.0);}glMatrixMode (GL_MODELVIEW);glLoadIdentity ();}void keyboard (unsigned char key, int x, int y){switch (key){case 27: // 'VK_ESCAPE'exit (0);break;default:break;}}int main (int argc, char ** argv){glutInit (&argc, argv);glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);glutInitWindowSize (600, 600);glutCreateWindow ("Bresenham ellipse");init ();glutReshapeFunc (reshape);glutDisplayFunc (display);glutKeyboardFunc (keyboard);glutMainLoop ();return 0;}努力不一定有结果,但不努力一定没结果。
bresenham算法计算步骤
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算法1.直线光栅化直线光栅化是指用像素点来模拟直线. 比如下图中用蓝色的像素点来模拟红色的直线. 图中坐标系是显示器上的坐标系: x轴向右, y轴向下.设deltaX = endX –startX, deltaY = endY –startY. 那么斜率为k = deltaY / deltaX. 我们先考虑简单的情况: 当0 < k < 1即直线更贴近x轴. 在这种情况下deltaY < deltaX, 所以在光栅化的过程中, 在y轴上描的点比在x轴上描点少. 那么就有一个很直观的光栅化算法:line_bresenham(startX, startY, endX, endY){deltaX = endX - startX;deltaY = endY - startY;k = deltaY / deltaX;for (x = startX, y = startY; x <= endX; ++x){if (满足一定条件){++y;}drawPixel(x, y);}}2.基于斜率/ 距离的两个简单直线光栅化算法好了,貌似很简单, 就剩一个问题: “满足一定条件”是什么? 可以用斜率判断, 也可以用上图中直线与光栅线交点 (红点) 与光栅点 (蓝点)的距离来判断. 继续用伪代码讲解:// 算法1: 用斜率判断void line_bresenham_k(startX, startY, endX, endY){deltaX = endX - startX;deltaY = endY - startY;k = deltaY / deltaX;for (x = startX, y = startY; x <= endX; ++x){if (x - startX != 0){currentK = (y - startY) / (x - startX); // 计算当前斜率if (currentK < k) // 如果当前斜率< k, 则增加y坐标{++y}}drawPixel(x, y);}}// 算法2: 用距离判断. 计算直线与光栅线交点y坐标我们需要用到// 直线方程y = k (x - startX) + startYline_bresenham_dist(startX, startY, endX, endY){deltaX = endX - startX;deltaY = endY - startY;k = deltaY / deltaX;for (x = startX, y = startY; x <= endX; ++x){// 计算直线与光栅线交点的y坐标, 以及与光栅点的距离ptY = k * (x - startX) + startY;dist = ptY - y;// 如果距离> 0.5或者< -0.5,需要增加y以将距离的绝对值控制在0.5之类if (dist > 0.5 || dist < -0.5){++y;}drawPixel(x, y);}}3.消灭浮点数以上都是很直观的算法, 下面不直观的来了–上面的算法都需要在循环体内执行乘法, 准确的说, 是进行浮点数的乘法. 我们怎么能减少这些浮点数的乘法开销呢? 以基于距离的算法2为例: 首先, k是一个浮点数, 0.5也是浮点数. 我们可以通过将这些表达式都乘以2 * deltaX (整数) 来解决浮点数的问题. 伪代码:// 算法3: 在算法2的基础上消灭浮点数!line_bresenham_dist(startX, startY, endX, endY){deltaX = endX - startX;deltaY = endY - startY;for (x = startX, y = startY; x <= endX; ++x){// 计算直线与光栅线交点的y坐标, 以及与光栅点的距离ptY1 = deltaY * (x - startX) + startY * deltaX;dist1 = ptY1 - y * deltaX;dist1 = dist1 << 1; // dist1 = dist1 * 2// 如果距离> 0.5或者< -0.5, 说明我们需要增加y以// 将距离的绝对值控制在0.5之类if (dist1 > deltaX || dist < -deltaX){++y;}drawPixel(x, y);}}4.消灭乘法圆满解决浮点数运算问题! 不过…乘法运算还在. 消灭乘法问题的办法比较不直观, 让我们想一想: 还有什么办法能简化运算. 直线方程已经不能再简化, 所以唯一的突破口就是能不能利用递推,用上一次循环的计算结果推导下一次循环的计算结果.首先我们来看看在算法2的基础上 (因为算法2计算红点蓝点之间的距离, 比较直观), 怎么通过第n – 1次循环计算出的dist值 (设为d1) 来推导出第n次循环的dist值 (设为d2). 先回顾一下: dist = 直线与光栅线交点的y坐标–相应光栅点的y坐标. 我们从几何上直观地考虑: 在第n次循环中, 我们先根据上一次循环所计算出来的d1, 暂时令d2 = d1 + k(x每次递增1,所以直线方程,相当于每次增加一个K), 因为我们要保证-0.5 < d2 < 0.5, 而d1 + k满足d1 + k > –0.5, 所以我们只需要考虑当d1 + k > 0.5时, 我们需要将光栅点y坐标增加1, 并且将d2减去1. 显然, 设y1是第n – 1次循环中光栅点的y坐标, y2是第n次循环中光栅点的y坐标. 我们有1) d2 = d1 + k – (y2 – y1)2) 当d1 + k > 0.5时y2 = y1 + 1, 否则y2 = y1我们已经能根据上面的两个关系式写出算法, 不过为了消除乘法和浮点数, 我们将这两个关系式两端同时乘以2 * deltaX, 并且设e = 2 * deltaX * d, 则我们有:3) e2 = e1 + 2 * deltaY – 2 * deltaX * (y2 – y1)4) 当e1 + 2 * deltaY > deltaX时y2 = y1 + 1, 否则y2 = y1终于, 没有了乘法 (2 * deltaY在循环体外计算且被简化为左移一位的运算), 没有了浮点数, 根据关系式3) 和 4), 写出算法:// 算法4: 在算法2, 3的基础上利用递推消灭乘法和浮点数!line_bresenham(startX, startY, endX, endY){deltaX = endX - startX;deltaY = endY - startY;e = 0;deltaX2 = deltaX << 1;deltaY2 = deltaY << 1;drawPixel(startX, startY);for (x = startX + 1, y = startY; x <= endX; ++x){// 关系式3) e2 = e1 + 2 * deltaY –2 * deltaX * (y2 –y1)// 关系式4) 当e2 + 2 * deltaY > deltaX时y2 = y1 + 1, 否则y2 = y1e += deltaY2;if (e > deltaX){e -= deltaX2;++y;}drawPixel(x, y);}}上面递推关系的推导过程是从图形上“直观”地分析得来的, 但是不严密. 我们能不能形式化地证明关系式1), 2), 3), 4)呢? 因为关系式3), 4)和1), 2)能互相推导, 我们只证明3), 4)如下:在算法3的基础上设第n –1次循环计算出的dist1值为e1, 对应的y值为y1, 第n次循环计算出的dist1值为e2, 对应的y值为y2. 根据算法3,dist1 = 2 * deltaY * (x –startX) + 2 * startY * deltaX –2 * y * deltaX, 则e2 – e1= 2 * deltaY * (x – startX) + 2 * startY * deltaX – 2 * y2 * deltaX – [2 * deltaY * (x – 1 – startX) + 2 * startY * deltaX – 2 * y1 * deltaX ]= – 2 * y2 * deltaX + 2 * deltaY + 2 * y1 * deltaX= 2 * deltaY – 2 * deltaX * (y2 – y1)所以e2 = e1 + deltaY –deltaX * (y2 –y1). 所以我们有关系式1) e2 = e1 + 2 * deltaY – 2 * deltaX * (y2 – y1)2) –deltaX < e1 < deltaX3) –deltaX < e2 < deltaX4) y2 –y1 = 0 或者1我们根据e1 + 2 * deltaY的取值范围进行讨论. 首先, 因为不等式6), 我们有2 * deltaY – deltaX < e1 + 2 * deltaY < 2 * deltaY + deltaX情况1: 如果2 * deltaY –deltaX < e1 + 2 * deltaY < deltaX, 则2 * deltaY – deltaX – 2 * deltaX * (y2 – y1) < e2 < deltaX– 2 * deltaX * (y2 – y1)反证: 若y2 –y1 = 1, 则2 * deltaY –deltaX –2 * deltaX < e2 < deltaX –2 * deltaX = -deltaX, 所以y2 –y1 = 1不成立. 即情况1中y2 = y1.情况2: 如果deltaX < e1 + 2 * deltaY < 2 * deltaY + deltaX, 则deltaX – 2 * deltaX * (y2 – y1) < e2 < 2 * deltaY + deltaX – 2 * deltaX * (y2 – y1)反证: 若y2 –y1 = 0, 则deltaX < e2 < 2 * deltaY + deltaX 所以y2 –y1 = 0不成立. 即情况2中y2 = y1 + 1.打了这么多字, 累…以上就是当0 < k < 1的情况, 剩余几种情况(k > 1, –1 < k < 0, k <–1. 不要挑剔我不用“>=”这种符号…) 都可以通过简单的x, y交换以及正负交换来搞定.。
中点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算法Bresenham算法的思想主要是通过判断y+1和y+0与直线上的点的距离远近来决定下⼀个像素点的y值到底是y还是y+1。
设直线y=kx+b,假设我第⼀点为(x,y),第⼆点为(x+1,y2)那么第⼆点我通过判断y+1和y哪个距离y2更近来选择下⼀个像素点的位置。
设y+1与y2的距离为D1,y与y2的距离为D2。
D1=y+1-y2=y+1-k(x+1)-b;D2=y2-y=k(x+1)+b-y我们通过判断D2-D1的符号来判断哪个距离更近D2-D1=k(x+1)+b-y-(y+1-k(x+1)+b)=2k(x+1)+2b-2y-1通过判断这个式⼦的符号即可知道我们要取哪个值。
但现在有⼀问题,就是这个式⼦中出现了k,k不是⼀个整数。
为了去掉k,我们可以通过把这个式⼦乘上▲x(k=▲y/▲x),⽽且设k为正数,即▲x为正)p=▲x(D2-D1)=2▲y*x-2▲x*y+c (c=2▲y+▲x(2b-1),是⼀个常量)通过判断p的符号我们即可选择绘制y+1还是y。
使⽤增量思想为了减少运算,我们使⽤增量思想,通过p i把p i+1推导出来p i+1=2▲y(x+1)-2▲x*y i+1+cp i=2▲y*x-2▲x*y i+cp i+1=p i+2▲y-2▲x(y i+1-y i)其中y i+1-y i是0或1,根据p i的符号来确定。
p0=2▲y*x0-2▲x((▲y/▲x)(x0+b))+2▲y+▲x(2b-1)=2▲y-▲x最后算法步骤如下:1.输⼊端点2.画出第⼀个点3.计算常量▲x,▲y,p0=2▲y-▲x4.判断p的符号,如果p<0绘制点(x+1,y)p next=p+2▲y否则,绘制点(x+1,y+1)p next=p+2▲y-2▲x5.重复第四步,共▲x-1次讨论k值其他情况关于▲x和▲y的问题补充说明:我们可以注意到,▲x是必定⼤于0的(因为我们总是⽤右边的点减左边的点⽽▲y则不⼀定,当|k|<1时不需要处理,因为都是乘以▲x,但是当|k|>1时要注意,k为负数时要改为乘以-▲y当-1<k<0时推导过程如下:结论:p0=-▲x-2▲yp i+1=p i-2▲y-2▲x(y i+1-y i)当1<k时推导过程如下:结论:p0=2▲x-▲yp i+1=p i+2▲x-2▲y(x i+1-x i)当<k<-1时推导过程如下:修改:应该从y0开始,每次-1.结论:p0=2▲x+▲yp i+1=p i+2▲x+2▲y(x i+1-x i)。
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种情况分别枚举,那重复代码便会显得⼗分臃肿,因此在设计算法时必须充分考虑上述各种情况的共性,后⾯将给出考虑了所有情况的实现代码。
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圆弧算法的优点在于其简洁性和高效性。
由于该算法只需进行简单的加减运算和比较判断,因此在计算机中的实现非常方便。
而且,该算法的绘制结果具有较高的精度,可以满足大部分绘制需求。
此外,由于Bresenham圆弧算法基于对称性,因此可以减少计算量,提高绘制速度,特别适用于实时绘制和动画效果的生成。
然而,Bresenham圆弧算法也存在一些局限性。
首先,该算法只适用于绘制位于正方形区域内的圆弧,无法直接绘制超出该区域的圆弧。
其次,由于该算法是通过逼近的方式来绘制圆弧,因此在绘制过程中可能会产生一些误差。
特别是对于较大的圆弧或高分辨率要求较高的场景,这种误差可能会导致绘制结果的不准确。
Bresenham圆弧算法是一种简洁高效的圆弧绘制算法,通过利用圆的对称性和Bresenham直线算法的思想,可以快速、准确地绘制圆弧。
该算法在计算机图形学和计算机游戏等领域得到广泛应用,为实时绘制和动画效果的生成提供了重要的支持。
通用整数bresenham算法
通用整数bresenham算法
Bresenham算法是一种用于在计算机屏幕上绘制直线、圆和其
他形状的算法。
在这里,我将重点介绍通用整数Bresenham算法,
用于绘制直线。
通用整数Bresenham算法是一种用于在计算机屏幕上绘制直线
的算法。
它是一种基于整数运算的算法,因此在计算机上执行速度
很快。
该算法通过在每个步骤中选择最接近直线路径的像素来绘制
直线。
该算法的基本原理是利用斜率来确定下一个要绘制的像素。
在
每一步中,根据直线斜率的大小来决定是向横坐标方向移动一个像
素还是向纵坐标方向移动一个像素。
通过适当的取整和判断,Bresenham算法能够以非常高效的方式绘制直线。
通用整数Bresenham算法的优点之一是它不需要使用浮点运算,这使得它非常适合于嵌入式系统和其他资源受限的环境。
此外,该
算法的实现比较简单,适用于各种编程语言和平台。
然而,通用整数Bresenham算法也有一些局限性。
例如,当直
线的斜率非常大或非常小的时候,该算法可能会出现绘制的直线与实际直线有所偏差。
此外,对于对角线上的像素,该算法可能不够精确。
总的来说,通用整数Bresenham算法是一种高效的直线绘制算法,特别适合于需要在计算机屏幕上绘制直线的应用程序。
它的简单性和高效性使得它成为计算机图形学中常用的算法之一。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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)。
(2)当此值为负时,d1<d2,说明直线上理论点离(xi+1,yi)象素较近,则下一个象素点应取(xi+1,yi)。
(3)当此值为零时,说明直线上理论点离上、下两个象素点的距离相等,取哪个点都行,假设算法规定这种情况下取(xi+1,yi+1)作为下一个象 素点。
mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12Course PagePage 2 of 6因此只要利用(d1-d2)的符号就可以决定下一个象素点的选择。
为此,我们进一步定义一个新的判别式: pi=△x×(d1-d2)=2△ y·xi-2△x·yi+c (2-11)式(2-11)中的△x=(x2-x1)>0,因此pi与(d1-d2)有相同的符号; 这里△ y=y2-y1,m=△y/△ x;c=2△ y+△x(2b-1)。
下面对式(2-11)作进一步处理,以便得出误差判别递推公式并消除常数c。
将式(2-11)中的下标i改写成i+1,得到: pi+1=2 △y·xi+1-2△ x·yi+1+c (2-12)将式(2-12)减去(2-11),并利用xi+1=xi+1,可得: pi+1= pi+2△y-2△x· (yi+1-yi) 再假设直线的初始端点恰好是其象素点的坐标,即满足: y1=mx1+b 由式(2-11)和式(2-14)得到p1的初始值: p1=2△y-△ x 这样,我们可利用误差判别变量,得到如下算法表示: 初始 p1=2 △y-△ x 当pi≥0时: yi+1=yi+1, xi+1=x i+1, pi+1=p i+2(△y-△ x) 否则: yi+1=yi, xi+1=x i+1, pi+1=p i+2△ y (2-16) (2-15) (2-14) (2-13)从式(2-16)可以看出,第i+1步的判别变量pi+1仅与第i步的判别变量pi、直线的两个端点坐标分量差△ x和△ y有关,运算中只含有整数相加和 乘2运算,而乘2可利用算术左移一位来完成,因此这个算法速度快并易于硬件实现。
三、直线Bresenham算法思想之二: 由于象素坐标的整数性,数学点(xi,yi)与所取象素点(xi,yir)间会引起误差(εi),当xi列上已用象素坐标(xi,yir)表示直线上的点(xi, yi),下一直线点B(xi+1,yi+1),是取象素点C(xi+1,yir ),还是D(xi+1,y(i+1)r)呢? 设A为CD边的中点,正确的选择: 若B点在A点上方,选择D点; 否则,选C点。
mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12Course PagePage 3 of 6用误差式描述为: ε(xi+1)=BC-AC=(yi+1-yir)-0.5 求递推公式: ε(xi+2)=(yi+2-y(i+1)r)-0.5 = yi+1+m-y(i+1)r-0.5 当ε(xi+1)≥0时,选D点,y(i+1)r = yir+1 ε(xi+2)= yi+1+m-yir-1-0.5=ε(xi+1)+m-1 当ε(xi+1)﹤0时,选C点,y(i+1)r = yir ε(xi+2)= yi+1+m-yir-0.5=ε(xi+1)+m 初始时: ε(xs+1)=BC-AC=m-0.5 (2-12') (2-11') (2-10') (2-9') (2-8')为了运算中不含实型数,同时不影响不等式的判断,将方程两边同乘一正整数。
令方程两边同乘2·Δx,即d=2·Δx· ε,则: 初始时: d = 2·Δy-Δx 递推式: (2-13')当d≥0时:{ d=d+2·(Δy-Δx); y++; x++; } (2-14')mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12Course PagePage 4 of 6否则: { d=d+2·Δy; x++; } 四、直线Bresenham算法实现: 条件:0≤m≤1且x1<x2 1、输入线段的两个端点坐标和画线颜色:x1,y1,x2,y2,color; 2、设置象素坐标初值:x=x1,y=y1; 3、设置初始误差判别值:p=2·Δy-Δx; 4、分别计算:Δx=x2-x1、Δy=y2-y1; 5、循环实现直线的生成: for(x=x1;x<=x2;x++) { putpixel(x,y,color) ; if(p>=0) { y=y+1; p=p+2· (Δy-Δx); } else { p=p+2·Δy; } } 五、直线Bresenham算法完善: 现在我们修正(2-16)公式,以适应对任何方向及任何斜率线段的绘制。
如下图所示,线段的方向可分为八种,从原点出发射向八个区。
由线段 按图中所示的区域位置可决定xi+1和yi+1的变换规律。
容易证明:当线段处于①、④、⑧、⑤区时,以|△x|和|△y|代替前面公式中的△ x和△ y,当线段处于②、③、⑥、⑦区时,将公式中的|△ x|和|△ y|对换,则上述两公式仍有效。
在线段起点区分线段方向 六、直线Bresenham算法演示:mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12Course PagePage 5 of 6斜率小于1 七、直线Bresenham算法特点: 由于程序中不含实型数运算,因此速度快、效率高,是一种有效的画线算法。
八、直线Bresenham算法程序:斜率大于1void Bresenhamline (int x1,int y1,int x2,int y2,int color) { int x, y, dx, dy, s1, s2, p, temp, interchange, i; x=x1; y=y1; dx=abs(x2-x1); dy=abs(y2-y1);if(x2>x1) s1=1; else s1=-1;if(y2>y1) s2=1; else s2=-1;if(dy>dx) { temp=dx; dx=dy; dy=temp; interchange=1; } else interchange=0;p=2*dy-dx; for(i=1;i<=dx;i++)mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12Course PagePage 6 of 6{ putpixel(x,y,color); if(p>=0) { if(interchange= =0) y=y+s2; else x=x+s1; p=p-2*dx; } if(interchange= =0) x=x+s1; else y=y+s2; p=p+2*dy; } }联系我们 | 制作小组 | 友情连接© 2009 洛阳理工学院. All rights reservedmhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht2011-7-12。