第三章 基 本 图 形 的 生 成 本 章 主 要 内 容 直线段的扫描转换算法 圆弧的扫描转换算法 多边形的扫描转换与区域填充 字符 裁剪

Slides:



Advertisements
Similar presentations
2.8 函数的微分 1 微分的定义 2 微分的几何意义 3 微分公式与微分运算法则 4 微分在近似计算中的应用.
Advertisements

2.6 隐函数微分法 第二章 第二章 二、高阶导数 一、隐式定义的函数 三、可微函数的有理幂. 一、隐函数的导数 若由方程 可确定 y 是 x 的函数, 由 表示的函数, 称为显函数. 例如, 可确定显函数 可确定 y 是 x 的函数, 但此隐函数不能显化. 函数为隐函数. 则称此 隐函数求导方法.
练一练: 在数轴上画出表示下列各数的点, 并指出这些点相互间的关系: -6 , 6 , -3 , 3 , -1.5, 1.5.
§3.4 空间直线的方程.
《解析几何》 -Chapter 3 §7 空间两直线的相关位置.
第八章 向量代数 空间解析几何 第五节 空间直线及其方程 一、空间直线的点向式方程 和参数方程 二、空间直线的一般方程 三、空间两直线的夹角.
3.4 空间直线的方程.
圆的一般方程 (x-a)2 +(y-b)2=r2 x2+y2+Dx+Ey+F=0 Ax2+Bxy+Cy2+Dx+Ey+ F=0.
解析几何 4.1.2圆的一般方程 邵东一中高1数学组 林真武.
圆复习.
第三章 函数逼近 — 最佳平方逼近.
第二章 二次函数 第二节 结识抛物线
清仓处理 跳楼价 满200返160 5折酬宾.
Computer Graphics 第四章 多边形填充.
第四章 多边形填充.
第4章 基本光栅图形算法.
第二章 导数与微分 第二节 函数的微分法 一、导数的四则运算 二、复合函数的微分法.
2-7、函数的微分 教学要求 教学要点.
点与圆的位置关系 云衢中学 孟战军.
七 年 级 数 学 第二学期 (苏 科 版) 复习 三角形.
探索三角形相似的条件(2).
第三章 基 本 图 形 的 生 成 本 章 主 要 内 容 直线段的扫描转换算法 圆弧的扫描转换算法 多边形的扫描转换与区域填充 字符 裁剪
强连通分量 无向图 1、任意两顶点连通称该图为连通图 2、否则将其中的极大连通子图称为连通分量 A D C B E 有向图
计算机科学与技术专业课程 计算机图形学 宋传鸣 辽宁师范大学计算机与信息技术学院.
计算机数学基础 主讲老师: 邓辉文.
1 直线生成算法(DDA、BRES) 2 圆生成算法(Mid) 3 多边形填充算法(扫描线、区域)
第五章 基本图形生成算法 如何在指定的输出设备上根据坐标描述构造基本二维几何图形(点、直线、圆、椭圆、多边形域、字符串及其相关属性等)。
第3章 二维线画图元的生成.
双曲线的简单几何性质 杏坛中学 高二数学备课组.
§7.2 直线的方程(1) 1、经过两点P1(x1,y1),P2(x2,y2)的斜率公式: 2、什么是直线的方程?什么是方程的直线?
使用矩阵表示 最小生成树算法.
2.1.2 空间中直线与直线 之间的位置关系.
实数与向量的积.
线段的有关计算.
第四章 基本图形生成算法 (一) 2019/4/21 Thank you for your time today.
第四章 一次函数 4. 一次函数的应用(第1课时).
第二节 圆的扫描转换算法 x2+y2=R2.
⑴当∠MBN绕点B旋转到AE=CF时(如图1),比较AE+CF与EF的大小关系,并证明你的结论。
3.3 垂径定理 第2课时 垂径定理的逆定理.
第四章 基本图形生成算法 (二) 2019/4/25 IBM Confidential.
直线和圆的位置关系.
第4章 Excel电子表格制作软件 4.4 函数(一).
直线与圆的位置关系.
复习: 若A(x1,y1,z1) , B(x2,y2,z2), 则 AB = OB - OA=(x2-x1 , y2-y1 , z2-z1)
正切函数的图象和性质 周期函数定义: 一般地,对于函数 (x),如果存在一个非零常数T,使得当x取定义域内的每一个值时,都有
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
抛物线的几何性质.
1.设A和B是集合,证明:A=B当且仅当A∩B=A∪B
第三章 函数的微分学 第二节 导数的四则运算法则 一、导数的四则运算 二、偏导数的求法.
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
第 四 章 迴歸分析應注意之事項.
直线和圆的位置关系 ·.
O x y i j O x y i j a A(x, y) y x 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算 5.4 平面向量的坐标运算.
分数再认识三 真假带分数的练习课.
第15讲 特征值与特征向量的性质 主要内容:特征值与特征向量的性质.
多边形填充 计算机科学与技术系.
§2 方阵的特征值与特征向量.
§2-2 点的投影 一、点在一个投影面上的投影 二、点在三投影面体系中的投影 三、空间二点的相对位置 四、重影点 五、例题 例1 例2 例3
线性回归.
24.4弧长和扇形面积 圆锥的侧面积和全面积.
第四节 向量的乘积 一、两向量的数量积 二、两向量的向量积.
第二章 图形基元的显示 扫描转换 将图形描述转换成用象素矩阵表示的过程 图形基元(输出图形元素)图形系统能产生的最基本图形 线段、圆、多边形.
第四章 函数的 积分学 第七节 定积分的换元积分法     与分部积分法 一、定积分的换元积分法 二、定积分的分部积分法.
三角 三角 三角 函数 余弦函数的图象和性质.
位似.
最小生成树 最优二叉树.
3.3.2 两点间的距离 山东省临沂第一中学.
§3.1.2 两条直线平行与垂直的判定 l1 // l2 l1 ⊥ l2 k1与k2 满足什么关系?
9.3多项式乘多项式.
Presentation transcript:

