第三章 基 本 图 形 的 生 成

58
1 第第第 第 第 第 第 第 第 第 第 第 第 第 第 第 1.第第第第第第第第第第 2.第第第第第第第第第 3.第第第第第第第第第第第第第 4.第第 5.第第 6.第第第 7.第第

description

第三章 基 本 图 形 的 生 成. 本 章 主 要 内 容 直线段的扫描转换算法 圆弧的扫描转换算法 多边形的扫描转换与区域填充 字符 裁剪 反走样 消隐. 3.1 直线段的扫描转换算法. 直线的扫描转换 确定最佳逼近于该直线的一组像素 按扫描线顺序,对这些像素进行写操作 三个常用算法 数值微分 (DDA) 算法 中点画线法 Bresenham 画线算法. 3.1.1 数值微分 (DDA) 法. 基本方法 (不是 DDA 方法) 已知 过端点 的直线段 L : y = kx+b 则有: - PowerPoint PPT Presentation

Transcript of 第三章 基 本 图 形 的 生 成

Page 1: 第三章 基 本 图 形 的 生 成

第 1 页

第三章 基 本 图 形 的 生 成

本 章 主 要 内 容1.直线段的扫描转换算法2.圆弧的扫描转换算法3.多边形的扫描转换与区域填充4.字符5.裁剪6.反走样7.消隐

Page 2: 第三章 基 本 图 形 的 生 成

第 2 页

3.1 直线段的扫描转换算法

直线的扫描转换直线的扫描转换•确定最佳逼近于该直线的一组像素确定最佳逼近于该直线的一组像素•按扫描线顺序,对这些像素进行写操作按扫描线顺序,对这些像素进行写操作

三个常用算法•数值微分数值微分 (DDA)(DDA) 算法算法•中点画线法中点画线法• BresenhamBresenham 画线算法画线算法

Page 3: 第三章 基 本 图 形 的 生 成

第 3 页

3.1.1 数值微分 (DDA) 法• 基本方法(不是 DDA 方法) 已知过端点 的直线段 L : y = kx+b

则有:

x=x+xInc ;

而像素 (x, round(y)) 作为当前点的坐标。

评价:①这种方法直观易懂,②但效率太低,因为画每一个点需要一次浮点乘法和一次舍入运算。

01

01

xx

