1、第二章 基本图形的生成与计算,第一节 直线的扫描转换 第二节 圆与椭圆的扫描转换 第三节 线画图元的属性控制,教学时数:8学时(含实验2学时) 教学目的与要求:要求学生全面了解基本图形生成的各种算法,理解掌握直线、圆、椭圆生成的基本算法以及线划图元的属性控制方法,能通过编程实现各种算法。 教学重点:直线、圆、椭圆生成的基本算法以及线划图元的属性控制方法,实验 教学难点:直线、圆、椭圆生成的基本算法,本章主要阅读文献资料: 1、刘大有主编: 计算机图形学(第1版),机械工业出版社,2003年8月版。 2、陈传波,陆枫编著: 计算机图形学基础(第1版),电子工业出版社,2002年3月版。 3、孙家
2、广等:计算机图形学(新版),清华大学出版社,1999年。,图形的扫描转换,图形的扫描转换,在光栅显示器上显示的任何一种图形,实际上都是一些具有一种或多种颜色的像素的集合。确定一个像素集合及其颜色,用于显示一个图形的过程,称为图形的扫描转换或光栅化。图形的扫描转换(光栅化):确定一个像素集合,用于显示一个图形的过程。步骤如下: 1、确定有关像素。 2、用图形的颜色或其它属性,对像素进行写操作。,所以扫描转换的主要工作是确定最佳逼近于图形的像素集。 对一维图形,不考虑线宽,则用一个像素宽的直线来显示图形。二维图形的光栅化,即区域的填充:确定区域所对应的像素集,并用所要求的颜色或图案显示。 任何图形
3、的光栅化,必须显示在一个窗口内,否则不予显示。即确定一个图形的哪些部分在窗口内,哪些在窗口外,即裁剪。裁剪通常在扫描转换之前进行。,21 直线的扫描转换,在数学上,理想的直线是没有宽度的,由无数个点构成的集合。我们只能在显示器所给定的有限个象素组成的矩阵中,确定最佳逼近于该直线的一组象素,并且按扫描顺序,用当前的写方式,对这些象素进行写操作。生成图形的常用算法有: 数值微分法 中点画线法 Bresenham直线生成算法,21 直线的扫描转换 一、数值微分法,数值微分法(digital differential analyzer,DDA) 假定直线的起点、终点分别为:(x0,y0), (x1,y
4、1),且都为整数。,21 直线的扫描转换 一、数值微分法,1、直接求交法 求表示直线段P0P1的像素集的最简单方法是利用直线方程直接计算。 假设待扫描转换的直线段为P0(x0,y0)P1(x1,y1),端点坐标均为整数再令x=x1-x0, yy1-y0,斜率ky/x,直线方程为ykx+B。 从直线的起点开始,确定最佳逼近于直线的直线,确定最佳逼近于直线的y坐标。 让x从起点到终点变化,x每增加1对应的y坐标为y=kx+B,21 直线的扫描转换 一、数值微分法,但是由于y值由y=kx+B计算而来,可能为浮点数,需要对y值取整对某个xi它所对应的yi=kxi+B的结果进行四舍五入,记为yi,rro
5、und(yi)(int)(yi+0.5),故对直线段P0P1扫描实际得到像素集为(xi,yi,r) ,其中yi,r是yi四舍五入所得的整数值。这个方法直观,但效率太低,因为每一步需要一次浮点乘法和一次四舍五入取整运算。,21 直线的扫描转换 一、数值微分法,2、增量算法 注意到公式 yi+1=kxi+1+B = k(xi+x)+B= kxi+B+kx= yi+kx 因此当x=1时, 有yi+1=yi+k,(xi+1,yi+k),(xi, round(yi),(x i , yi),栅格交点表示象素点位置,。,。,。,。,(xi+1,round(yi+k),21 直线的扫描转换 一、数值微分法,所
6、以:当x每递增1,y递增k(即直线斜率); 注意上述分析的算法仅适用于k 1的情形。在这种情况下,x每增加1,y最多增加1。 当 k 1时,必须把x,y地位互换,大家自己依此处理,要保证任意两点连线正确显示。,21 直线的扫描转换 一、数值微分法,增量算法:在一个迭代算法中,如果每一步的x、y值是用前一步的值加上一个增量来获得,则称为增量算法。 DDA算法的本质是用数值方法解微分方程,通过同时对x和y各增加一个小增量,计算下一步的x,y值,因此DDA算法就是一个增量算法。 缺点: 在此算法中,y、m必须是float,且每一步都必须对y进行舍入取整,不利于硬件实现。,21 直线的扫描转换 一、数
7、值微分法,扫描转换直线段的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);/*以颜色color显示象素*/y=y+k;,21 直线的扫描转换 一、数值微分法,例:画直线段P0(0,0)-P1(5,2) x int(y+0.5) y+0.5 0 0 0+0.5 1 0 0.4+0.5 2 1
8、0.8+0.5 3 1 1.2+0.5 4 2 1.6+0.5 5 2 2.0+0.5,21 直线的扫描转换 二、中点画线法,原理: 假定直线斜率0K1,若直线在x方向上增加一个单位, 则在y方向上的增量只能在0、1之间。 假设已确定点亮象素点P(Xp,Yp), 则下一个与直线最 接近的像素只能 是P1点或P2点。 设M为中点,Q为交点 现需确定下一个点亮的象素。,P,P2,P1,Q,21 直线的扫描转换 二、中点画线法,当M在Q的下方- P2离直线更近更近-取P2 。 M在Q的上方- P1离直线更近更近-取P1 M与Q重合, P1、P2任取一点。问题:如何判断M与Q点的关系?,假设直线的起点
9、和终点分别为(x0,y0)和(x1,y1), 则方程为:ax+by+c=0 其中a=y0-y1, b=x1-x0, c=x0y1-x1y0 由常识知:欲判断M点是在Q点上方还是在Q点下方,只需把M代入F(x,y),并检查它的符号。,21 直线的扫描转换 二、中点画线法,21 直线的扫描转换 二、中点画线法,构造判别式: d=F(M)=F(xp+1,yp+0.5) =a(xp+1)+b(yp+0.5)+c当d0,M在直线(Q点)上方,取右方P1;当d=0,选P1或P2均可,约定取P1;能否采用增量算法呢?,P,P2,P1,Q,21 直线的扫描转换 二、中点画线法,若d0-M在直线上方-取P1;
10、此时再下一个象素的判别式为d1=F(xp+2, yp+0.5)=a(xp+2)+b(yp+0.5)+c= a(xp +1)+b(yp +0.5)+c +a =d+a;增量为a 若dM在直线下方-取P2; 此时再下一个象素的判别式为d2= F(xp+2, yp+1.5)=a(xp+2)+b(yp+1.5)+c= a(xp +1)+b(yp +0.5)+c +a +b =d+a+b ; 增量为abd0= F(xp+1, yp+0.5)=a(xp+1)+b(yp+0.5)+c= axp+byp +c +a +0.5b = F(xp, yp) +a +0.5b= a +0.5b (2a+b),21 直
11、线的扫描转换 二、中点画线法,例:用中点画线法光栅化一条连接两点(0,0)和(5,2)的直线段。,x,y,d的初值和循环迭代过程中每一步的值,21 直线的扫描转换 二、中点画线法,程序Midpointline(x0,y0,x1,y1,color)int x0,y0,x1,y1,color;int a,b,d1,d2,d,x,y;a = y0-y1; b = x1 x0; d = 2 * a +b;d1 = 2*a; d2 = 2*(a+b);x = x0; y = y0;drawpixel (x,y,color);while (xx1) if (d0) x+; y+; d +=d2;else
12、x+; d +=d1;drawpixel (x,y,color); 该方法只适用于0=k=1的情形,其他情形大家自己依此处理,要保证任意两点连线 正确显示,21 直线的扫描转换 三、 Bresenham画线算法,在直线生成的算法中Bresenham算法是最有效的算法之一。 该方法最初是为数字绘图仪设计的,由于适用于光栅图形显示器,所以被广泛用于直线的扫描转换与其他一些应用。 令 k=y/x,就0k1的情况来说明Bresenham算法。 Bresenham也是通过在每列像素中确定与理想直线最近的像素来进行直线的扫描转换的。 算法原理:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺
13、序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素,21 直线的扫描转换 三、 Bresenham画线算法,右图所示,线段两端点P0P1坐标分别为(x0,y0),(x1,y1),为整数,则起点P0的像素已经确定 下一个像素的列坐标x必为x+1,行坐标要么不变,要么加1 行坐标是否加1取决于误差项d,由于线段的起始点在像素中心,所以d的初始值为0,显然在直线P0P1上,x每增加1,对应的d的值增加直线的斜率值k,d=d+k(k=dy/dx),一旦d=1则减去1 因此d始终在0,1之间,21 直线的扫描转换 三、 Bresenham画线算法,令e=d-0.5,当e=0时,x增1,
14、y增1 当e0时, x增1,y不增加 由于e=d-0.5并且d的初值为0,所以e的初值为-0.5,d,d,d,d,k,当d0.5时,直线与x+1列垂直网格线交点最接近于当前像素(x,y)的右上方像素(x+1,y+1); 而当d0.5时,更接近于像素(x+1,y); 当d0.5时,与上述二像素一样近,约定取 (x+1,y+1)。,21 直线的扫描转换 三、 Bresenham画线算法,BresenhamLine(x0,y0,x1,y1,color) int x0,y0,x1,y1,color; int x,y,dx,dy;float k,e; int e;dx = x1-x0;dy = y1-y
15、0;k = dy/dx; e = -0.5; x=x0; y=y0; e = -dx; x=x0; y=y0; for( i=0; i= 0)y=y+1; e=e-1; y=y+1; e = e - 2*dx; ,e=e+k e=e+dy/dx 2*e*dx=2*e*dx+2dy 令e=2*e*dx 则e=e+2dy 即将原来的e同时乘上2*dx,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换,处理对象:圆心在原点的圆弧 圆的八对称性,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换,圆弧的正负划分性,圆弧外的点:F(x,y)0 圆弧内的点:F(x,y)0,2-2 圆与椭圆的扫描转换 一、圆弧的
16、扫描转换中点算法,考虑对象:第二个八分圆,第一象限的八分之一圆弧,P,P1,P2,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换中点算法,问题:与直线情形类似 圆弧的隐函数:F(X,Y)=X2+Y2-R2=0 切线斜率m in -1,0 中点 M=(Xp+1,Yp-0.5),当F(M)0时,M在圆内,说明P1距离圆弧更近,取P1;当F(M)0时,P取P2,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换中点算法,构造判别式d=F(M)=F(Xp+1,Yp-0.5)=(Xp+1)2+(Yp-0.5)2-R21)若d0,取P1,再下一个象素的判别式为: d1=F(Xp+2,Yp-0.5)=d+2Xp
17、+3,沿正右方向,d的增量为2Xp+3;2)若d0,取P2,再下一个象素的判别式为:d2=F(Xp+2,Yp-1.5)=d+(2Xp+3)+(-2Yp+2)沿右下方向,d的增量为2(Xp-Yp)+5 d的初始值(在第一个象素(0,R)处),d0=F(1, R-0.5)=1.25-R 算法中有浮点数,用e=d-0.25代替,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换中点算法,所以:初始化运算d0 = 1.25 R 对应于 e 0= 1- R判别式 d 0 对应于 e -0.25 又因为:e的初值e0为整数,运算过程中的分量也为整数,故e始终为整数 所以: e -0.25 等价于 e 0 程序
18、如下(完全用整数实现):,MidpointCircle(r,color) Int r, color; int x,y,d;x = 0; y = r ; d = 1-r ;putpixel(x,y,color);,while( x y) if (d 0) d += 2*x+3; x+; else d += 2*(x-y)+5;x+ ; y-;putpixel(x,y,color); ,中点画圆的算法步骤: 输入圆的半径R。 计算初始值d=1-R,x=0,y=R。 绘制点(x,y)及其在八分圆中的另外7个对称点。 判断d的符号。若d0,则先将d更新为d+2x+3,再将(x,y)更新为(x+1,y)
19、;否则先将d更新为d+2(x-y)+5,再将(x,y)更新为(x+1,y-1)。 当xy时,重复(3)和(4),否则结束。,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换中点算法,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换中点算法,例:中点算法绘制R=12的1/8圆弧的判别式及坐标值,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,基本原理 当已知一条曲线的方程时,正负法是一个十分有效的绘图方法。假定要绘制的曲线的方程为F(x,y)=0,它具有正负划分性,即该曲线将平面分成了三个点集: G+=(x,y)|F(x,y)0 G0=(x,y)|F(x,y)=0即曲线本身 G-=(x,y)|
20、F(x,y)0,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,基本原理假定初始点P0 G0,沿某方向(假定为X轴)前进X时,到达G+或G-(假定为G-)中的P1,在沿另外一方向(Y轴)前进Y,到达P2。若P2 G+,则改变前进方向,否则继续向G+前进。 ,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,基本原理但上述想法只有在一定的条件下才能顺利进行。例如对曲线当x0时曲线上下摆动非常厉害。沿x轴方向前进一个步长可能会跨过曲线的几个周期,更谈不上围绕曲线前进了。因此要对曲线加必要的限制。,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,基本原理 易画曲线 F(x,y)具有正
21、负划分性 F(x,y)二阶连续 曲线上各点曲率半径足够大,即在确定的的度量下,曲线比较平坦,初始定向 确定 的符号,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,前进规则取判别式,2-2 圆与椭圆的扫描转换 一、圆弧的扫描转换正负法,正负法生成圆弧 考虑第一像限圆弧段 圆弧是易画曲线 取初始点P0(x0,y0) = (0,R) 初始定向为:D = 4, X=1, y = -1 则P1为 (x0+1,y0) = (1,R); 又因为 D(Pi) = F(Pi)F(P1) = F(Pi)F(1,R),所以由前进规则得前进点递推公式 1)
22、当D(Pi) =0时,Xi+1 = Xi, Yi+1 = yi-1;当D(Pi) 0时,Xi+1 = Xi+1, Yi+1 = yi; 判别式D(Pi+1)的递推公式? 判别式的初值D(P1) = F(P1)= F(1,R) = 1,2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换,F(x,y)=b2x2+a2y2-a2b2=0 椭圆的对称性,只考虑第一象限椭圆弧生成,分上下两部分,以切线斜率为-1的点作为分界点。 椭圆上一点处的法向:,2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换,在上半部分,法向量的y分量大 在下半部分,法向量的x分量大,若在当前中点处,法向量( 2b2 (Xp+1) ,2
23、a2 (Yp-0.5)的y分量比x分量大, 即: b2 (Xp+1) a2 (Yp-0.5), 而在下一中点,不等式改变方 向,则说明椭圆弧从上部分转入下部分,2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换中点画法,与圆弧中点算法类似:确定一个象素后,接着在两个候选象素的中点计算一个判别式的值,由判别式的符号确定更近的点先讨论椭圆弧的上部分(Xp,Yp)中点(Xp+1,Yp-0.5) d1=F(Xp+1,Yp-0.5)= b2(Xp+1)2+a2(Yp-0.5)2-a2b2,2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换中点画法,根据d1的符号来决定下一像素是取正右方的那个,还是右下方的那个。
24、 x每次增加1,确定y值的增量。若d10,中点在椭圆内,取正右方象素,判别式更新为:d1=F(Xp+2,Yp-0.5)=d1+b2(2Xp+3)d1的增量为b2(2Xp+3)当d10,中点在椭圆外,取右下方象素,更新判别式:d1=F(Xp+2,Yp-1.5)=d1+b2(2Xp+3)+a2(-2Yp+2)d1的增量为b2(2Xp+3)+a2(-2Yp+2)d1的初始条件:椭圆弧起点为(0,b),第一个中点为(1,b-0.5) 初始判别式:d10=F(1,b-0.5)=b2+a2(-b+0.25),2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换中点画法,转入下一部分,下一象素可能是一正下方或右下
25、方,此时判别式要初始化。 y每次减少1,确定x值的增量。d2 = F(Xp+0.5,Yp-1) = b2(Xp+0.5)2+a2(Yp-1)2-a2b2 若d2=0,则d2 = F(Xp+0.5,Yp-2) = d2 + a2(-2Yp+3) 下半部分弧的终止条件为 y = 0,2-2 圆与椭圆的扫描转换 二、椭圆的扫描转换中点画法,MidpointEllipe(a,b, color) int a,b,color; int x,y; float d1,d2;x = 0; y = b;d1 = b*b +a*a*(-b+0.25);putpixel(x,y,color);while( b*b*(
26、x+1) a*a*(y-0.5)if (d10)d1 +=b*b*(2*x+3); x+;else d1 +=(b*b*(2*x+3)+a*a*(-2*y+2)x+; y-; putpixel(x,y,color);/上部分,d2 = sqr(b*(x+0.5) +sqr(a*(y-1) sqr(a*b); while(y 0) if (d2 0) d2 +=b*b*(2*x+2)+a*a*(-2*y+3);x+; y-;elsed2 += a*a*(-2*y+3); y-; putpixel(x,y,color); ,2-3 线画图元的属性控制,前面我们介绍的直线、圆和椭圆的扫描转换算法仅用
27、于单线宽、实线型的直线、圆和椭圆),但是,在实际应用中通常使用指定线宽和线型的直线、圆和椭圆。,2-3 线画图元的属性控制,一、线宽控制 1、像素复制方法 绘制宽度为k个象素的线画图元,在扫描转换时同时显示k个象素。 当图元在该象素点的斜率m(-1,1)时,垂直方向象素复制 否则,水平方向象素复制,优点: 实现简单 缺点: 线段两端要么为水平的,要么是竖直的 折线顶点处有缺口,2-3 线画图元的属性控制,图元的宽度不均匀宽度为奇数个像素的图元效果较好,对产生宽度为偶数个像素的图元,由于没有中心,所产生的图元不对称,效果不好。,2-3 线画图元的属性控制,2、移动刷子方法把宽度为指定线宽的刷子的
28、中心沿直线移动,即可获得相应的宽图元。,1个象素宽的图元,刷子依次以各象素为中心,55的方形刷子,2-3 线画图元的属性控制,3、填充法要产生宽度为k的图元,可以首先计算出距原理想图元k/2的两条等距线将它们连接起来就构成了宽度为k的区域,然后调用填充图元的生成函数将其填充,便得到了所求的宽度为k的图元。优点: 生成的图元宽度均匀 生成的图形质量高 缺点 计算量大 有些图形的等距线难以获得,例1:PaintBrush,例2:PhotoShop,二、线型控制 在实际应用中,除了使用单像素宽的线条,还经常使用指定线型和线宽的直线与弧线。 线型:实线、虚线、短划线和点划线,2-3 线画图元的属性控制
29、,4种常用的线型,2-3 线画图元的属性控制,二、线型控制 线型控制一般用一个位屏蔽器来实现。例如我们可以用1个16位的整数表示一个位串,当当前像素对应的位为1时显示该像素,为0时不显示。用这样的位串控制线型时,线型必须以16个象素为周期进行重复。在程序实现时只要将前面的扫描转换程序中无条件写像素语句PutPixel(x,y,color);改为if(位串)%16)PutPixel(x,y,color);就行了,i为整型变量,用来指示当前像素的序号,每处理一个象素,值增加1,例子:PowerPoint,本章小结,基本概念: 图形的扫描转换或光栅化 圆的八对称性 椭圆的对称性 基本算法: 直线的扫
30、描转换: 数值微分法 直接求交法: y=kx+b, yi,rround(yi)(int)(yi+0.5) 增量算法 : yi+1=yi+k 中点画线法: d=F(M)=F(xp+1,yp+0.5) =a(xp+1)+b(yp+0.5)+c Bresenham直线生成算法: d=d+k(k=dy/dx),圆弧的扫描转换 中点算法: d=F(M)=F(Xp+1,Yp-0.5)=(Xp+1)2+(Yp-0.5)2-R2 正负法: 椭圆的扫描转换 中点算法 线元属性的控制 线宽控制 像素复制方法 移动刷子法 填充法 线型控制,例:已知直线的起点为(x1,y1),终点为(xn,yn),用DDA增量法写出
31、该直线生成的流程图。,输入两点坐标(x1,y1)、(xn,yn),计算增量值x=xn-x1、y=yn-y1,确定k=y/x,|k|1,真,假,for(i=1;i abs(x);i+),x=x+1; y=int(y+k+0.5) Putpixel(x,y,color),for(i=1;i abs(y);i+),y=y+1; x=int(x+1/k+0.5) Putpixel(x,y,color),1、名词解释:扫描转换、圆的八对称性、椭圆的对称性。 2、利用DDA算法、中点算法、Bresenham算法扫描转换直线段p1p2,其中p1为(0,0),p2为(20,15)。 3、试用Bresenham算法画直线段的原理推导斜率为负且大于1的直线段绘制过程(要求写清原理、误差函数、递推公式及最终画图过程)。 4、利用中点算法扫描转换圆心在点O,R=8的圆。 5、利用中点画圆算法的原理推导第一象限x=y到y=0圆弧段的扫描转换算法(要求写清原理、误差函数、递推公式及最终画图过程)。 6、利用中点算法扫描转换a=6,b=5的椭圆。 7、试推导按逆时针方向生成第一象限椭圆弧段的中点画椭圆算法(要求写清原理、误差函数、递推公式及最终画图过程)。 8、试比较直线线宽的几种处理方式。,本章思考题,