Bresenham直线算法与画圆算法
第三章 生成直线和圆弧的算法
Bresenham画线算法
设图中xi列上已用(xi,yir)作为表示直线的点, 又设B点是直线上的点,其坐标为(xi+1,yi+1),显然 下一个表示直线的点( xi+1,yi+1,r)只能从图中的C 或者D点中去选。设A为CD边的中点。 若B在A点上面 则应取D点作为( xi+1,yi+1,r),否则应取C点。
P2 Q
P=(xp,yp) P1
中点画线法
• 画线从(x0, y0)开始,d的初值 d0=F(x0+1, y0+0.5)= a(x0 +1)+b(y0 +0.5)+c = F(x0, y0)+a+0.5b = a+0.5b 由于只用d 的符号作判断,为了只包含整数运算, 可以用2d代替d来摆脱小数,提高效率。
数值微分(DDA)法
• 增量算法:在一个迭代算法中,如果每 一步的x、y值是用前一步的值加上一个 增量来获得,则称为增量算法。 • DDA算法就是一个增量算法。
数值微分(DDA)法
void DDALine(int x0,int y0,int x1,int y1,int color) { int x; float dx, dy, y, k; dx, = x1-x0, dy=y1-y0; k=dy/dx, y=y0; for (x=x0; x≤x1, x++) { drawpixel (x, int(y+0.5), color); y=y+k; } }
一逐点比较法
算法: 1、偏差计算 1)一般公式
α β
A(xA, xA)
M(xM, xM)
• 偏差
yM y A d = tg β − tg α = − xM x A y M x A − y A xM = xM x A
Bresenham画圆算法图形学讲义教学课件
共享顶点的两条边分别位于扫描线的两边,交点算一个。 共享顶点的两条边都位于扫描线的下边,交点算零个。 共享顶点的两条边都位于扫描线的上边,交点算二个。
右、上边界的象素不予填充。 左、下边界的象素予以填充。
算法的实现
求交
所有的边和扫描线求交,效率很低。因为一条扫描线往往只 和少数几条边相交。
如何判断多边形的一条边与扫描线是否相交?(ymin,ymax)
=(x+1)2 + (y-1)2 -R2 - 2(y-1) + 1 = D - 2(y-1) + 1
有了上述 D的递推计算公式,还需计算出D的初值。 ∵ 圆弧的起点为(0,R) ∴ D的初值为:
D = (0+1)2 +(R-1)2-R2 = 2 (1-R)
BresenhamCircle(r, color)
填充。
王选。
TrueType技术
Windows的字库
二次Bezier曲线描述轮廓, 控制点按顺时针方向编号。
使用时先生成轮廓,再在内部填充形成点阵 信息,显示或输出。
例子
H的TrueType字库控制信息 X方向 Y方向
标准字符集
• ASCII
• 共127个。 • 0-31 不可见,控制字符。 • 32-127可见(大小写字母,数字,运算
象素入栈多次,栈要很大的空间。
扫描线填充算法
沿扫描线,在扫描线与多边形的相交区间内填充。
只取一个种子象素。
种子象素入栈;当栈非空时执行以下四步操作:
1 栈顶元素出栈;
2 沿扫描线对出栈象素的左右象素进行填充,直至遇到边 界象素为止。即对每个出栈象素,对包含该象素的整个区 间进行填充。
}/*end of switch*/ }/*end of while*/ }/*end of BresenhamCircle*/
计算机图形学-三种直线生成算法及圆的生成算法
计算机科学与技术学院2013-2014学年第一学期《计算机图形学》实验报告班级:110341C学号:110341328姓名:田野教师:惠康华成绩:实验(一):平面图形直线和圆的生成一、实验目的与要求1.在掌握直线和圆的理论基础上,分析和掌握DDA生成直线算法、中点生成直线算法、Bresenham生成直线算法、中点画圆算法、Bresenham圆生成算法。
2.熟悉VC6.0MFC环境,利用C语言编程实现直线和圆的生成。
3.比较直线生成三种算法的异同,明确其优点和不足。
同时了解圆的生成算法适用范围。
二、实验内容1.掌握VC6.0环境中类向导和消息映射函数的概念,并且为本次实验做好编程准备工作。
2. 用C语言进行编程实现上述算法,并且调试顺利通过。
3. 在MFC图形界面中显示不同算法下的图形,并且注意对临界值、特殊值的检验。
完成后保存相关图形。
三、算法分析➢DDA直线生成算法描述:1)给定一直线起始点(x0,y0)和终点(x1,y1)。
分别计算dx=x1-x0,dy=y1-y0。
2)计算直线的斜率k=dy/dx。
当|k|<1时转向3);当|k|<=1时,转向4);3)当x每次增加1时,y增加k。
即(xi,yi)→(xi+1,yi+k)。
直到xi增加到x1。
并且每次把得到的坐标值利用系统函数扫描显示出来。
但要注意对y坐标要进行int(y+0.5)取整运算。
结束。
4)对y每次增加1时,x增加1/k,即(xi,yi)→(xi+1/k,yi+1)。
直到yi增加到y1. 并且每次把得到的坐标值利用系统函数扫描显示出来。
但要注意对x坐标要进行int(x+0.5)取整运算。
结束。
➢中点生成算法描述:算法基本思想:取当前点(xp,yp),那么直线下一点的可能取值只能近的正右方点P1(xp+1,yp)或者P2(xp+1,yp+1)。
为了确定好下一点,引入了这两点中的中点M(xp+1,yp+0.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)。
§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布雷森汉姆算法画圆的原理与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中点画圆原理介绍
1.中点Bresenham 算法的原理圆心在原点、半径为R 的圆方程的隐函数表达式为:圆将平面划分成三个区域:对于圆上的点,F(x ,y)=0;对于圆外的点,F (x ,y )>0;对于圆内的点,F (x ,y )<0。
事实上,考虑到圆在第一象限内的对称性,本算法可以进一步简化。
用四条对称轴x =0,y =0, x =y,x =-y 把圆分成8等份。
只要绘制出第一象限内的1/8圆弧,根据对称性就可绘制出整圆,这称为八分法画圆算法。
假定第一象限内的任意点为P (x,y ),可以顺时针确定另外7个点:P (y ,x ),P (y ,-x ),P (x,- y ),P (-x ,-y ),P (-y ,-x ),P (-y ,x ),P (-x ,y )。
2.构造中点偏差判别式从P (xi ,yi )开始,为了进行下一像素点的选取,需将Pu 和Pd 的中点M (x i+1,y i-0.5)代入隐函数,构造中点偏差判别式:⑴当d<0时,下一步的中点坐标为:M (xi +2,yi -0.5)。
下一步中点偏差判别式为:⑵当d ≥0时,下一步的中点坐标为:M (xi +2,yi -1.5)。
),(222=-+=R y x y xF )5.0,1(),(-+==i i M M y x F y x F d ⎩⎨⎧≥<=+)0( 1-)0(1d y d y y i i i 2221)5.0()2()5.0,2(R y x y x F d i i i i i --++=-+=+3232)5.0()1(222++=++--++=i i i i i x d x R yx2221)5.1()2()5.1,2(R y x y x F d i i i i i --++=-+=+。
Bresenham画线画圆算法
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,即Sub21.如果下下个点是下个点的右上邻接点,则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算法画圆并实现圆形的填充。
二、实验思路三、程序代码1)void MidPointCirle(int radius,float a,float b,float c) //bresenham画圆{int x,y;x=0;y=radius;d=3-2*radius;glVertex2i(x,y);while(y>x){if(d<=0){d=d+4*x+6;}else{d=d+4*(x-y)+10;y--;}x++;glColor3f(a,b,c);glVertex2i(x,y);glColor3f(a,b,c);glVertex2i(x,-y);glColor3f(a,b,c);glVertex2i(-x,y);glColor3f(a,b,c);glVertex2i(-x,-y);glColor3f(a,b,c);glVertex2i(y,x);glColor3f(a,b,c);glVertex2i(y,-x);glColor3f(a,b,c);glVertex2i(-y,x);glColor3f(a,b,c);glVertex2i(-y,-x);}}2)void fillPointCirle(int r,float a,float b,float c) //圆形填充{int x,y;float d;x=0;d=3-2*r;glVertex2i(x,y);while(y>x){if(d<=0){d=d+4*x+6;}else{d=d+4*(x-y)+10;y--;}x++;glColor3f(a,b,c);glVertex2i(x,y);glColor3f(a,b,c);glVertex2i(x,-y);for(int i=-y;i<y;i++)glVertex2i(x,i);glColor3f(a,b,c);glVertex2i(-x,y);glColor3f(a,b,c);glVertex2i(-x,-y);for(int j=-y;j<y;j++)glVertex2i(-x,j);glColor3f(a,b,c);glVertex2i(y,x);glColor3f(a,b,c);glVertex2i(y,-x);for(int p=-x;p<x;p++)glVertex2i(y,p);glColor3f(a,b,c);glVertex2i(-y,x);glColor3f(a,b,c);glVertex2i(-y,-x);for(int q=-x;q<x;q++)glVertex2i(-y,q);}3)void myMouse(int button,int state, int mouseX, int mouseY) //点击鼠标实现圆形填充并实现颜色的随机生成{if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){glBegin(GL_POINTS);fillPointCirle(R*100,(GLfloat)(rand()%1000/1000.0),(GLfloat)(rand()%1000/1000.0),(GLfloat)(rand()%1000/1000.0));glEnd();glFlush();}else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){glClear(GL_COLOR_BUFFER_BIT);}glFlush();}四、实验结果截屏。
计算机图形学--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)。
单片机c语言打点函数画带线宽的圆
单片机c语言打点函数画带线宽的圆在单片机的C语言中实现带线宽的圆形绘制可以通过使用Bresenham算法。
该算法是一种经典的图形绘制算法,可以用来绘制圆、椭圆以及其他一些曲线。
下面将详细介绍如何使用C语言实现带线宽的圆绘制。
Bresenham算法是一种基于数学原理的快速绘制算法,用于近似绘制圆形。
该算法基本思路是根据圆的对称性通过逐渐增加或减少圆周上的点来绘制整个圆。
以下是一个基于Bresenham算法实现绘制带线宽的圆的C代码示例:```c#include <stdio.h>//定义显示函数或绘制像素的函数void drawPixel(int x, int y) {//实现具体的绘制像素的代码}//定义绘制圆的函数void drawCircle(int xc, int yc, int r, int width) { int x = 0;int y = r;int d = 3 - 2 * r;while (x <= y) {//绘制圆的每个八分之一部分for (int i = 0; i <= width; i++) {drawPixel(xc + x, yc + y + i);drawPixel(xc + x, yc - y - i);drawPixel(xc - x, yc + y + i);drawPixel(xc - x, yc - y - i);drawPixel(xc + y, yc + x + i);drawPixel(xc + y, yc - x - i); drawPixel(xc - y, yc + x + i); drawPixel(xc - y, yc - x - i); }if (d < 0) {d += 4 * x + 6;} else {d += 4 * (x - y) + 10;y--;}x++;}}int main() {//调用绘制圆的函数drawCircle(100, 100, 50, 3);return 0;}```在上述代码中,`drawPixel`函数用于实现具体的绘制像素的功能,可以根据硬件平台的不同而有所不同。
Bresenham直线算法与画圆算法
Bresenham直线算法与画圆算法文章分类:Java编程计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。
(上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
(引自wiki百科布雷森漢姆直線演算法)这个算法的流程图如下:可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。
只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。
下面是一个C语言实现版本。
Java代码1.view sourceprint?2. // 交换整数 a 、b 的值3.4.inline void swap_int(int *a, int *b)5.{6. *a ^= *b;7. *b ^= *a;8. *a ^= *b;9.}10.11.// Bresenham's line algorithm12.13.void draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsigned long c)14.{15. // 参数 c 为颜色值16. int dx = abs(x2 - x1),17. dy = abs(y2 - y1),18. yy = 0;19.20. if(dx < dy)21. {22. yy = 1;23. swap_int(&x1, &y1);24. swap_int(&x2, &y2);25. swap_int(&dx, &dy);26. }27.28. int ix = (x2 - x1) > 0 ? 1 : -1,29. iy = (y2 - y1) > 0 ? 1 : -1,30. cx = x1,31. cy = y1,32. n2dy = dy * 2,33. n2dydx = (dy - dx) * 2,34. d = dy * 2 - dx;35.36.// 如果直线与 x 轴的夹角大于45度37. if(yy)38. {39. while(cx != x2)40. {41. if(d < 0)42. {43. d += n2dy;44. }45. else46. {47. cy += iy;48. d += n2dydx;49. }50.51. putpixel(img, cy, cx, c);52.53. cx += ix;54. }55. }56.57.// 如果直线与 x 轴的夹角小于度58. else59. {60. while(cx != x2)61. {62. if(d < 0)63. {64. d += n2dy;65. }66. else67. {68. cy += iy;69. d += n2dydx;70. }71.72. putpixel(img, cx, cy, c);73.74. cx += ix;75. }76. }77.}可以看到,在画线的循环中,这个算法只用到了整数的加法,所以可以非常的高效。
LCD_画点,画直线,画圆,画矩形的几种算法
LCD_Send_Cmd(0x2b);
LCD_Send_Data((y1 & (0xff00))>>8);
LCD_Send_Data(y1 & 0x00ff);
LCD_Send_Data((y2 & (0xff00))>>8);
LCD_Send_Data(y2 & 0x00ff);
{
LCD_Draw_Point(x,y,bkColor);
if(Dx>=0) x++;
else x--;
e+=2*dy;
if(e>=0)
{
if(Dy>=0) y++;
else y--;
}
}
}
}
/*Bresenham算法画圆*/
void LCD_Draw_Circle2(int x,int y,int r,u16 color)
{
int a,b;
int di;
a=0;
b=r;
di=3-(r<<1);//判断下个点位置的标志
while(a<=b)
}
}
}
}
/*利用Bresenham算法画实心圆,缺点画圆速度慢*/
void LCD_Draw_FullCircle2(int Xpos,int Ypos,int Radius,u16 color)
{
int tx=0,ty=Radius,d=3-2*Radius,i;
}
else
{
di +=10+4*(a-b);
Bresenham直线算法
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
经过少量的延伸之后,原本用来画直线的算法也可用来画圆。
且同样可用较简单的算术运算来完成,避免了计算二次方程式或三角函数,或递归地分解为较简单的步骤。
以上特性使其仍是一种重要的算法,并且用在绘图仪、绘图卡中的绘图芯片,以及各种图形程式库。
这个算法非常的精简,使它被实作于各种装置的固件,以及绘图芯片的硬件之中。
“Bresenham”至今仍经常作为一整个算法家族的名称,即使家族中绝大部份算法的实际开发者是其他人。
该家族的算法继承了 Bresenham 的基本方法并加以发展,详见参考资料。
目录[隐藏]∙ 1 演算方法∙ 2 一般化∙ 3 最佳化∙ 4 历史∙ 5 参考资料∙ 6 参阅∙7 外部链接[编辑]演算方法Bresenham直线算法描绘的直线。
假设我们需要由 (x0, y0) 这一点,绘画一直线至右下角的另一点(x1, y1),x,y分别代表其水平及垂直座标,并且x1 - x0 > y1 - y0。
在此我们使用电脑系统常用的座标系,即x座标值沿x轴向右增长,y座标值沿y轴向下增长。
因此x及y之值分别向右及向下增加,而两点之水平距离为x1−x0且垂直距离为y1-y0。
由此得之,该线的斜率必定介乎于1至0之间。
而此算法之目的,就是找出在x0与x1之间,第x行相对应的第y列,从而得出一像素点,使得该像素点的位置最接近原本的线。
对于由(x0, y0)及(x1, y1)两点所组成之直线,公式如下:因此,对于每一点的x,其y的值是因为x及y皆为整数,但并非每一点x所对应的y皆为整数,故此没有必要去计算每一点x所对应之y值。
反之由于此线之斜率介乎于1至0之间,故此我们只需要找出当x 到达那一个数值时,会使y上升1,若x尚未到此值,则y不变。
Bresenham的直线生成算法和整圆生成算法完整代码
Bresenham的直线生成算法和整圆生成算法完整代码以下是Bresenham的直线生成算法和整圆生成算法,已调试过,没有任何问题。
Bresenham直线生成算法#include "stdio.h"#include "graphics.h"Bresenham_line(x0,y0,x1,y1,color)int x0,y0,x1,y1,color;{int x,y,dx,dy, i; float k,e;dx=x1-x0;dy=y1-y0;k=(dy*1.0)/dx; e=-0.5; x=x0; y=y0;for (x=x0; x<=x1; x++){putpixel(x,y,color);e=e+k;if(e>=0){ y++;e=e-1;}}}int main(){int x0,y0,x1,y1,c;int driver=DETECT,mode=0;initgraph(&driver,&mode,"c:\\tc");setbkcolor(BLUE);setcolor(YELLOW);printf("input x0,y0,x1,y1,c");scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&c);Bresenham_line(x0,y0,x1,y1,c);closegraph();}当取e=2*dy-dx时,可以消除浮点和除法运算#include "stdio.h"#include "graphics.h"Bresenham_line(x0,y0,x1,y1,color)int x0,y0,x1,y1,color;{int x,y,dx,dy, i,e; float k;dx=x1-x0;dy=y1-y0;k=(dy*1.0)/dx; e=2*dy-dx; x=x0; y=y0;for (x=x0; x<=x1; x++){putpixel(x,y,color);e=e+2*dy;if(e>=0){ y++;e=e-2*dx;}}}int main(){int x0,y0,x1,y1,c;int driver=DETECT,mode=0;initgraph(&driver,&mode,"c:\\tc"); setbkcolor(BLUE);setcolor(YELLOW);printf("input x0,y0,x1,y1,c");scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&c); Bresenham_line(x0,y0,x1,y1,c);closegraph();}Bresenham整圆生成算法#include "stdio.h"#include "graphics.h"void circlePoints(int x0,int y0,int x,int y,int color) { putpixel(x+x0,y+y0,color);putpixel(x+x0,-y+y0,color);putpixel(y+x0,x+y0,color);putpixel(y+x0,-x+y0,color);putpixel(-x+x0,-y+y0,color);putpixel(-x+x0,y+y0,color);putpixel(-y+x0,-x+y0,color);putpixel(-y+x0,x+y0,color);}Bresenhamcircle (int x0,int y0,int r){int x,y,d,color=15;d=3-2*r;x=0;y=r; /*从(0,r)开始画圆*/?circlePoints(x0,y0,x,y,color);while(x<y)< p="">{if(d<0){d=d+4*x+6;x++;}else{d= d+4*(x-y)+10;x++;y--;}circlePoints(x0,y0,x,y,color);}}main(){int r,x0,y0;int driver=DETECT,mode=0; initgraph(&driver,&mode,"c:\\tc"); setbkcolor(BLUE);setcolor(YELLOW);printf("input x0,y0,r\n");scanf("%d%d%d",&x0,&y0,&r); Bresenhamcircle(x0,y0,r);getch();closegraph();}</y)<>。
OpenGL画直线、圆、椭圆
使用openGl画直线(DDA算法)、画圆、椭圆(Bresenham算法)#include<stdlib.h>#include<iostream.h>#include <GL/glut.h>/* initialization: */void myinit(void){/* attributes */glClearColor(1.0, 1.0, 1.0, 0.0);//设置背景颜色glColor3f(1.0, 0.0, 0.0); //设置绘制颜色为红色/* set up viewing: *//* 500 x 500 window with origin lower left */glMatrixMode(GL_PROJECTION); //指定设置投影参数glLoadIdentity();/*OpenGL为我们提供了一个非常简单的恢复初始坐标系的手段,那就是调用glLoadIdentity()命令。
该命令是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。
也就是说,无论以前进行了多少次矩阵变换,在该命令执行后,当前矩阵均恢复成一个单位矩阵,即相当于没有进行任何矩阵变换状态。
*/gluOrtho2D(0.0, 500.0, 0.0, 500.0); //设置投影参数glMatrixMode(GL_MODELVIEW);/*这两个都是glMatrixMode()函数的参数,那就先说说glMatrixMode吧~,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有,GL_PROJECTION,GL_MODELVIEW和GL_TEXTURE;如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Bresenham直线算法与画圆算法
文章分类:Java编程
计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。
(上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)
接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
(引自wiki百科布雷森漢姆直線演算法)
这个算法的流程图如下:
可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。
只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。
下面是一个C语言实现版本。
Java代码
1.view sourceprint?
2. // 交换整数 a 、b 的值
3.
4.inline void swap_int(int *a, int *b)
5.{
6. *a ^= *b;
7. *b ^= *a;
8. *a ^= *b;
9.}
10.
11.// Bresenham's line algorithm
12.
13.void draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsi
gned long c)
14.{
15. // 参数 c 为颜色值
16. int dx = abs(x2 - x1),
17. dy = abs(y2 - y1),
18. yy = 0;
19.
20. if(dx < dy)
21. {
22. yy = 1;
23. swap_int(&x1, &y1);
24. swap_int(&x2, &y2);
25. swap_int(&dx, &dy);
26. }
27.
28. int ix = (x2 - x1) > 0 ? 1 : -1,
29. iy = (y2 - y1) > 0 ? 1 : -1,
30. cx = x1,
31. cy = y1,
32. n2dy = dy * 2,
33. n2dydx = (dy - dx) * 2,
34. d = dy * 2 - dx;
35.
36.// 如果直线与 x 轴的夹角大于45度
37. if(yy)
38. {
39. while(cx != x2)
40. {
41. if(d < 0)
42. {
43. d += n2dy;
44. }
45. else
46. {
47. cy += iy;
48. d += n2dydx;
49. }
50.
51. putpixel(img, cy, cx, c);
52.
53. cx += ix;
54. }
55. }
56.
57.// 如果直线与 x 轴的夹角小于度
58. else
59. {
60. while(cx != x2)
61. {
62. if(d < 0)
63. {
64. d += n2dy;
65. }
66. else
67. {
68. cy += iy;
69. d += n2dydx;
70. }
71.
72. putpixel(img, cx, cy, c);
73.
74. cx += ix;
75. }
76. }
77.}
可以看到,在画线的循环中,这个算法只用到了整数的加法,所以可以非常的高效。
接下来,我们再来看一看Bresenham画圆算法。
Bresenham画圆算法又称中点画圆算法,与Bresenham 直线算法一样,其基本的方法是利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。
为了简便起见,考虑一个圆心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。
为什么只计算八分圆周上的点就可以了呢?和上面的直线算法类似,圆也有一个“八对称性”,如下图所示。
显然,我们只需要知道了圆上的一个点的坐标 (x, y) ,利用八对称性,我们马上就能得到另外七个对称点的坐标。
和直线算法类似,Bresenham画圆算法也是用一系列离散的点来近似描述一个圆,如下图。
(上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系)
Bresenham画圆算法的流程图如下。
可以看到,与画线算法相比,画圆的循环中用到了整数的乘法,相对复杂了一些。
下面是一个C语言实现版本。
Java代码
1.view sourceprint?
2. // 八对称性
3.
4.inline void _draw_circle_8(IMAGE *img, int xc, int yc, int x, i
nt y, unsigned long c)
5.{
6. // 参数 c 为颜色值
7. putpixel(img, xc + x, yc + y, c);
8. putpixel(img, xc - x, yc + y, c);
9. putpixel(img, xc + x, yc - y, c);
10. putpixel(img, xc - x, yc - y, c);
11. putpixel(img, xc + y, yc + x, c);
12. putpixel(img, xc - y, yc + x, c);
13. putpixel(img, xc + y, yc - x, c);
14. putpixel(img, xc - y, yc - x, c);
15.}
16.
17. //Bresenham's circle algorithm
18.void draw_circle(IMAGE *img, int xc, int yc, int r, int fill, u
nsigned long c)
19.{
20. // (xc, yc) 为圆心,r 为半径
21. // fill 为是否填充
22. // c 为颜色值
23. // 如果圆在图片可见区域外,直接退出
24.
25. if(xc + r < 0 || xc - r >= img->w || yc + r < 0 || yc - r >
= img->h)
26. {
27. return;
28. }
29.
30. int x = 0, y = r, yi, d;
31. d = 3 - 2 * r;
32.
33. if(fill)
34. {
35. // 如果填充(画实心圆)
36. while(x <= y)
37. {
38. for(yi = x; yi <= y; yi ++)
39. {
40. _draw_circle_8(img, xc, yc, x, yi, c);
41. }
42. if(d < 0)
43. {
44. d = d + 4 * x + 6;
45. }
46. else
47. {
48. d = d + 4 * (x - y) + ;
49. y --;
50. }
51.
52. x++;
53. }
54. }
55. else
56. {
57. // 如果不填充(画空心圆)
58. while (x <= y)
59. {
60. _draw_circle_8(img, xc, yc, x, y, c);
61.
62. if(d < 0)
63. {
64. d = d + 4 * x + 6;
65. }
66. else
67. {
68. d = d + 4 * (x - y) + ;
69. y --;
70. }
71.
72. x ++;
73. }
74. }
75.}
可以看到,Bresenham画圆算法(中点圆算法)的实现也非常简单。