yyk

),(),,( 111000 yxPyxP

bkxy

Page 4: 第三章 基 本 图 形 的 生 成

第 4 页

3.1.1 数值微分 (DDA) 法•数值微分数值微分 (DDA)(DDA) 算法算法 ------ 增 量 算 法

( X i+1 ,Yi + 1)(X i , Yi) 栅格交点表示像素点位置。

。 。

分 析:

1: 如果 | k | ≤1 ,则 yi+1 = kxi+1 + b

= kxi + kx + b = yi + kx

当 x =1; 有: yi+1 = yi+k ……式 3-1 当 x =-1; 有: yi+1 = yi-k ……式 3-2

乘法运算

Page 5: 第三章 基 本 图 形 的 生 成

第 5 页

3.1.1 数值微分 (DDA) 法2: 如果 | k| > 1 ,有 当 y =1; 有: xi+1 = xi + 1/k …… 式 3-3

当 y=-1; 有: xi+1 = xi - 1/k …… 式 3-4

增量算法:在一个迭代算法中,如果每一步的 x 、y 值是用前一步的值加上一个增量来获得,则称为增量算法。如:式 3-1 、式 3-2 、式 3-3 、式 3-4 那样;

DDA 算法便是一个增量算法。尊重历史,继往开来

乘法运算

Page 6: 第三章 基 本 图 形 的 生 成

第 6 页

3.1.1 数值微分 (DDA) 法#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; setpixel (round(x), round(y), color);

浮点运算

取整运算

Page 7: 第三章 基 本 图 形 的 生 成

第 7 页

3.1.1 数值微分 (DDA) 法

关于 DDA 的评价:1. DDA 方法计算像素位置比直接采用方程式更快;2. 利用了光栅特性消除了 3-1 式中的乘法;3. 浮点增量的连续迭代加中取整误差的积累,导致

长线段所计算的像素位置偏离实际线段;4. 程序 DDAline 中的取整函数和浮点运算仍然十分

耗时;改进措施:

将增量 k、 1/k 分解成整数和小数部分,使所有计算都改进成整数 DDA 算法的性能;

Page 8: 第三章 基 本 图 形 的 生 成

第 8 页

3.1.2 中点画线法• 采用增量思想的 DDA 算法,每计算一个象素,只需计算一个加法,是否最优?

• 如非最优,如何改进?

• 目标:进一步将一个加法改为一个整数加法。

• 新思路- > DDA 算法采用两点式,可否采用其他的直线表示方式?

Page 9: 第三章 基 本 图 形 的 生 成

第 9 页

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为下一点。

P=( xp, yp)

Q

P2

P1

Page 10: 第三章 基 本 图 形 的 生 成

第 10 页

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 为下一个象素;

Page 11: 第三章 基 本 图 形 的 生 成

第 11 页

3.1.2 中点画线法1. 这样做,每一个像素的计算量是 4个加法,两个乘

法。2. 如果也采用增量算法呢?3. d 是 xp, yp的线性函数,因此可采用增量计算,提

高运算效率。

Page 12: 第三章 基 本 图 形 的 生 成

第 12 页

3.1.2 中点画线法

• 若当前象素处于 d0 情况,则取正右方象素 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

Page 13: 第三章 基 本 图 形 的 生 成

第 13 页

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, 我们有如下算法 。

Page 14: 第三章 基 本 图 形 的 生 成

第 14 页

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 */

Page 15: 第三章 基 本 图 形 的 生 成

第 15 页

3.1.2 中点画线法例:用中点画线法

i xi yi d

1 0 0 1

2 1 0 -3

3 2 1 3

4 3 1 -1

5 4 2 50 1 2 3 4 5

3

2

1

)2,5()0,0( 10 PP 5,2 0110 xxbyya

,6)(2,42,12 210 badadbad

Page 16: 第三章 基 本 图 形 的 生 成

第 16 页

3.1.3 Bresenham 算法

• 基本思想– DDA 算法采用点斜式,中点法采用隐式表示。

– 中点法可以有整数算法。

– 其他表示可以推出整数算法吗?

Page 17: 第三章 基 本 图 形 的 生 成

第 17 页

3.1.3 Bresenham 算法

Xk Xk+1 Xk+2 Xk+3

Yk+3

Yk+2

Yk+1

Yk

Xk Xk+1 Xk+2 Xk+3

Yk+1

Y

Yk

d2

d1

813.............122)1(2

713.....)1(1)1(

613..........)1(

513..........)1(

21

2

1

byxmdd

bxmyyyd

ybxmyyd

bxmy

kk

kkk

kkk

k

Page 18: 第三章 基 本 图 形 的 生 成

第 18 页

3.1.3 Bresenham 算法

1413..................................................2

1313...........)..........(22

1213)...(2).(2

1113..........................2.2

1013...........2.2)(

0

11

111

111

21

xyp

yyxypp

yyxxxypp

cyxxyp

cyxxyddxp

kkkk

kkkkkk

kkk

kkk

可见 ,如果 pk<0, 即 d1<d2,yk+1=yk, 否则 yk+1=yk+1

决策参数 :

Page 19: 第三章 基 本 图 形 的 生 成

第 19 页

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) k pk (xk+1,yk+1)

0 6 (21,11) 5 6 (26,15)

1 2 (22,12) 6 2 (27,16)

2 -2 (23,12) 7 -2 (28,16)

3 14 (24,13) 8 14 (29,17)

4 10 (25,14) 9 10 (30,18)

Page 20: 第三章 基 本 图 形 的 生 成

第 20 页

3.2 圆弧扫描转换算法

圆弧的扫描转换圆弧的扫描转换确定最佳逼近于该圆弧的一组象素确定最佳逼近于该圆弧的一组象素按扫描线顺序,对这些象素进行写操作按扫描线顺序,对这些象素进行写操作四个常用算法

中点画圆法中点画圆法BresenhamBresenham 画圆算法画圆算法生成圆弧的正负法生成圆弧的正负法圆的内接正多边形逼近法圆的内接正多边形逼近法

Page 21: 第三章 基 本 图 形 的 生 成

第 21 页

