计算机图形学常用算法及代码大全(共40页).doc
《计算机图形学常用算法及代码大全(共40页).doc》由会员分享,可在线阅读,更多相关《计算机图形学常用算法及代码大全(共40页).doc(40页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精选优质文档-倾情为你奉上2.1.1 生成直线的DDA算法数值微分法即DDA法(Digital Differential Analyzer),是一种基于直线的微分方程来生成直线的方法。一、直线DDA算法描述:设(x1,y1)和(x2,y2)分别为所求直线的起点和终点坐标,由直线的微分方程得= m =直线的斜率(21)可通过计算由x方向的增量x引起y的改变来生成直线:xi+1=xi+x(22)yi+1=yi+y=yi+xm(23)也可通过计算由y方向的增量y引起x的改变来生成直线:yi+1=yi+y(24)xi+1=xi+x=xi+y/m(25)式(22)至(25)是递推的。二、直线DDA算法思
2、想:选定x2x1和y2y1中较大者作为步进方向(假设x2x1较大),取该方向上的增量为一个象素单位(x=1),然后利用式(21)计算另一个方向的增量(y=xm=m)。通过递推公式(22)至(25),把每次计算出的(xi+1,yi+1)经取整后送到显示器输出,则得到扫描转换后的直线。之所以取x2x1和y2y1中较大者作为步进方向,是考虑沿着线段分布的象素应均匀,这在下图中可看出。另外,算法实现中还应注意直线的生成方向,以决定x及y是取正值还是负值。三、直线DDA算法实现:1、已知直线的两端点坐标:(x1,y1),(x2,y2)2、已知画线的颜色:color3、计算两个方向的变化量:dx=x2x1
3、 dy=y2y14、求出两个方向最大变化量的绝对值: steps=max(|dx|,|dy|)5、计算两个方向的增量(考虑了生成方向): xin=dx/steps yin=dy/steps6、设置初始象素坐标:x=x1,y=y17、用循环实现直线的绘制:for(i=1;i0)?static_cast(fNum+0.5):static_cast(fNum-0.5)/*!* brief DDA画线函数* param pDC in窗口DC* param BeginPt in直线起点* param EndPt in直线终点* param LineCor in直线颜色* return 无*/void C
4、DrawMsg:DDA_DrawLine(CDC *pDC,CPoint &BeginPt,CPoint &EndPt,COLORREF LineCor)long YDis = (EndPt.y - BeginPt.y);long XDis = (EndPt.x-BeginPt.x);long MaxStep = max(abs(XDis),abs(YDis); / 步进的步数float fXUnitLen = 1.0f; / X方向的单位步进float fYUnitLen = 1.0f; / Y方向的单位步进fYUnitLen = static_cast(YDis)/static_cast(
5、MaxStep);fXUnitLen = static_cast(XDis)/static_cast(MaxStep);/ 设置起点像素颜色pDC-SetPixel(BeginPt.x,BeginPt.y,LineCor); float x = static_cast(BeginPt.x);float y = static_cast(BeginPt.y);/ 循环步进for (long i = 1;iSetPixel(FloatToInteger(x),FloatToInteger(y),LineCor);2.1.2 生成直线的Bresenham算法从上面介绍的DDA算法可以看到,由于在循环中
6、涉及实型数据的加减运算,因此直线的生成速度较慢。在生成直线的算法中,Bresenham算法是最有效的算法之一。Bresenham算法是一种基于误差判别式来生成直线的方法。一、直线Bresenham算法描述:它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一个象素。我们首先讨论m=y/x,当0m1且x1x2时的Bresenham算法。从DDA直线算法可知这些条件成立时,公式(2-2)、(2-3)可写成:xi+1=xi+1(26)yi+1=yi+m(27)有两种Bresenham算法思想,它们各自从不同角度介绍了Bresen
7、ham算法思想,得出的误差判别式都是一样的。二、直线Bresenham算法思想之一:由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(xi,yi),它是直线上点(xi,yi)的最佳近似,并且xi=xi(假设md2,说明直线上理论点离(xi+1,yi+1)象素较近,下一个象素点应取(xi+1,yi+1)。(2)当此值为负时,d10,因此pi与(d1-d2)有相同的符号;这里y=y2-y1,m=y/x;c=2y+x(2b-1)。下面对式(2-11)作进一步处理,以便得出误差判别递推公式并消除常数c。将式(2-11)中的下标i改写成i+1,得到:pi+1=2yxi+1-2xyi
8、+1+c(212)将式(2-12)减去(2-11),并利用xi+1=xi+1,可得:pi+1= pi+2y-2x(yi+1-yi)(213)再假设直线的初始端点恰好是其象素点的坐标,即满足:y1=mx1+b(214)由式(2-11)和式(2-14)得到p1的初始值: p1=2y-x(215)这样,我们可利用误差判别变量,得到如下算法表示:初始 p1=2y-x(216)当pi0时: yi+1=yi+1,xi+1=xi+1,pi+1=pi+2(y-x)否则:yi+1=yi,xi+1=xi+1, pi+1=pi+2y从式(2-16)可以看出,第i+1步的判别变量pi+1仅与第i步的判别变量pi、直线
9、的两个端点坐标分量差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(xi1,y(i+1)r)呢?设A为CD边的中点,正确的选择:若B点在A点上方,选择D点; 否则,选C点。用误差式描述为:(xi+1)=BC-AC=(yi+1-yir)-0.5(28)求递推公式
10、:(xi+2)=(yi+2-y(i+1)r)-0.5 = yi+1+m-y(i+1)r-0.5(29)当(xi+1)0时,选D点,y(i+1)r = yir+1(xi+2)= yi+1+m-yir-1-0.5=(xi+1)+m-1(210)当(xi+1)0时,选C点,y(i+1)r = yir(xi+2)= yi+1+myir-0.5=(xi+1)+m(211)初始时:(xs+1)=BC-AC=m-0.5(212)为了运算中不含实型数,同时不影响不等式的判断,将方程两边同乘一正整数。令方程两边同乘2x,即d=2x,则:初始时:d = 2y-x(213)递推式:当d0时: d=d+2(yx);y
11、+;x+;否则: d=d+2y;x+; (214)实现代码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 (i=0; i=0) y+, e=e-1;或者将e扩大2dx倍;void Bresenhamline (int x0,int y0,int x1, int y1,int color)int x, y, dx, dy;float k, e;dx = x1-x
12、0, dy = y1- y0, k=dy/dx;e=-dx, x=x0, y=y0;for (i=0; i=0) y+, e=e-2dx;四、直线Bresenham算法实现:条件:0m1且x1x21、输入线段的两个端点坐标和画线颜色:x1,y1,x2,y2,color;2、设置象素坐标初值:x=x1,y=y1;3、设置初始误差判别值:p=2y-x;4、分别计算:x=x2-x1、y=y2-y1;5、循环实现直线的生成:for(x=x1;x=0) y=y+1;p=p+2(y-x);else p=p+2y;五、直线Bresenham算法完善:现在我们修正(2-16)公式,以适应对任何方向及任何斜率线
13、段的绘制。如下图所示,线段的方向可分为八种,从原点出发射向八个区。由线段按图中所示的区域位置可决定xi+1和yi+1的变换规律。容易证明:当线段处于、区时,以|x|和|y|代替前面公式中的x和y,当线段处于、区时,将公式中的|x|和|y|对换,则上述两公式仍有效。在线段起点区分线段方向七、直线Bresenham算法特点:由于程序中不含实型数运算,因此速度快、效率高,是一种有效的画线算法。2.2.2 中点算法生成圆中点画圆算法在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定。实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高。一、中点画圆算法描述设要显示
14、圆的圆心在原点(0,0),半径为R,起点在(0,R)处,终点在(,)处,顺时针生成八分之一圆,利用对称性扫描转换全部圆。为了应用中点画圆法,我们定义一个圆函数F(x,y)=x2+y2-R2(219)任何点(x,y)的相对位置可由圆函数的符号来检测:F(x,y)0点(x,y)位于数学圆外(220)如下图所示,图中有两条圆弧A和B,假定当前取点为Pi(xi,yi),如果顺时针生成圆,那么下一点只能取正右方的点E(xi+1,yi)或右下方的点SE(xi+1,yi-1)两者之一。中点画线算法假设M是E和SE的中点,即 ,则:1、当F(M)0时,M在圆外(圆弧B),表明SE点离圆更近,应取SE点;3、当
15、F(M)=0时,在E点与SE点之中随便取一个即可,我们约定取SE点。 二、中点画圆算法思想因此,我们用中点M的圆函数作为决策变量di,同时用增量法来迭代计算下一个中点M的决策变量di+1。(221)下面分两种情况来讨论在迭代计算中决策变量di+1的推导。1、见图(a),若di0,则选择E点,接着下一个中点就是,这时新的决策变量为:(222)(a)(di0) 中点画线算法式(222)减去(221)得:di+1=di+2xi+3(223)2、见图(b),若di0,则选择SE点,接着下一个中点就是 ,这时新的决策变量为:(224)(b)(di0) 中点画线算法式(224)减去(221)得:di+1=
16、di+2(xi-yi)+5(225)我们利用递推迭代计算这八分之一圆弧上的每个点,每次迭代需要两步处理:(1)用前一次迭代算出的决策变量的符号来决定本次选择的点。(2)对本次选择的点,重新递推计算得出新的决策变量的值。剩下的问题是计算初始决策变量d0,如下图所示。对于初始点(0,R),顺时针生成八分之一圆,下一个中点M的坐标是 ,所以:(226生成圆的初始条件和圆的生成方向三、中点画圆算法实现1、输入:圆半径r、圆心(x0,y0);2、确定初值:x=0,y=r、d=5/4-r;3、While(x=y)利用八分对称性,用规定的颜色color画八个象素点(x,y); 若d0y=y-1;d=d+2(
17、x-y)+5);否则d=d+2x+3;x=x+1;五、中点画圆算法完善在上述算法中,使用了浮点数来表示决策变量d。为了简化算法,摆脱浮点数,在算法中全部使用整数,我们使用e=d-1/4代替d。显然,初值d=5/4-r对应于e=1-r。决策变量d0对应于e-1/4。算法中其它与d有关的式子可把d直接换成e。又由于e的初值为整数,且在运算过程中的迭代值也是整数,故e始终是整数,所以e-1/4等价于e0。因此,可以写出完全用整数实现的中点画圆算法。要求:写出用整数实现的中点画圆算法程序,并上机调试,观看运行结果。六、中点画圆算法程序void MidpointCircle(int x0,int y0,
18、int r,int color)int x,y;float d;x=0;y=r;d=5.0/4-r;while(x=y)putdot(x0,y0,x,y,color);if(d0)d+=x*2.0+3;elsed+=2.0*(x-y)+5;y-; x+;putdot(x0,y0,x,y,color)putpixel(x0+x,y0+y,color);putpixel(x0+x,y0-y,color);putpixel(x0-x,y0+y,color);putpixel(x0-x,y0-y,color);putpixel(x0+y,y0+x,color);putpixel(x0+y,y0-x,c
19、olor);putpixel(x0-y,y0+x,color);putpixel(x0-y,y0-x,color);2.2.3 正负算法生成圆正负法是利用平面曲线将平面划分成正负区域,对当前点产生的圆函数进行符号判别,利用负反馈调整以决定下一个点的产生来直接生成圆弧。一、正负画圆算法描述设要显示圆的圆心在原点(0,0),半径为R,初始点的坐标为(0,R),顺时针生成八分之一圆,令:F(x,y)=x2+y2-R2则圆的方程为:F(x,y)=0 (2-27)当点(x,y)在圆内时,则F(x,y)0;当点(x,y)在圆上时,则F(x,y)=0;二、正负画圆算法思想现以下图的AB弧为例,来说明正负画圆
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 常用 算法 代码 大全 40
限制150内