第四讲 改进的Bresanham算法圆的扫描转换
中点bresenham算法过程
中点Bresenham算法是一种用于计算在直线上的格点的算法。
它是由Bresenham在1965年提出的,是一种高效的计算机图形学算法,通常用于直线、圆、椭圆等形状的绘制。
通过这篇文章,我们将详细介绍中点Bresenham算法的过程。
1. 背景知识在计算机图形学中,我们经常需要在屏幕上绘制直线、圆、椭圆等形状。
而计算机屏幕上的图像是由像素组成的,因此我们需要一种算法来计算出这些形状上的像素坐标,从而进行绘制。
中点Bresenham算法就是用来解决这个问题的。
2. 中点Bresenham算法的原理中点Bresenham算法的原理是通过巧妙的数学推导,找到离直线最近的像素点,从而确定需要绘制的像素坐标。
该算法通过利用误差项来判断下一个像素点的位置,具有高效、简洁的特点。
3. 中点Bresenham算法的过程中点Bresenham算法的过程可以分为以下几个步骤:3.1 初始化变量:首先需要确定直线的起点和终点,并初始化相关变量,如起点坐标(x0, y0)、终点坐标(x1, y1)、误差项d和增量变化量dx、dy等。
3.2 计算斜率k和误差项初始值:通过计算直线的斜率k,并根据斜率确定误差项的初始值。
3.3 循环计算像素点的坐标:根据误差项的大小,确定下一个像素点的位置,并更新误差项的值,直到绘制完整条直线。
4. 中点Bresenham算法的优势* 算法简洁高效:中点Bresenham算法通过简单的数学计算,即可确定直线上的像素坐标,避免了直接计算斜率导致的浮点数运算,因此在计算速度上具有较大优势。
* 适用范围广泛:中点Bresenham算法不仅适用于直线,还可以用于绘制圆、椭圆等图形,具有良好的通用性。
5. 中点Bresenham算法的应用中点Bresenham算法广泛应用于计算机图形学中的直线、圆、椭圆等图形的绘制。
其高效、简洁的特点使得它成为了计算机图形学中不可或缺的算法之一。
中点Bresenham算法是计算机图形学中的重要算法之一,通过巧妙的数学计算,实现了高效、简洁的直线绘制。
改进的Bresenham算法
改进的Bresenham算法这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步。
算法步骤:(1)输入直线的两端点P0(x0,y0)和P1(x1,y1)。
(2)计算初始值dx,dy,e=-dx,x=x0,y=y0。
(3)绘制点(x,y)。
(4)e更新为e+2*dy。
判断e的符号,若e 0,则(x,y)更新为(x+1,y+1),同时将e更新为e-2*dx;否则(x,y)更新为(x+1,y)。
(5)当直线没有画完时,重复步骤(3)和(4)否则结束。
水平、垂直和|k|=1的直线可以直接装入帧缓冲存储器面无须进行画线算法处理。
下面是我的算法,如有错误请指出。
#include GL/freeglut.h voidinit(void){glClearColor(0.0f,0.0f,0.0f,1.0f);}void drawLine(intx1,int y1,int x2,int y2){int x,y,dx,dy,e;//k does not existif(x1==x2){if(y1 y2){y=y1;glBegin(GL_POINTS);while(y=y2){glVertex2i(x1,y);++y;}glEnd();}//if(y1 y2)else{y=y2;glBegin(GL_POINTS);while(y=y1){glVertex2i(x1,y);++y;}glEnd();}}//if(x1==x2)else if(y1==y2)//k=0{if(x1 x2){x=x1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y1);++x;}glEnd();}//if(x1 x2)else{x=x2;glBegin(GL_POINTS);while(x=x1){glVertex2i(x,y1);++x;}glEnd();}}else{if(x1 x2){int temp=x1;x1=x2;x2=temp;temp=y1;y1=y2;y2=temp;}x=x1;y=y1;dx=x2-x1;dy=y2-y1;//k=1 if(dx==dy){glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;++y;}glEnd();}else if(dx==-dy)//k=-1{glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;--y;}glEnd();}else if(dy dx)//k 1{glBegin(GL_POINTS);dx=1;e=-dy;dy=1;y=y1 y2?y2:y1;int maxY=y1 y2?y1:y2;while(y=maxY){glVertex2i(x,y);++y;e+=dx;if(e 0){++x;e-=dy;}}glEnd();}else if(dy 0)//0 k1{e=-dx;dx=1;dy=1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;e+=dy;if(e0){e-=dx;++y;}}glEnd();}else if(-dy dx)//0 k-1{e=-dx;dx=1;dy=1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;e+=dy;if(e0){--y;e+=dx;}}glEnd();}else if(-dy dx)//k-1{e=dy;dx=1;dy=1;glBegin(GL_POINTS);y=y1 y2?y1:y2;int minY=y1 y2?y2:y1;while(y=minY){glVertex2i(x,y);--y;e+=dx;if(e 0){++x;e+=dy;}}glEnd();}}}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0f,0.0f,0.0f);//Vertical line drawLine(0,-200,0,200);//Horizontal line drawLine(-200,0,200,0);//k=1 line drawLine(-200,-200,200,200);//k=-1 line drawLine(-200,200,200,-200);//k=1/2 line drawLine(200,100,-200,-100);//k=2 line drawLine(-100,-200,100,200);//k=-1/2 line drawLine(-200,100,200,-100);//k=-2 line drawLine(-100,200,100,-200);drawLine(30,120,10,70);drawLine(10,70,30,10);drawLine(30,10,60,50);drawLine(60,50,80,10);drawLine(80,10,120,80);drawLine(120,80,70,80);drawLine(70,80,30,120);glutSwapBuffers();}void reshape(int w,inth){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w=h){gluOrtho2D(-600.0,600.0,-600.0*(GLfloat)h/(GLfloat)w,600.0*(GLfloat)h/(GLfloat)w);}else{gluOr tho2D(-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(intargc,char*argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(600,600);glutCreateWindow("optimized Bresenhamline");init();glutReshapeFunc(reshape);glutDisplayFunc(display);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}作者:断桥&残雪发表于2010-12-04 20:29原文链接评论:0查看评论发表评论最新新闻:·马云:B2C创业者别埋怨淘宝不会停下来等你(2010-12-04 20:17)·Chrome to WP7手机端应用程序已经通过审核,可以下载了(2010-12-04 20:00)·盘点网络犯罪与信息战风云30年(2010-12-04 18:06)·网易邮箱:推出简历中心(2010-12-04 18:03)·马云:互联网三座大山将败给创新型小网站(2010-12-04 17:33)编辑推荐:"博客无双"活动:写博客、攒园豆、赢大奖网站导航:博客园首页我的园子新闻闪存小组博问知识库。
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画圆算法图形学讲义教学课件
当D > 0 , 只可能有4、5两种情况。且最佳象素点为
D或V,可用如下判别式:
δDV = | D |- | V |
δDV ≤ 0 则应选D,否则选V。(见图3)
对于第4种情况: δDV = D + V ( D >0,V <0) = (x+1)2 + (y-1)2 - R2 + (x)2 + (y-1)2 - R2
b初值为假,遍历活动边表,每访问一个节点,b取反一次。 若b为真,则填充当前节点的x值开始到下一节点的x值结束 的左闭右开的区间。
问题: 如何处理多边形的水平边?
边界填充算法
基本思想:每一条扫描线和每条多边形的交点,将该扫 描线上交点右方所有的象素取补。 算法简单,每个象素可能被访问多次,输入,输出量 大。
符号,标点符号等)。 • 它的编码用一个字节可以表示
2 汉字
• 汉字量大,必须用两个字节表示。 • “信息交换用汉字编码字符集基本集” • -GB2312-80
四、多边形的扫描转换与区域填充
1. 多边形的扫描转换 多边形的顶点表示和点阵表示。
顶点表示
点阵表示
1. 逐点比较算法 2. 扫描线算法
算法:
H、D、V三点到圆心的距离平方与圆的半径平 方差,即为H、D、V到圆弧距离的一种度量:
H = (x+1)2 + y2 - R2; D = (x+1)2 + (y-1)2 - R2; (式1) V = x2 + (y-1)2 - R2;
为了根据这些度量值可确定最佳象素点,首先, 将H、D、V与理想圆弧的关系进行分类。如图 3所示,存在以下五种情况:
减少求交运算量,提高排序的效率
活动边表的例子 y=3 Y=8
计算机图形学——圆的扫描转换(基本光栅图形算法)
计算机图形学——圆的扫描转换(基本光栅图形算法)与直线的⽣成类似,圆弧⽣成算法的好坏直接影响到绘图的效率。
本篇博客将讨论圆弧⽣成的3个主要算法,正负法、Bresenham 法和圆的多边形迫近法,在介绍算法时,只考虑圆⼼在原点,半径为R的情况。
⼀、正负法1、基本原理假设已选取Pi-1为第i-1个像素,则如果Pi-1在圆内,就要向圆外⽅向⾛⼀步;若已在圆外就要向圆内⾛⼀步。
总之,尽量贴近圆的轮廓线。
2、正负法的具体实现1)圆的表⽰:设圆的圆⼼为(0,0),半径为R,则圆的⽅程为:F(x,y)=x2+y2–R2=0当点(x,y)在圆内时,F(x,y)<0。
当点(x,y)在圆外时,F(x,y)>0。
2)实现步骤第1步:x0=0,y0=R第2步:求得Pi(x i,y i)后找点P i+1的原则为:当P i在圆内时(F(xi,yi)≤0),要向右⾛⼀步得P i+1,这是向圆外⽅向⾛去。
取x i+1= x i+1, y i+1= y i当P i在圆外时(F(xi,yi)>0),要向下⾛⼀步得P i+1,这是向圆内⽅向⾛去,取x i+1= x i, y i+1= y i-1⽤来表⽰圆弧的点均在圆弧附近且 F(xi, yi)时正时负假设已经得到点(x i, y i),则容易算出F(x i, y i),即确定了下⼀个点(x i+1, y i+1),则如何计算F(x i+1, y i+1),以确定下下个点(x i+2, y i+2)?分为两种情况:右⾛⼀步后:x i+1=x i+1,y i+1=y i,此时:F(x i+1, y i+1)=x i+12+y i2-R2=x i2+y i2-R2+2x i+1 = F(x i, y i)+2x i+1下⾛⼀步后:x i+1=x i,y i+1=y i-1, 此时:F(x i+1, y i+1)=x i2+(y i-1)2-R2= F(x i, y i)-2y i+1由此可得:确定了F(xi+1, yi+1)之后,即可决定下⼀个点(xi+2, yi+2),选择道理同上。
§3.2圆、圆弧的生成—Bresenham算法
§3.2圆的生成——Bresenham算法条件:给定圆心(x c,y c)和半径R约定:只考虑圆心在原点,半径为整数R的圆x2+y2.=R2。
对于圆心不在原点的圆,可先通过平移转换,化为圆心在原点的圆,再进行扫描转换,把所得到的像素集合加上一个位移量,就可以把目标圆光栅化。
在众多圆的生成算法,如逐点比较法、角度DDA法、Bresenham算法中,Bresenham画圆法是一种最简单有效的的方法。
首先注意到只要生成一个八分圆,那么,圆的其它部分就可以通过一系列的对成变换得到。
12345678由算法生成y=x第一八分圆关于y=x对称变换第一四分圆关于x=0对称变换上半圆关于y=0对称变换如果以点x=0,y=R为起点按顺时针方向生成圆,则在第一象限内y是x 的单调递减函数。
要在这三个像素中选择一个使其与理想圆的距离的平方达到最小,即下列数值中的最小者。
R(0,R)(R,0)xy这样,从圆上任一点出发,按顺时针方向生成圆时,为了最佳逼近该圆,对于下一像素的取法只有三种可能的选择,即正右方像素、正下方像素和右下角像素,分别记作:m H、m V、m D。
(x i,y i)(x i,y i-1)(x i+1,y i)(x i+1,y i-1)m Hm Dm Vm H=|(x i+1)2+(y i)2-R2|m V=|(x i)2+(y i+1)2-R2|m D=|(x i+1)2+(y I-1)2-R2|m H(x i,y i)(x i+1,y i)(x i+1,y i+1)(x i+1,y i-1)(x i-1,y i-1)(x i,y i-1)m Vm D12354圆与点(x i,y i)附近光栅格网的相交关系只有五种可能。
从圆心到右下角像素(x i+1,y i-1)的距离平方m D与圆心到圆上点的距离平方R2之差等于:Δi=(x i+1)2+(y i-1)2-R2如果Δi<0,那么右下角像素(x i+1,y i-1)在该圆内(图中①、②),显然这时只能取像素(x i+1,y i),即m H;或像素(x i+1,y i-1),即m D。
Bresenham直线算法与画圆算法(转)
Bresenham直线算法与画圆算法(转)在我们内部开发使用的一个工具中,我们需要几乎从0 开始实现一个高效的二维图像渲染引擎。
比较幸运的是,我们只需要画直线、圆以及矩形,其中比较复杂的是画直线和圆。
画直线和圆已经有非常多的成熟的算法了,我们用的是Bresenham的算法。
计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。
(上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在n维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
(引自wiki 百科布雷森漢姆直線演算法)这个算法的流程图如下:可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。
只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。
下面是一个C 语言实现版本。
1 2 3 4 5 // 交换整数 a 、b 的值inline void swap_int(int *a, int *b) {*a ^= *b;*b ^= *a;*a ^= *b;6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 }// Bresenham's line algorithmvoid draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsigned long c) {// 参数 c 为颜色值int dx = abs(x2 - x1),dy = abs(y2 - y1),yy = 0;if (dx < dy) {yy = 1;swap_int(&x1, &y1);swap_int(&x2, &y2);swap_int(&dx, &dy);}int ix = (x2 - x1) > 0 ? 1 : -1,iy = (y2 - y1) > 0 ? 1 : -1,cx = x1,cy = y1,n2dy = dy * 2,n2dydx = (dy - dx) * 2,d = dy * 2 - dx;if (yy) { // 如果直线与 x 轴的夹角大于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}putpixel(img, cy, cx, c);cx += ix;}} else { // 如果直线与 x 轴的夹角小于 45 度while (cx != x2) {if (d < 0) {d += n2dy;} else {cy += iy;d += n2dydx;}50515253putpixel(img, cx, cy, c);cx += ix;}}}可以看到,在画线的循环中,这个算法只用到了整数的加法,所以可以非常的高效。
Bresenham画圆算法的改进
Bresenham画圆算法的改进
王志喜;王润云
【期刊名称】《计算机工程》
【年(卷),期】2004(30)12
【摘要】由于没有充分考虑圆弧的特点,使得传统的Bresenham画圆算法效率还不够高,算法过于复杂,容易造成失真.该文总结了传统的Bresenham画圆算法,指出了传统Bresenham画圆算法的缺陷,提出改进的Bresenham画圆算法,并用实例进行验证,对Bresenham画圆算法的优越性进行了分析.
【总页数】3页(P178-180)
【作者】王志喜;王润云
【作者单位】湘潭工学院计算机系,湘潭,411201;湘潭工学院计算机系,湘
潭,411201
【正文语种】中文
【中图分类】TP312
【相关文献】
1.一种改进的等分迭代Bresenham直线生成算法 [J], 李竹林;邓石冬
2.嵌入式自像系统的改进Bresenham反走样算法的应用 [J], 张鹏;王良
3.一种快速的Bresenham直线生成改进算法 [J], 孙云
4.改进的Bresenham直线生成算法 [J], 陈定钰
5.串联型机械臂直线轨迹规划Bresenham算法应用与改进 [J], 张岩;过仕安;李争;安国庆;薛智宏;盖祥虎
因版权原因,仅展示原文概要,查看原文内容请购买。
易懂的Bresenham布雷森汉姆算法画圆的原理与Python编程实现教程
易懂的Bresenham布雷森汉姆算法画圆的原理与Python编程实现教程Bresenham 布雷森汉姆算法画圆的原理与编程实现教程注意:Bresenham的圆算法只是中点画圆算法的优化版本。
区别在于Bresenham的算法只使⽤整数算术,⽽中点画圆法仍需要浮点数。
注意:不要因为我提到了中点画圆法你就去先看完再看Bresenham算法,这样是浪费时间。
中点画圆法和Bresenham画圆法只是思想⼀样,但是思路并没有很⼤关联。
所以直接看Bresenham算法就可以。
看下⾯这个图,这就是⼀个像素⼀个像素的画出来的。
我们平常的圆也是⼀个像素⼀个像素的画出来的,你可以试试在“画图”这个软件⾥⾯画⼀个圆然后放⼤很多倍,你会发现就是⼀些像素堆积起来的。
我们看出来圆它是⼀个上下左右都对称,⽽且也是中⼼对称的。
所以我们只⽤画好⼋分之⼀圆弧就可以,其他地⽅通过对称复制过去就好。
看下⾯这幅图,绿线夹住的那部分就是⼋分之⼀圆弧。
注意我们是逆时针画圆的(即从⽔平那个地⽅即(r,0)开始画因为⼀开始我们只知道⽔平位置的像素点该放哪其他地⽅我们都不知道)。
Bresenham 算法画完⼀个点(x,y)后注意x,y都是整数。
他们代表的是x,y⽅向上的第⼏个像素。
,它下⼀步有两个选择(x,y+1),(x-1,y+1)。
也就是说y⼀定增加,但是x要么保持不变要么减⼀(你也可以让x⼀定增加y要么不变要么加⼀,其实差不多的)。
当程序画到粉红⾊那个像素点的时候,程序选择下⼀步要绘制的点为(x-1,y+1)。
当程序画到黄⾊的那个像素点时候,程序选择下⼀步要绘制的点为(x,y+1)。
我们看看粉⾊的那个点的下⼀步是如何抉择的。
Bresenham是根据待选的两个点哪个离圆弧近就下⼀步选哪个。
那它是怎么判断的呢?这两个点⼀定有⼀个在圆弧内⼀个在圆弧外。
到底选哪个?Bresenham的⽅法就是直接计算两个点离圆弧之间的距离,然后判断哪个更近就选哪个。
生成圆的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)。
中点画圆和Bresehnm画圆算法
二、中点画圆算法
void huayuan(int x0,int y0,int r,int color) { int x,y,d; x=0;y=r;d=1.25-r; while(y>=x) { huadian(x0,y0,x,y,color); if(d<0) {d=d+2*x+3;x++;} else {d=d+2*(x-y)+5;x++;y--;} } } void main() { int r, c=RGB(255,0,0); initgraph(640,480); huayuan(200,200,100,c); if(getch()==1) exit; closegraph(); }
四、两种画圆算法的优劣
算法比较和启发: 通过实际的程序运行比较分析,是中点画圆法速度快.就算法本身而言,该算 法仍可在某些方面进行改进,如将其中的浮点运算改为整数运算等,执行速度 将更快。 生成直线和圆这类基础算法在编程时要被无数次的调用,可能每生成一帧画面 就要被调用成百上千次,因此其执行速度是至关重要的.而这类基础算法的长 度都很短,即使多用一些分支,多用一些变量和语句,一般来说只不过增加几 十个语句.这样的空间增加与算法极重要的速度要求来比较是相对次要的因素, 因此在开发图形学的基础算法时,如果有可能提高算法的速度,应不惜多占一 些存储空间.
三、 Bresenham 画圆算法原理
算法原理: Bresenham画圆算法与Bresenham 直线算法一样,其基本的方法是利用判别变 量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就 可以计算出来。为了简便起见,考虑一个圆 心在坐标原点的圆,而且只计算八 分圆周上的点,其余圆周上的点利用对称性就可得到。
计算机图形学实验报告模板圆的扫描转换
北京联合大学应用文理学院实验报告课程名称计算机图形学实验(实训)名称圆的扫描转换班级信息与计算科学2009级姓名学号同组者实验(实训)日期完成日期本实验(实训)所用学时统计预习实验(实训)报告总计评阅意见:成绩北京联合大学应用文理学院实验报告一、实验目的1、掌握用中点画圆法进行圆的扫描转换方法;2、掌握用Bresenham画圆法进行圆的扫描转换方法;3、理解中点画圆法与Bresenham画圆法的区别;二、算法原理介绍1、中点画圆算法假设x坐标为xp的各像素点中,与该圆弧最近者已确定,为P(xp,yp),那么,下一个与圆弧最近的像素只能是正右方的P1(xp+1,yp),或右下方的P2(xp+1,yp-1)两者之一。
令M为P1和P2的中点,易知M的坐标为(xp+1,yp-0.5)。
显然,若M在圆内,则P1离圆弧近,应取为下一个像素;否则应取P2。
判别式d:d = F(M)=F(xp+1,yp-0.5)=(xp+1)^2+(yp-0.5)^2-R^2d的初始值为:d0 = F(1,R-0.5)=1+(R-0.5)^2-R^2=1.25-R在d≥0的情况下,取右下方像素P2,d = F(xp+2,yp-1.5)=(xp+2)^2+(yp-1.5)^2-R^2=d+2(xp-yp)+5在d<0的情况下,取正右方像素P1,d = F(xp+2,yp-0.5)=(xp+2)^2+(yp-0.5)^2-R^2=d+2xp+32、 Bresenham画圆算法假设生成圆心在坐标原点,半径为r,从x=0到x=y的1/8圆弧。
xi+1=xi +1相应的y则在两种可能中选择:y=yi,或者y=yi-1选择的原则是考察理想的y值是靠近yi还是靠近yi-1判别式:d i+1=2(xi+1)2+yi2+(yi-1)2-2r2判断式d的初始值为:d0= 3-2r。
如果d i+1>=0,则y=yi-1,di+2 =d i+1 + 4(xi- yi)+10如果d i+1<0,则y=yi,d i+2 =d i+1+ 4x i+6三、程序源代码1、中点画圆算法#include"graphics.h"#include"math.h"#include"conio.h"main(){void MidPointCircle(int,int);/*定义主函数变量,MidPointCircle中点画圆算法函数*/int gdriver,gmode; /*gdriver和gmode分别表示图形驱动器和模式*/gdriver=DETECT; /*DETECT是自动选择显示模式*/initgraph(&gdriver,&gmode,"c:\\tc3.0\\BGI");/*图形驱动文件的路径*/ MidPointCircle(200,YELLOW); /*定义圆的半径和颜色*/getch();/*getch();会等待你按下任意键,再继续执行下面的语句*/closegraph();/*关闭图形系统*/return(0); /*返回值为0*/}void MidPointCircle(int r,int color) /*定义函数变量半径和颜色*/{ int x,y;float d; /*float类型中小数位数为7位,即可精确到小数点后7位 */x=0; y=r; d=1.25-r;while(x<y) /*满足条件x<y时进入循环,不满足跳出*/{ if(d<0){d+=2*x+3; x++;}else { d+=2*(x-y)+5; x++; y--;}putpixel(x+200,y+200,color); putpixel(y+200,x+200,color);putpixel(200-x,y+200,color); putpixel(y+200,200-x,color);putpixel(200+x,200-y,color); putpixel(200-y,x+200,color);putpixel(200-x,200-y,color); putpixel(200-y,200-x,color);/* putpixel 在指定位置画一像素*/}}2、 Bresenham画圆算法#include"graphics.h"#include"math.h"#include"conio.h"main(){void Bresenham_Circle(int,int);/* Bresenham_Circle为 Bresenham画圆算法函数*/int gdriver,gmode;gdriver=DETECT;initgraph(&gdriver,&gmode,"c:\\tc3.0\\BGI");Bresenham_Circle(200,YELLOW); /*定义圆的半径和颜色*/getch();closegraph();return(0);}void Bresenham_Circle(int R,int color){ int x,y,delta,delta1,delta2,direction;x=0;y=R;delta=2*(1-R);while(y>=0) /*满足条件y>=0时进入循环,不满足跳出*/{putpixel(x+200,y+200,color); putpixel(y+200,x+200,color);putpixel(200-x,y+200,color); putpixel(y+200,200-x,color);putpixel(200+x,200-y,color); putpixel(200-y,x+200,color);putpixel(200-x,200-y,color); putpixel(200-y,200-x,color);if(delta<0){delta1=2*(delta+y)-1;if(delta1<=0)direction=1;else direction=2;}else if(delta>0){delta2=2*(delta-x)-1;if(delta2<=0) direction=2;else direction=3;}elsedirection=2;switch (direction)/*switch语句,即“切换”语句;case即“情况*/ {case 1:x++;delta+=2*x+1;break;/*执行 break 语句会退出当前循环或语句*/case 2:x++;y--;delta+=2*(x-y+1);break;case 3: y--;delta+=(-2*y+1);break;}}}四、实验结果图1中点画圆算法生成的圆半径r=200,颜色为黄色图2 Bresenham画圆算法生成的圆半径R=200,颜色为黄色五、总结与体会通过运用 C 语言环境下的图像显示设置,本次实验我学会了用中点画圆法、Bresenham 画圆法进行圆的扫描转换,更加深刻的理解了中点画圆法、Bresenham 画圆法进行圆的扫描转换的生成原理。
计算机图形学--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算法
void DDALine(int x0,int y0,int x1,int y1,int color) int i; float dx, dy, length,x,y; 举例: 线段P0(0,0)和P1(5,2)的DDA方法扫描转换。 if (fabs(x1-x0)>=fabs(y1-y0)) Line: P0(0, 0)-- P1(5, 2) length=fabs(x1-x0); x int(y+0.5) y+0.5 0 0 0+0.5 3 else 0.4+0.5 length=fabs(y1-y0); 1 0 2 2 1 0.8+0.5 dx = (x1-x0)/length; 3 1 1.2+0.5 1 dy=(y1-y0)/length; 4 2 1.6+0.5 i=1;x= x0;y= y0; 5 2 2.0+0.5 0 1 2 3 4 5 while(i<=length) { 图3-2 直线段的DDA扫描转换 SetPixel (int(x+0.5), int(y+0.5), color); x=x+dx; y=y+dy; i++; DDA算法与基本算法相比,减少了浮点乘法,提高了效率。但是x 与dx、y与dy用浮点数表示,每一步要进行四舍五入后取整,不利于硬 件实现,因而效率仍有待提高。
hi x(d1 d 2 )
则hi的计算仅包括整数运算,其符号与(d1-d2)的符号相同。 当hi<0时,直线上理想位置与像素(xi+1,yi)更接近,应取右方像素; 当hi>0时,像素(xi+1,yi+1)与直线上理想位置更接近; 当 hi=0 时,两个像素与直线上理想位置一样接近,可约定取(xi + 1 ,yi + 1)。
中点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改进算法(任何斜率,任何方向)
先标明这转载自/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画圆算法与中点画圆法
Bresenham画圆算法与中点画圆法Bresenham画圆算法不失⼀般性,假设圆的圆⼼位于坐标原点(如果圆⼼不在原点,可以通过坐标平移使其与原点重合),半径为R。
以原点为圆⼼的圆C有四条对称轴:x = 0, y = 0, x = y和x = -y。
若已知圆弧上⼀点P1=C(x, y),利⽤其对称性便可以得到关于四条对称轴的其它7个点,即: P2=C(x,-y), P3=C(-x, y), P4=C(-x,-y), P5=C(y,x), P6=C(-y,x), P7=C(y,-x), P8=C(-y,-x)。
这种性质称为⼋对称性。
因此,只要扫描转换⼋分之⼀圆弧,就可以通过圆弧的⼋对称性得到整个圆。
【Bresenham算法】简单图形的扫描转换常⽤算法是Bresenham算法。
它的思想在于⽤误差量来衡量点选取的逼近程度。
其过程如下:以平⾯⼆维图形的扫描转换为例,设要画的图形⽅程为F(x, y)=0,要画的区域为[x0, x](不妨设x⽅向是最⼤位移⽅向,即△x > △y),则F(x,y) 也是⼀个误差度量函数,我们拿离散的点值代⼊如果⼤于0则正向偏离,否则负向偏离,等于0的情况⽐较少,它表⽰的是不偏离即恰好与真实点重合。
既然x是最⼤位移⽅向,那每次对x⾃增1,相应的y可以选择不增或增1(或-1,具体问题具体分析),选择的⽅法就是d = F(x + 1, y ± 0.5)的正负情况进⾏判断从⽽选择y的值。
实际情况中还要考虑到浮点数的计算问题,因为基本的图形扫描转换算法最好能够硬件实现,所以摆脱浮点数是最好的,常⽤的⽅法是对d 进⾏递推,⽽不是直接由F(x,y)给出(直接给出速度会慢)。
【圆的扫描转换算法】以画圆为例,给出圆⼼的坐标(0, 0)和半径R,求圆图像的最佳逼近点。
圆是中⼼对称的特殊图形,所以可以将圆⼋等分,则只须对⼋分之⼀圆孤求解,其它圆孤可以由对称变换得到,我们求的⼋分之⼀圆孤为(0, R) -(R√2,R√2),可知最⼤位移⽅向是x⽅向,x0 = 0, y0 = R,每次对x⾃增,然后判断y是否减1,直到x >= y为⽌(从点(0, R)到圆的⼋分之⼀处就有这种情况)。
基于Bresenham 算法圆弧的设计与算法分析
文化视野1832021年18期 (6月下旬)摘要:本文在对LCD 的GUI 设计进行大量实验的基础上,利用Bresenham 算法如何在LCD 上形成圆弧、椭圆等基本图形进行设计,并对Bresenham 算法进行了详细的算法分析,结果表明Bresenham 算法在LCDGUI 设计方面具有高效性和准确性。
关键词:Bresenham ;算法分析;圆弧设计一、圆的构建圆形是在GUI 设计过程中不可规避的重要图形,可以通过确定“一点一线”来描述一个圆形,“一点”为圆心,“一线”为圆的半径,圆心确定了圆的位置,半径确定了圆的大小。
圆形及圆弧的生成算法主要有数值微分法、Bresenham 画圆算法和中点画线法等。
由于圆形是一个对称的结构,不但左右对称,而且中心对称,所以利用Bresenham 画圆算法只需要绘制出圆的一段圆弧,然后通过对称复制的方法即可实现整个圆的绘制。
首先确定目标圆的圆心,然后以圆心为坐标原点建立对称坐标系,如先绘制第一象限的1/8段圆弧(如图1所示)。
设最先确定的逼近像素点P i-1的坐标为(x i-1,y i-1),那么在圆弧附近有两个或者多个逼近像素点,如图1中的S i (x i-1+1,y i-1)和T i (x i-1+1,y i-1-1)点,在这两个点的选择时需要计算这两个点离理论圆弧的距离,选择离理论圆弧比较近的那个点作为圆弧构建的下一个像素点,以此类推,可以形成一段1/8段圆弧。
下面来讨论一下S i 点和T i 点到理论圆弧的距离,设S i 点和T i 点到理论圆弧的距离分别为D(S i )、D(T i ),计算公式如下:图1 Bresenham 算法构建1/8段圆弧因为S i 点和T i 点的坐标分别为(x i-1+1,y i-1)、(x i-1+1,y i-1-1),那么Si 点和Ti 点分别离坐标原点即圆心的距离的平方分别为:(x i-1+1)2+y i-12、(x i-1+1)2+(y i-1-1)2,将它们与圆的半径的平方做差就可以得出S i 点和T i 点离理论圆弧的距离大小了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
济南大学信息学院
13
算法步骤为: ( 0≤k≤1 )
1.输入直线的两端点P0(x0,y0)和P1(x1,y1)。
2019/2/13
济南大学信息学院
12
改进1:为计算方便,令e=d-0.5
xi1 xi 1 y yi 1 (e 0) i1 (e 0) yi
• e初=-0.5, • 每走一步有e=e+k。 • if (e>0) then e=e-1
2019/2/13
则有:
1 y y y
(d0 ) (d0 )
P u ( xi + 1, yi + 1) Q M (xi + 1, yi + 1/ 2 ) P (xi , yi ) 图5-5 P d ( xi + 1, yi ) B re n se m ha m 算 法 生 成 直 线 的 原 理
5
2019/2/13
2019/2/13
济南大学信息学院
9
过各行、各列像素中心构造一组虚拟网格 4.1.3 改进的Bresenham 算法 线,按直线从起点到终点的顺序计算直线
假定直线段的0≤k≤1 基本原理:
与网格线的交点,交点与网格线之间的误 差为d,根据d来确定该列网格中与此交点 最近的像素点。
k k k k k d d d d
yi 1.5 k(xi 1) b k
d F ( x , y ) F ( x 1 , y 0 . 5 ) y 0 . 5 k ( x 1 ) b M M i i i i
2019/2/13 济南大学信息学院 6
误差项的递推 d≥0:取点(xi+1, yi )
F ( x , y ) y kx b 0
2019/2/13
济南大学信息学院
8
用2d△x代替d
1.输入直线的两端点P0(x0,y0)和P1(x1,y1)。
0≤k≤1
2.计算初始值△x、△y、d=△x-2△y、x=x0、y=y0。 3.绘制点(x,y)。判断d的符号。 若d<0,则(x,y)更新为(x+1,y+1),d更新为 d+2△x-2△y; 否则(x,y)更新为(x+1,y), d更新为d-2△y。 4.当直线没有画完时,重复步骤3。否则结束。
d F ( x , y ) F ( x 1 , y 0 . 5 ) y 0 . 5 k ( x 1 ) b M M i i i i
2019/2/13 济南大学信息学院 7
初始值d的计算
0≤k≤1
d0 F ( x0 1, y0 0.5) y0 0.5 k ( x0 1) b y0 kx0 b k 0.5 0.5 k
第4讲 改进的Brensemham算法 圆的扫描转换
2019/2/13
济南大学信息学院
1Leabharlann 5.1.2 中点Bresenham算法
设两端点为P0 (x0,y0)和 P1 (x1,y1),则直线的方程
y yy 1 F ( x , y ) y kx b 0 , 其中 k 0 xx x 1 0
该直线方程将平面分为三个区域: • 对于直线上的点,F(x,y)=0;
• 对于直线上方的点,F(x,y)>0;
• 对于直线下方的点,F(x,y)<0。
2019/2/13 济南大学信息学院 2
y F(x,y)=0 F(x,y)>0 x F(x,y)<0 F(x,y)=0
y
F(x,y)>0
F(x,y)<0
图5-8 改进的Brensemham算法绘制直线的原理
2019/2/13 济南大学信息学院 10
xi1 xi 1 y yi 1 (d 0.5) i1 (d 0.5) yi
误差项的计算
• d初=0, • 每走一步:d=d+k • 一旦y方向上走了一步,d=d-1
x
图 5-4 直 线 将 平 面 分 为 三 个 区 域
F(x,y)=y-2x-1=0
2019/2/13
济南大学信息学院
3
Bresenham算法的基本原理:在最大位移方向上走一步时, 在另一个方向上是否走步取决于误差项的判断。 假定0≤k≤1,x是最大位移方向
P u ( xi + 1, yi + 1) Q M (xi + 1, yi + 1/ 2 ) P (xi , yi ) 图5-5
0≤k≤1
下一个中点(xi+2, yi +0.5)
d F(xi 2, yi 0.5) yi 0.5 k(xi 2) b d k
( xi+2, yi+0.5) ( xi+1, yi+0.5) ( xi, yi) d>=0
yi 0.5 k(xi 1) b k
2019/2/13
济南大学信息学院
11
算法步骤: ( 0≤k≤1 ) 1.输入直线的两端点P0(x0,y0)和P1(x1,y1)。 2.计算初始值△x、△y、d=0、x=x0、y=y0。 3.绘制点(x,y)。 4.d 更新为 d+k,判断 d 的符号。若 d>0.5,则 (x,y) 更 新为 (x+1,y+1),同时将 d 更新为 d-1;否则 (x,y) 更 新为(x+1,y)。 5.当直线没有画完时,重复步骤3和4。否则结束。
2019/2/13
P d ( xi + 1, yi ) B re n se m ha m 算 法 生 成 直 线 的 原 理
济南大学信息学院 4
0≤k≤1
判别式:
F ( x , y ) y kx b
d F ( x , y ) F ( x 1 , y 0 . 5 ) y 0 . 5 k ( x 1 ) b M M i i i i
济南大学信息学院
误差项的递推 d<0:取点(xi+1, yi +1)
0≤k≤1
( xi+2, yi+1.5) ( xi+1, yi+0.5) ( xi, yi) d<0
下一个中点(xi+2, yi +1.5)
d F(xi 2, yi 1.5) yi 1.5 k(xi 2) b d 1 k