下面仅以圆心在原点、半径 R 为整数的圆为例,讨论圆的生成算法。

假设圆的方程为: X

2

+ Y2

= R2

圆弧扫描算法

Page 22: 第三章 基 本 图 形 的 生 成

第 22 页

3.2 圆弧扫描算法

X2 + Y

2 = R

2

Y = Sqrt(R2 - X2)在一定范围内,每给定一X值,可得一 Y值。

当 X取整数时, Y须取整。缺点:浮点运算,开方,取整,不均匀。

y

x

Page 23: 第三章 基 本 图 形 的 生 成

第 23 页

中点画圆法

利用圆的对称性,只须讨论 1/8 圆。第二个 8 分圆

P 为当前点亮象素,那么,下一个点亮的象素可能是 P1 ( Xp+1 , Yp )或 P2 ( Xp +1 , Yp -1) 。

M

P1

P2

P ( Xp , Yp )

Page 24: 第三章 基 本 图 形 的 生 成

第 24 页

中点画圆法

构造函数: F ( X , Y ) =X2 + Y

2 - R

2 ;则 F ( X , Y ) = 0 ( X , Y )在圆上; F ( X , Y ) < 0 ( X , Y )在圆内; F ( X , Y ) > 0 ( X , Y )在圆外。设 M 为 P1 、 P2 间的中点, M=(Xp+1,Yp-0.5)

M

P1

P2

Page 25: 第三章 基 本 图 形 的 生 成

第 25 页

中点画圆法

有如下结论: F ( M ) < 0 ->M 在圆内 -> 取 P

1

F ( M ) >= 0 ->M 在圆外 -> 取 P2

为此,可采用如下判别式:

M

P1

P2

Page 26: 第三章 基 本 图 形 的 生 成

第 26 页

中点画圆法

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.

M

P1

P2

Page 27: 第三章 基 本 图 形 的 生 成

第 27 页

中点画圆法

若 d>=0, 则 P2 为下一个象素,那么再下一个象素的判别式为:

d1 = F(xp + 2, yp - 1.5)

= (xp + 2)2 + (yp - 1.5)

2 - R

2

= d + ( 2xp + 3 ) + ( -2 yp + 2 )

即 d 的增量为 2 (xp - yp) +5. d 的初值 : d0 = F(1, R-0.5)

= 1 + (R-0.5)2 - R

2

= 1.25 - R

M

P1

P2

Page 28: 第三章 基 本 图 形 的 生 成

第 28 页

中点画圆法

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--; } } }

Page 29: 第三章 基 本 图 形 的 生 成

第 29 页

中点画圆法

• 为了进一步提高算法的效率,可以将上面的算法中的浮点数改写成整数,将乘法运算改成加法运算,即仅用整数实现中点画圆法。

• 使用 e=d-0.25 代替 d• e0=1-R

Page 30: 第三章 基 本 图 形 的 生 成

第 30 页

Bresenham 画圆算法 设圆的半径为r。考虑圆心在(0, 0),并从x=0、 y=r开始的顺时针方向的1/8圆周的生成过程。在这种情况下,x每步增加1,从x=0开始,到x=y结束。即有: xi+1=xi

+1 相应的yi+1则在两种可能中选择:

yi+1= yi 或者 yi+1= yi-1 选择的原则是:考察精确值y是靠近yi还是靠近yi+1 。

1d

2d

xi xi+1 x

yi

y

yi-12

i2

i22

i2

2

2i

22i

22i1

2i