第三章 基 本 图 形 的 生 成 本 章 主 要 内 容 直线段的扫描转换算法 圆弧的扫描转换算法 多边形的扫描转换与区域填充 字符 裁剪 反走样 消隐

3.1 直线段的扫描转换算法 直线的扫描转换 三个常用算法 确定最佳逼近于该直线的一组像素 按扫描线顺序,对这些像素进行写操作 数值微分(DDA)算法 中点画线法 Bresenham画线算法

3.1.1 数值微分(DDA)法 基本方法(不是DDA方法) 已知过端点 的直线段L:y = kx+b 则有: x=x+xInc; 而像素 (x, round(y)) 作为当前点的坐标。 评价:①这种方法直观易懂,②但效率太低,因为画每一个点需要一次浮点乘法和一次舍入运算。

3.1.1 数值微分(DDA)法 数值微分(DDA)算法---增 量 算 法 分 析: 1:如果 | k | ≤1,则 ( X i+1 ,Yi + 1) (X i , Yi) 栅格交点表示像素点位置 。 分 析: 1:如果 | k | ≤1,则 yi+1 = kxi+1 + b = kxi + kx + b = yi + kx 当x =1;有:yi+1 = yi+k ……式3-1 当x =-1;有:yi+1 = yi-k ……式3-2 乘法运算

3.1.1 数值微分(DDA)法 2:如果 | k| >1,有 当y =1;有:xi+1 = xi + 1/k ……式3-3 增量算法:在一个迭代算法中,如果每一步的x、y值是用前一步的值加上一个增量来获得,则称为增量算法。如:式3-1、式3-2、式3-3、式3-4那样; DDA算法便是一个增量算法。尊重历史,继往开来 乘法运算

3.1.1 数值微分(DDA)法 #define round(x) ((int)(x+0.5)) 取整运算 #define round(x) ((int)(x+0.5)) void DDALine(int x0,int y0,int x1,int y1,int color)  int dx = x1- x0, dy = y1- y0, steps, k; float xin,yin,x = x0 ,y = y0 ; if(abs(dx)>abs(dy)) steps = abs(dx); else steps = abs(dy); xin = dx/(float)steps; yin = dy/(float)steps; setpixel (round(x), round(y), color); for (k=0;k<steps;k++) x + = xin; y + = yin;  浮点运算

3.1.1 数值微分(DDA)法 关于DDA的评价: 改进措施: DDA方法计算像素位置比直接采用方程式更快; 利用了光栅特性消除了3-1式中的乘法; 浮点增量的连续迭代加中取整误差的积累,导致长线段所计算的像素位置偏离实际线段; 程序DDAline中的取整函数和浮点运算仍然十分耗时; 改进措施: 将增量k、1/k分解成整数和小数部分,使所有计算都改进成整数DDA算法的性能;

3.1.2 中点画线法 采用增量思想的DDA算法,每计算一个象素,只需计算一个加法,是否最优? 如非最优,如何改进? 目标:进一步将一个加法改为一个整数加法。 新思路-> DDA算法采用两点式,可否采用其他的直线表示方式?

