Bresenham快速画直线算法.docx
- 文档编号:25078694
- 上传时间:2023-06-04
- 格式:DOCX
- 页数:20
- 大小:203.77KB
Bresenham快速画直线算法.docx
《Bresenham快速画直线算法.docx》由会员分享,可在线阅读,更多相关《Bresenham快速画直线算法.docx(20页珍藏版)》请在冰豆网上搜索。
Bresenham快速画直线算法
Bresenham快速画直线算法
现在的计算机的图像的都是用像素表示的,无论是点、直线、圆或其他图形最终都会以点的形式显示。
人们看到屏幕的直线只不过是模拟出来的,人眼不能分辨出来而已。
那么计算机是如何画直线的呢,其实有比较多的算法,这里讲的是Bresenham的算法,是光栅化的画直线算法。
直线光栅化是指用像素点来模拟直线,比如下图用蓝色的像素点来模拟红色的直线。
给定两个点起点P1(x1,y1),P2(x2,y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。
假设直线的斜率0
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.结束
算法的具体过程是怎样的呢,其实就是在每次画点的时候选取与实现直线的交点y坐标的差最小的那个点,例如下图:
关键是如何找最近的点,每次x都递增1,y则增1或者不增1,由上图,假设已经画了d1点,那么接下来x加1,但是选d2还是u点呢,直观上可以知道d2与目标直线和x+1直线的交点比较近即纵坐标之差小也即与(x+1,y+1)点纵坐标差大于0.5,所当然是选d2,其他点了是这个道理。
一、 算法原理简介:
算法原理的详细描述及部分实现可参考:
http:
//www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
假设以(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+1,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) ξ=ξ+dy–dx,其他情况 可以看到,此时运算已经全变为整数了。 以下为算法的伪代码: ξ←0,y←y1 Forx←x1tox2do PlotPointat(x,y) If(2(ξ+dy) ξ←ξ+dy Else y←y+1,ξ←ξ+dy–dx EndIf EndFor 二、 算法的注意点: 在实际应用中,我们会发现,当dy>dx或出现Fig.2右图情况时时,便得不到想要的结果,这是由于我们只考虑dx>dy,且x,y的增量均为正的情况所致。 经过分析,需要考虑8种不同的情况,如Fig.3所示: 当然,如果直接在算法中对8种情况分别枚举,那重复代码便会显得十分臃肿,因此在设计算法时必须充分考虑上述各种情况的共性,后面将给出考虑了所有情况的实现代码。 三、 算法的实现 以下代码的测试是利用Opencv2.0进行的,根据需要,只要稍微修改代码便能适应不同环境 代码1: intCEnginApp: : Draw_Line(intx0,inty0,//startingposition intx1,inty1,//endingposition COLORREFcolor,//colorindex UNINT*vb_start,intlpitch)//videobufferandmemorypitch { //thisfunctiondrawsalinefromxo,yotox1,y1usingdifferentialerror //terms(basedonBresenahamswork) RECTcRect; //GetWindowRect(m_hwnd,&m_x2d_ClientRect); GetClientRect(m_hwnd,&cRect); ClientToScreen(m_hwnd,(LPPOINT)&cRect); ClientToScreen(m_hwnd,(LPPOINT)&cRect+1); vb_start=vb_start+cRect.left+cRect.top*lpitch; intdx,//differenceinx's dy,//differenceiny's dx2,//dx,dy*2 dy2, x_inc,//amountinpixelspacetomoveduringdrawing y_inc,//amountinpixelspacetomoveduringdrawing error,//thediscriminanti.e.errori.e.decisionvariable index;//usedforlooping //pre-computefirstpixeladdressinvideobuffer vb_start=vb_start+x0+y0*lpitch; //computehorizontalandverticaldeltas dx=x1-x0; dy=y1-y0; //testwhichdirectionthelineisgoingini.e.slopeangle if(dx>=0) { x_inc=1; }//endiflineismovingright else { x_inc=-1; dx=-dx;//needabsolutevalue }//endelsemovingleft //testycomponentofslope if(dy>=0) { y_inc=lpitch; }//endiflineismovingdown else { y_inc=-lpitch; dy=-dy;//needabsolutevalue }//endelsemovingup //compute(dx,dy)*2 dx2=dx<<1; dy2=dy<<1; //nowbasedonwhichdeltaisgreaterwecandrawtheline if(dx>dy) { //initializeerrorterm error=dy2-dx; //drawtheline for(index=0;index<=dx;index++) { //setthepixel *vb_start=color; //testiferrorhasoverflowed if(error>=0) { error-=dx2; //movetonextline vb_start+=y_inc; }//endiferroroverflowed //adjusttheerrorterm error+=dy2; //movetothenextpixel vb_start+=x_inc; }//endfor }//endif|slope|<=1 else { //initializeerrorterm error=dx2-dy; //drawtheline for(index=0;index<=dy;index++) { //setthepixel *vb_start=color; //testiferroroverflowed if(error>=0) { error-=dy2; //movetonextline vb_start+=x_inc; }//endiferroroverflowed //adjusttheerrorterm error+=dx2; //movetothenextpixel vb_start+=y_inc; }//endfor }//endelse|slope|>1 //returnsuccess return (1); }//endDraw_Line 代码2: intCEnginApp: : Draw_Line2(intx1,inty1,intx2,inty2,COLORREFcolor,UNINT*vb_start,intlpitch) { RECTcRect; //GetWindowRect(m_hwnd,&m_x2d_ClientRect); GetClientRect(m_hwnd,&cRect); ClientToScreen(m_hwnd,(LPPOINT)&cRect); ClientToScreen(m_hwnd,(LPPOINT)&cRect+1); vb_start=vb_start+cRect.left+cRect.top*lpitch; intdx=x2-x1; intdy=y2-y1; intux=((dx>0)<<1)-1;//x的增量方向,取或-1 intuy=((dy>0)<<1)-1;//y的增量方向,取或-1 intx=x1,y=y1,eps;//eps为累加误差 eps=0;dx=abs(dx);dy=abs(dy); if(dx>dy) { for(x=x1;x! =x2;x+=ux) { Plot_Pixel_32(x,y,0,255,0,255,vb_start,lpitch); eps+=dy; if((eps<<1)>=dx) { y+=uy;eps-=dx; } } } else { for(y=y1;y! =y2;y+=uy) { Plot_Pixel_32(x,y,0,255,0,255,vb_start,lpitch); eps+=dx; if((eps<<1)>=dy) { x+=ux;eps-=dy; } } } return1; } 调用代码: DD_INIT_STRUCT(ddsd); if(FAILED(lpSface[PrimarySface]->Lock(NULL,&ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR, NULL))) returnfalse; intx1,y1,x2,y2; for(inti=0;i<100;i++) { srand(time(0)); x1=rand()%750; y1=rand()%550; x2=rand()%750; y2=rand()%550; Draw_Line2(x1,y1,x2,y2,RGB(0,255,0),(UNINT*)ddsd.lpSurface,ddsd.lPitch>>2); } if(FAILED(lpSface[PrimarySface]->Unlock(NULL))) returnfalse; 效果图: TheBresenhamLine-DrawingAlgorithm ThebasicBresenhamalgorithm Considerdrawingalineonarastergridwherewerestricttheallowableslopesofthelinetotherange . Ifwefurtherrestricttheline-drawingroutinesothatitalwaysincrements x asitplots,itbecomesclearthat,havingplottedapointat (x,y),theroutinehasaseverelylimitedrangeofoptionsastowhereitmayputthe next pointontheline: ∙Itmayplotthepoint (x+1,y),or: ∙Itmayplotthepoint (x+1,y+1). So,workinginthe firstpositiveoctant oftheplane,linedrawingbecomesamatterofdecidingbetweentwopossibilitiesateachstep. Wecandrawadiagramofthesituationwhichtheplottingprogramfindsitselfinhavingplotted (x,y). Inplotting (x,y) thelinedrawingroutinewill,ingeneral,bemakingacompromisebetweenwhatitwouldliketodrawandwhattheresolutionofthescreenactuallyallowsittodraw.Usuallytheplottedpoint (x,y) willbeinerror,theactual,mathematicalpointonthelinewillnotbeaddressableonthepixelgrid.Soweassociateanerror, witheach y ordinate,therealvalueof y shouldbe .Thiserrorwillrangefrom-0.5tojustunder+0.5. Inmovingfrom x to x+1 weincreasethevalueofthetrue(mathematical)y-ordinatebyanamountequaltotheslopeoftheline, m.Wewillchoosetoplot (x+1,y) ifthedifferencebetweenthisnewvalueand y islessthan0.5. Otherwisewewillplot (x+1,y+1).Itshouldbeclearthatbysodoingweminimisethetotalerrorbetweenthemathematicallinesegmentandwhatactuallygetsdrawnonthedisplay. Theerrorresultingfromthisnewpointcannowbewrittenbackinto thiswillallowustorepeatthewholeprocessforthenextpointalongtheline,at x+2. Thenewvalueoferrorcanadoptoneoftwopossiblevalues,dependingonwhatnewpointisplotted.If (x+1,y) ischosen,thenewvalueoferrorisgivenby: Otherwiseitis: ThisgivesanalgorithmforaDDAwhichavoidsroundingoperations,insteadusingtheerrorvariable tocontrolplotting: Thisstillemploysfloatingpointvalues.Consider,however,whathappensifwemultiplyacrossbothsidesoftheplottingtestby andthenby2: Allquantitiesinthisinequalityarenowintegral. Substitute for .Thetestbecomes: Thisgivesan integer-only testfordecidingwhichpointtoplot. Theupdaterulesfortheerroroneachstepmayalsobecastinto form.Considerthefloating-pointversionsoftheupdaterules: Multiplyingthroughby yields: whichisin form. Usingthisnew``error''value, withthenewtestandupdateequationsgivesBresenham'sinteger-onlylinedrawingalgorithm: ∙Integeronly-henceefficient(fast). ∙Multiplicationby2canbeimplementedbyleft-shift. ∙Thisversionlimitedtoslopesinthefirstoctant, . HereisaC++implementationoftheBresenhamalgorithmforlinesegmentsinthefirstoctant. voidlinev6(Screen&s, unsignedx1,unsignedy1, unsignedx2,unsignedy2, unsignedcharcolour) { intdx=x2-x1, dy=y2-y1, y=y1, eps=0; for(intx=x1;x<=x2;x++){ s.Plot(x,y,colour); eps+=dy; if((eps<<1)>=dx){ y++;eps-=dx; } } } Thisisanall-integerfunction,employsleftshiftformultiplicationandeliminatesredundantoperationsbytrickyuseofthe eps variable. ThisimplementationofBresenham'salgorithmisincomplete,itdoesnotcheckthevalidityofitsarguments.Arealimplementationshoulddothis.Infact,arealimplementationofBresenham'salgorithmshoulddomorethansimplyrejectlineswithslopeslyingoutsidethefirstoctant,itshouldhandlelinesofarbitraryslope. Handlingmultipleslopes IfwetryouttheC++implementationoftheBresenhamalgorithm,wefindithassomepeculiarproperties. Asexpected,itfailstoplotlineswithnegativeslopes(tryitandseewhathappens).Italsofailstoplotlinesofpositiveslopegreaterthan1(thisisaninterestingcase,tryitalsoandseeifyoucanexplainwhatishappening). Moreunusually,wefindthattheorderinwhichtheendpointsaresuppliedtothisroutineissignificant,itwillonlyworkaslon
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Bresenham 快速 直线 算法