22

)1y()1x(r)1y(yd

)1x(ryyyd

)1x(ry

Page 31: 第三章 基 本 图 形 的 生 成

第 31 页

Bresenham 画圆算法选择的原则是:考察精确值y是靠近yi还是靠近yi+1 。

1d

2d

xi xi+1 x

yi

y

yi-1

2r3p

)yy(2)yy(264xpp

2r)1y(y)1x(2p

,ddp

)1y()1x(r)1y(yd

)1x(ryyyd

)1x(ry

1

i1i2

i2

1iii1i

22i

2i

2ii

21i

2i

2i

22i

22

2i

22i

22i1

2i

22

则有令

其中, pi 为决策参数。如果 pi<0 则 yi+1= yi 或者 yi+1= y

i-1

Page 32: 第三章 基 本 图 形 的 生 成

第 32 页

Bresenham 画圆算法圆的 Bresenham 算法的程序实现如下 :

circle(xc,yc,radius,c)

{ int x=0,y,p; y=radius;p=3-2*radius;

while(x<y)

{

plot_circle(xc,yc,x,y,c);

If(p<0) p=p+4*x+6;

else

{ p=p+4*(x-y)+10;

y-=1; }

x+=1;

}

if(x=y)

plot_circle(xc,yc,x,y,c);

}

plot_circle(xc,yc,x,y,c)

{int xc,yc,x,y,c;

set_pixel(xc+x,yc+y,c);

set_pixel(xc-x,yc+y,c);

set_pixel(xc+x,yc-y,c);

set_pixel(xc+x,yc+y,c);

set_pixel(xc+y,yc+x,c);

set_pixel(xc-y,yc+x,c);

set_pixel(xc+y,yc-xy,c);

set_pixel(xc-y,yc-x,c);}

结论: Bresenham 算法的主要计算量在于决策参数的计算,而决策函数只做 4 的乘法和加法;因此, Bresenham 算法运行速度很快,而且适宜在硬件上实施。

Page 33: 第三章 基 本 图 形 的 生 成

第 33 页

3.3 多边形的扫描转换与区域填充

•多边形有两种重要的表示方法:顶点表示和点阵表示。

•区域填充算法可分为两大类 :扫描转换填充算法、种子填充算法。

Page 34: 第三章 基 本 图 形 的 生 成

第 34 页

3.3.1.1 扫描线算法1、简单的射线法① 多边形内的区域填充的最本质的问题是要找出位于区域内的全部像素,即包容性检测问题。

② 基本思路:射线法是由被测点向某方向作射线,计算此射线与多边形所有边的交点个数。若交点个数为奇数,则被测点在多边形之内,否则,在多边形之外。

Page 35: 第三章 基 本 图 形 的 生 成

第 35 页

3.3.1.1 扫描线算法

1.奇异点的处理

左闭右开(上闭下开):射线左边的边与射线相交时交点有效,应计数;右边的无效,不计数。

2.水平边的处理

当射线与水平边重合时,不求交。

3.思路简单,速度极慢

Page 36: 第三章 基 本 图 形 的 生 成

第 36 页

3.3.1 多边形的扫描转换

•3.3.1.1 扫描线算法–基本思想:•按扫描线顺序,计算扫描线与多边形的相交区间,用要求的颜色显示这些区间的象素。该算法利用了相邻扫描线之间的相关性。

Page 37: 第三章 基 本 图 形 的 生 成

第 37 页

3.3.1 多边形的扫描转换对于一条扫描线填充过程可分为四个步骤:

•求 交求 交 求出每一条扫描线与多边形所有边的交点,建立 (x,y)交点表,若为水平边则跳过;

•排 序排 序 按 x及 y 增加(或减少 ) 的顺序,对这些交点进行排序;

•配 对配 对 对排序后的交点进行两两配对,定义填充区域;

•填 色填 色 将每对交点之间的所有像素置成所需要的颜色;

关键是交点的配对,但配对有可能出错,因为存在奇异点问题。

Page 38: 第三章 基 本 图 形 的 生 成

第 38 页

3.3.1.1 扫描线算法

0 1

1

2

2 3

3

4

4 5

5

6

6 7

7

8

8 9 10 11

P2(5,1)

E

P3(11,3)

D

P4(11,8)

GF

CBP5(5,5)

P6(2,7)

A

P1(2,2)

问题一:奇 异 点问题一:奇 异 点

第一类第一类: P2 、 P4 、 P5 、 P6 ;必须计 2次交点;相邻两边不时单调向上或向下;

第二类第二类: P1 、 P3 ;只需计 1次交点;相邻两边单调向上或向下;

Page 39: 第三章 基 本 图 形 的 生 成

第 39 页

3.3.1 多边形的扫描转换奇 异 点 的 解 决 办 法奇 异 点 的 解 决 办 法方法一:方法一:• 第一类第一类: P2 、 P4 、 P5 、 P6 ;相邻两边不时单调向上

或向下;计 2 次交点;• 第二类第二类: P1 、 P3 ;相邻两边单调向上或向下;计 1 次

交点;方法二:方法二:• 第一类第一类: P2 、 P4 、 P5 、 P6 ;必须计 2 次交点;相邻

两边不时单调向上或向下;不做处理;• 第二类第二类: P1 、 P3 ;只需计 1 次交点;相邻两边单调向

上或向下;将其中一条边的将其中一条边的 yy 值抬高一个像素。值抬高一个像素。

Page 40: 第三章 基 本 图 形 的 生 成

第 40 页

3.3.1 多边形的扫描转换

问题二:增量计算的应用问题二:增量计算的应用 xxi+1i+1 = x = xii+ 1/m + 1/m (( mm 为边的斜率)为边的斜率)

yi+1

yi

∆y

xi xi+1

Page 41: 第三章 基 本 图 形 的 生 成

第 41 页

3.3.1 多边形的扫描转换

问题三:如何减少交点计算的工作量问题三:如何减少交点计算的工作量

解决办法:1. 利用相邻扫描线之间的相关性,构造 AET

( Active Eges Table )表,表中只记录与当前扫描线相交的活动边,而且这些边按照与扫描线 y 交点的 x 坐标排序,以便交点匹配和填充。

2. 先构造便表( ET ),再构造 AET 。

Page 42: 第三章 基 本 图 形 的 生 成

第 42 页

3.3.1 多边形的扫描转换边表(边表( NETNET):):

1. NET 由 bucket构成, bucket 的数目与扫描线线数相同;

2. 存放在该扫描线第一次出现的边。若某边的较低端点为 ymin,则该边就放在扫描线 ymin的边表中;

3. 结点包括每条边两端点中最大的 y坐标值( ymax), y值较小的那个端点的 x坐标值( xmin)以及该边的斜率的倒数 (1/m),如下图所示。

1/m ymin ymax 指针

Page 43: 第三章 基 本 图 形 的 生 成

第 43 页

3.3.1 多边形的扫描转换

7

6 P4P5 P5P6 5

4

3

2

1

0 P1P2 P2P3

8

5 - 3 2 5 3 3

2 0 7

11 0 8

5 2 8 5 - 1. 5 7

P6P1

P3P4

0 1

1

2

2 3

3

4

4 5

5

6

6 7

7

8

8 9 10 11

P2(5,1)

E

P3(11,3)

D

P4(11,8)

GF

CBP5(5,5)

P6(2,7)

A

P1(2,2)

Page 44: 第三章 基 本 图 形 的 生 成

第 44 页

3.3.1 多边形的扫描转换

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

2 0 7 3. 5 - 1. 5 7

P6P1 P5P6

A B 7 2 8 11 0 8

P4P5 P3P4

C D△ x ymax △ x ymax △ x ymax △ x ymax

Page 45: 第三章 基 本 图 形 的 生 成

第 45 页

3.3.1 多边形的扫描转换多边形的扫描线算法如下:多边形的扫描线算法如下:1. 将 y值设置为 ET中所列的最小 y值,也即第一个非空的 buc

ket;2. 将 AET 初始化,使其为空;3. 重复做以上各步,直至 AET 和 ET 都为空为止。

① 把 ET中 y的信息与 AET 合并,同时保准 AET中按 x值实现排序;

② 对于扫描线 y,在一对交点之间填充所需要的像素颜色;③ 从 AET中删除 y>ymax的项;……?④ 对于仍留在 AET中的每一项,用 x+1/m 代替 x;……?⑤ 检查并保证 AET中各项按 x值的排序;⑥ 使 y增 1,成为下一条扫描线的坐标。

Page 46: 第三章 基 本 图 形 的 生 成

第 46 页

876543210

5 2 8 . 5 -1.5 7 ∧

11 0 8 ∧

2 0 7 ∧

5 -3 2 . 5 3 3 ∧

P4P5 P5P6

P3P4

P6P1

P1P2 P2P3

5 -3 2 . 5 3 3 ∧P1P2 P2P3

y=1y=2

2 0 7 . 11 0 8 ∧P6P1 P3P4

y=3

5 2 8 .P4P5

11 0 8 ∧P3P4

5 -1.5 7P5P6

2 0 7 .P6P1

y=5

7 2 8 .P4P5

11 0 8 ∧P3P4

3.5 -1.5 7P5P6

2 0 7 .P6P1

y=6

9 2 8 .P4P5

11 0 8 ∧P3P4

y=7

2 0 7 . 11 0 8 ∧P6P1 P3P4

y=4

y

x0 1 2 3 4 5 6 7 8 9 101112345678 P6

P4

P1

P5

P2

P3

2 0 7 . 8 3 3 ∧P6P1 P2P3

Page 47: 第三章 基 本 图 形 的 生 成

第 47 页

3.3.1 多边形的扫描转换

• 优点:1.对每个像素只访问一次2.与设备无关

• 缺点:1.数据结构复杂2.只适合软件实现

Page 48: 第三章 基 本 图 形 的 生 成

第 48 页

3.3.1.2 边界标志算法

• 基本思想:– 帧缓冲器中对多边形的每条边进行直线扫描转换,

亦即对多边形边界所经过的象素打上标志。– 然后再采用和扫描线算法类似的方法将位于多边

形内的各个区段着上所需颜色。– 使用一个布尔量 inside 来指示当前点是否在多边

形内的状态。

Page 49: 第三章 基 本 图 形 的 生 成

第 49 页

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

}