3.1.2 中点画线法 基本思想 当前象素点为(xp, yp) 。下一个象素点为P1 或P2 。 设M=(xp+1, yp+0.5),为p1与p2 之中点,Q为理想直线与x=xp+1 垂线的交点。将Q与M的y坐标进 行比较。 当M在Q的下方,则P2 应为 下一个象素点; M在Q的上方,应取P1为下一点。

3.1.2 中点画线法 构造判别式:d=F(M)=F(xp+1,yp+0.5) =a(xp+1)+b(yp+0.5)+c 其中a=y0-y1, b=x1-x0, c=x0y1-x1y0 当d<0,M在L(Q点)下方,取右上方P2为下一个象素; 当d>0,M在L(Q点)上方,取右方P1为下一个象素; 当d=0,选P1或P2均可,约定取P1为下一个象素;

3.1.2 中点画线法 这样做,每一个像素的计算量是4个加法,两个乘法。 如果也采用增量算法呢? d 是xp, yp的线性函数,因此可采用增量计算,提高运算效率。

3.1.2 中点画线法 若当前象素处于d0情况,则取正右方象素P1 (xp+1, yp), 要判下一个象素位置,应计算 d1=F(xp+2, yp+0.5)=a(xp+2)+b(yp+0.5)=d+a; 增量为a 若d<0时,则取右上方象素P2 (xp+1, yp+1)。要判断再下一象素,则要计算 d2= F(xp+2, yp+1.5)=a(xp+2)+b(yp+1.5)+c=d+a+b ;增量为a+b

3.1.2 中点画线法 至此,至少新算法可以和DDA算法一样好。 能否再做改进?能否实现整数运算? 画线从(x0, y0)开始,d的初值 d0=F(x0+1, y0+0.5)=F(x0, y0)+a+0.5b =a+0.5b。 可以用2d代替d来摆脱小数,提高效率。 令 d0=2a+b, d1=2a, d2=2a+2b,我们有如下算法 。

3.1.2 中点画线法 void Midpoint Line (int x0,int y0,int x1, int y1,int 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 (x<x1) { if (d<0) {x++, y++, d+=d2; } else {x++, d+=d1;} drawpixel (x, y, color); } /* while */ } /* mid PointLine */

3.1.2 中点画线法 例:用中点画线法 i xi yi d 1 0 0 1 2 1 0 -3 3 2 1 3 4 3 1 -1 1 0 0 1 2 1 0 -3 3 2 1 3 4 3 1 -1 5 4 2 5

3.1.3 Bresenham算法 基本思想 DDA算法采用点斜式,中点法采用隐式表示。 中点法可以有整数算法。 其他表示可以推出整数算法吗?

3.1.3 Bresenham算法 d2 d1 Yk+3 Yk+2 Yk+1 Yk Yk+1 Y Yk Xk Xk+1 Xk+2 Xk+3

3.1.3 Bresenham算法 决策参数: 可见,如果 pk<0,即d1<d2,yk+1=yk,否则 yk+1=yk+1

3.1.3 Bresenham算法 例:画直线从(20,10)到(30,18),斜率为0.8. △x=10, △y=8;初始决策参数为p0=2△y-△x=6. k pk (xk+1,yk+1) 6 (21,11) 5 (26,15) 1 2 (22,12) (27,16) -2 (23,12) 7 (28,16) 3 14 (24,13) 8 (29,17) 4 10 (25,14) 9 (30,18)

3.1.3 Bresenham算法

3.1.3 Bresenham算法

3.2圆弧扫描转换算法 圆弧的扫描转换 四个常用算法 确定最佳逼近于该圆弧的一组象素 按扫描线顺序,对这些象素进行写操作 中点画圆法 Bresenham画圆算法 生成圆弧的正负法 圆的内接正多边形逼近法

圆弧扫描算法 下面仅以圆心在原点、半径R为整数的圆为例,讨论圆的生成算法。 假设圆的方程为: X2 + Y2 = R2

3.2 圆弧扫描算法 X2 + Y2 = R2 Y = Sqrt(R2 - X2) 在一定范围内,每给定一 X值,可得一Y值。 缺点:浮点运算,开方, 取整,不均匀。 y x

中点画圆法 利用圆的对称性,只须讨论1/8圆。第二个8分圆 P为当前点亮象素,那么,下一个点亮的象素可能是P1(Xp+1,Yp)或P2(Xp +1,Yp -1)。 P(Xp ,Yp ) P1 M P2