Page 50: 第三章 基 本 图 形 的 生 成

第 50 页

3.3.1.2 边界标志算法

• 用软件实现时,扫描线算法与边界标志算法的执行速度几乎相同,

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

Page 51: 第三章 基 本 图 形 的 生 成

第 51 页

3.3.2 区域填充算法

• 区域指已经表示成点阵形式的填充图形,它是象素的集合。

• 区域可采用内点表示(内定义区域 interior-define

d ) 和边界表示(边界定义区域 boundary-defined )。• 区域可分为 4 向连通区域和 8 向连通区域。• 区域填充指先将区域的一点赋予指定的颜色,然

后将该颜色扩展到整个区域的过程。区域填充算法要求区域是连通的

Page 52: 第三章 基 本 图 形 的 生 成

第 52 页

3.3.2 区域填充算法

• 4 向连通区域和 8 向连通区域

四个方向运动 八个方向运动 四连通区域 八连通区域

表 示 内 点 表 示 边 界 点

Page 53: 第三章 基 本 图 形 的 生 成

第 53 页

3.3.2.1 区域填充的递归算法

简单的种子填充算法1、漫水法( flood-fill algorithm)

基本方法:首先在区域内侧是一点( x, y)的像素值,看其是否具有原始给定的值,也即决定该点是否在区域内未被填充过。如果是,则改变其颜色或亮度值。然后再在其四个方向或八个方向上扩展,继续测试,通过递归调用,实现四连通或八连通的区域填充。

适用于内定义区域。

Page 54: 第三章 基 本 图 形 的 生 成

第 54 页

3.3.2.1 区域填充的递归算法

简单的种子填充算法2、边界填充算法

基本方法:测试( x, y)的像素是否在区域内又未被访问过,①与边界值比较,以检测此像素是否为该区域的一部分;②与新值比较,以决定该像素是否已被访问过。测试的前提是:在初始状态,区域内没有一个像素已设置为新值。但,允许新值等于边界值。适用于内定义区域。

Page 55: 第三章 基 本 图 形 的 生 成

第 55 页

3.3.2.1 区域填充的递归算法

2 、边界填充算法 基本流程1. 种子像素压入堆栈;2. 当堆栈非空时,

• 从堆栈中推出一个像素,并将该像素置成所要的值;

• 对于每个与当前像素邻接的四连通或八连通像素,进行上述两部分内容的测试;

• 若所测试的像素在区域内又未被填充过,则将该像素压入堆栈。

Page 56: 第三章 基 本 图 形 的 生 成

第 56 页

3.3.2.1 区域填充的递归算法

2 、边界填充算法 算法的缺点1. 深度递归,栈有可能溢出;2. 使栈极小化的一种算法是:在任意不间断

的扫描线区段中,只取一个种子像素,称为扫描线种子填充算法。

Page 57: 第三章 基 本 图 形 的 生 成

第 57 页

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);

}

}

Page 58: 第三章 基 本 图 形 的 生 成

第 58 页

边界表示的 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.1 区域填充的递归算法