中点画圆法 构造函数:F(X,Y)=X2 + Y2 - R2 ;则 F(X,Y)= 0 (X,Y)在圆上; 设M为P1、P2间的中点,M=(Xp+1,Yp-0.5) P1 M P2

F(M)< 0 ->M在圆内-> 取P1 F(M)>= 0 ->M在圆外-> 取P2 中点画圆法 有如下结论: F(M)< 0 ->M在圆内-> 取P1 F(M)>= 0 ->M在圆外-> 取P2 为此,可采用如下判别式: P1 M P2

中点画圆法 d = F(M) = F(xp + 1, yp - 0.5) =(xp + 1)2 + (yp - 0.5) 2 - R2 若d<0, 则P1 为下一个象素,那么再下一个象素的判别式为: d2 = F(xp + 2, yp - 0.5) = (xp + 2)2 + (yp - 0.5) 2 - R2 = d + 2xp +3 即d 的增量为 2xp +3. P1 M P2

中点画圆法 若d>=0, 则P2 为下一个象素,那么再下一个象素的判别式为: d1 = F(xp + 2, yp - 1.5) = (xp + 2)2 + (yp - 1.5) 2 - R2 = d + (2xp + 3)+(-2 yp + 2) 即d 的增量为 2 (xp - yp) +5. d的初值: d0 = F(1, R-0.5) = 1 + (R-0.5)2 - R2 = 1.25 - R P1 M P2

中点画圆法 MidpointCircle(int r, int color) { int x,y; float d; x=0; y=r; d=1.25-r; drawpixel(x,y,color); while(x<y){ if(d<0){ d+ = 2*x+3; x++ } else{d+ = 2*(x-y) + 5; x++;y--; } }

中点画圆法 为了进一步提高算法的效率,可以将上面的算法中的浮点数改写成整数,将乘法运算改成加法运算,即仅用整数实现中点画圆法。 使用e=d-0.25代替d e0=1-R

Bresenham画圆算法 现在从A点开始向右下方逐点来寻找弧AB要用的点。如图中点Pi-1是已选中的一个表示圆弧上的点,根据弧AB的走向,下一个点应该从Hi或者Li中选择。显然应选离AB最近的点作为显示弧AB的点。 假设圆的半径为R,显然,当xhi2 + yhi2 -R2 ≥ R2 - (xli2 + yli2)时,应该取Li。否则取Hi。 令di = xhi2 + yhi2 + xli2 + yli2 - 2R2 显然,当di ≥0 时应该取Li。否则取Hi。

Bresenham画圆算法 剩下的问题是如何快速的计算di。设图中Pi-1的坐标为(xi-1,yi-1),则Hi和Li的坐标为(xi,yi-1)和(xi,yi-1-1 ) di = xi2 + yi-12 + xi2 + (yi-1-1)2 - 2R2 =2xi2 + 2yi-12 - 2yi-1 - 2R2 Hi+1和Li+1的坐标为(xi+1,yi)和(xi+1,yi-1 ) di+1 = (xi + 1)2 + yi2 + (xi + 1)2 + (yi - 1)2 - 2R2 =2xi2 + 4xi + 2yi2 - 2yi - 2R2 + 3

Bresenham画圆算法 当di<0时->取Hi -> yi=yi-1,则 di+1 = di + 4xi-1 + 7 当di ≥ 0时->取Li -> yi=yi-1-1,则 di+1 = di + 4(xi-1-yi-1) + 11 易知 x0=0,y0=R,x1=x0+1 因此 d0=12 + y02 + 12 +(y0 - 1)2 - 2R2 = 3 - 2y0 = 3 - 2R

3.3 多边形的扫描转换与区域填充 多边形有两种重要的表示方法:顶点表示和点阵表示。 多边形的扫描转换:把多边形的顶点表示转换为点阵表示。 区域可采用内点表示和边界表示两种表示形式。 区域填充:指先将区域的一点赋予指定的颜色,然后将该颜色扩展到整个区域的过程。

多边形分为凸多边形、凹多边形、含内环的多边形。

3.3.1多边形的扫描转换 2.3.1.1 扫描线算法 基本思想: 对于一条扫描线填充过程可以分为四个步骤: 按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作。 对于一条扫描线填充过程可以分为四个步骤: 求交 排序 配对 填色

一个多边形与若干扫描线

数据结构 活性边表(AET):把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中 结点内容 △x:从当前扫描线到下一条扫描线间x的增量 ymax:该边所交的最高扫描线号ymax

新边表(NET): 存放在该扫描线第一次出现的边。若某边的较低端点为ymin,则该边就放在扫描线ymin的新边表中

若y=yi,x=x i;则当y = y i+1时, 假定当前扫描线与多边形某一条边的交点的x坐标为x,则下一条扫描线与该边的交点不要重计算,只要加一个增量△x。 设该边的直线方程为:ax+by+c=0; 若y=yi,x=x i;则当y = y i+1时, 其中 为常数

扫描线与多边形的顶点或边界相交时,必须正确的交点的取舍。只需检查顶点的两条边的另外两个端点的y值。按这两个y值中大于交点y值的个数是0,1,2来决定。

算法过程 void polyfill (polygon, color) int color; 多边形 polygon; { for (各条扫描线i ) { 初始化新边表头指针NET [i]; 把y min = i 的边放进边表NET [i]; } y = 最低扫描线号; 初始化活性边表AET为空; for (各条扫描线i )

把新边表NET [i] 中的边结点用插入排序法插入AET表,使之按x坐标递增顺序排列; 遍历AET表,把配对交点区间(左闭右开)上的象素(x, y),用drawpixel (x, y, color) 改写象素颜色值; 遍历AET表,把y max= i 的结点从AET表中删除,并把y max > i 结点的x值递增x; 若允许多边形的边自相交,则用冒泡排序法对AET表重新排序; } } /* polyfill */

3.3.1.2边界标志算法 基本思想: 帧缓冲器中对多边形的每条边进行直线扫描转换,亦即对多边形边界所经过的象素打上标志。 然后再采用和扫描线算法类似的方法将位于多边形内的各个区段着上所需颜色。 使用一个布尔量inside来指示当前点是否在多边形内的状态。

算法过程 void edgemark_fill(polydef, color) 多边形定义 polydef; int color; inside = FALSE; for (每条与多边形polydef相交的扫描线y ) for (扫描线上每个象素x ) { if(象素 x 被打上边标志) inside = ! (inside); if(inside!= FALSE) drawpixel (x, y, color); else drawpixel (x, y, background); }

用软件实现时,扫描线算法与边界标志算法的执行速度几乎相同, 但由于边界标志算法不必建立维护边表以及对它进行排序,所以边界标志算法更适合硬件实现,这时它的执行速度比有序边表算法快一至两个数量级。

3.3.2区域填充算法 区域指已经表示成点阵形式的填充图形,它是象素的集合。 区域可采用内点表示和边界表示两种表示形式。 区域可分为4向连通区域和8向连通区域。 区域填充指先将区域的一点赋予指定的颜色,然后将该颜色扩展到整个区域的过程。区域填充算法要求区域是连通的

4向连通区域和8向连通区域 四个方向运动 八个方向运动 四连通区域 八连通区域

3.3.2.1区域填充的递归算法 内点表示的4连通区域的递归填充算法: void FloodFill4(int x,int y,int oldcolor,int newcolor) { if(getpixel(x,y)==oldcolor) //属于区域内点oldcolor { drawpixel(x,y,newcolor); FloodFill4(x,y+1,oldcolor,newcolor); FloodFill4(x,y-1,oldcolor,newcolor); FloodFill4(x-1,y,oldcolor,newcolor); FloodFill4(x+1,y,oldcolor,newcolor); }

边界表示的4连通区域的递归填充算法: void BoundaryFill4(int x,int y,int boundarycolor,int newcolor) { int color; if(color!=newcolor && color!=boundarycolor) { drawpixel(x,y,newcolor); BoundaryFill4 (x,y+1, boundarycolor,newcolor); BoundaryFill4 (x,y-1, boundarycolor,newcolor); BoundaryFill4 (x-1,y, boundarycolor,newcolor); BoundaryFill4 (x+1,y, boundarycolor,newcolor); }

3.3.2.2区域填充的扫描线算法 算法步骤: 首先填充种子点所在扫描线上的位于给定区域的一个区段 然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。 反复这个过程,直到填充结束。

(1)初始化:堆栈置空。将种子点(x,y)入栈。 (2)出栈:若栈空则结束。否则取栈顶元素(x,y),以y作为当前扫描线。 (3)填充并确定种子点所在区段:从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xl和xr。 (4)并确定新的种子点:在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的象素。若存在非边界、未填充的象素,则把每一区间的最右象素作为种子点压入堆栈,返回第(2)步。 上述算法对于每一个待填充区段,只需压栈一次;因此,扫描线填充算法提高了区域填充的效率。