图形学教案ch403pptConvertorWord文件下载.docx

上传人:b****1 文档编号:4586202 上传时间:2023-05-03 格式:DOCX 页数:16 大小:136.22KB
下载 相关 举报
图形学教案ch403pptConvertorWord文件下载.docx_第1页
第1页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第2页
第2页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第3页
第3页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第4页
第4页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第5页
第5页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第6页
第6页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第7页
第7页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第8页
第8页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第9页
第9页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第10页
第10页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第11页
第11页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第12页
第12页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第13页
第13页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第14页
第14页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第15页
第15页 / 共16页
图形学教案ch403pptConvertorWord文件下载.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

图形学教案ch403pptConvertorWord文件下载.docx

《图形学教案ch403pptConvertorWord文件下载.docx》由会员分享,可在线阅读,更多相关《图形学教案ch403pptConvertorWord文件下载.docx(16页珍藏版)》请在冰点文库上搜索。

图形学教案ch403pptConvertorWord文件下载.docx

下面来求d2的初值。

显然,d2的初值出现在由上半椭圆弧转入下半椭圆弧的时候。

下半椭圆弧的第一个象素就是上半椭圆弧的最后一个象素。

设在上半椭圆弧的最后一个象素是(xp,yp),那么d2的初值为

midpointellipse(a,b,c)

inta,b,c;

{

intx,y;

floatd1,d2;

x=0;

y=b;

d1=b*b+a*a*(-b+0.25);

putpixel(x,y,c);

while(b*b*(x+1)<

a*a*(y-0.5))

if(d1<

0)

{d1+=b*b*(2*x+3);

x++;

}

else{

d1+=b*b*(2*x+3)+a*a*(-2*y+2);

y--;

putpixel(x,y,c);

}/*上半椭圆结束*/

d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;

while(y>

if(d2<

{

d1+=b*b*(2*x+2)+a*a*(-2*y+3);

d2+=a*a*(-2*y+3);

y--;

}

有对称性,不难得出中心在原点的整个椭圆的算法:

putpixel(x,-y,c);

putpixel(-x,y,c);

putpixel(-x,-y,c);

由平移变换,立即得到中心在任意位置(xr,yr)的椭圆的算法:

midpointellipse(xr,yr,a,b,c)

intxr,yr,a,b,c;

putpixel(x+xr,y+yr,c);

putpixel(x+xr,-y+yr,c);

putpixel(-x+xr,y+yr,c);

putpixel(-x+xr,-y+yr,c);

由平移变换,立即得到中心在任意位置(xr,yr)的椭圆的算法。

d2+=b*b*(2*x+2)+a*a*(-2*y+3);

主函数如下:

#include<

graphics.h>

math.h>

main()

intgdriver=DETECT,gmode;

initgraph(&

gdriver,&

gmode,””);

midpointellipse(150,150,50,40,15);

4.4区域填充

区域填充的方法主要有:

(多边形域的)扫描线填充算法、(多边形域的)边填充算法、区域的递归填充算法(简单的种子填充算法)、区域的扫描线填充算法(改进的种子填充算法)。

4.4.1区域的递归填充算法(简单的种子填充算法)

和递归填充算法相关的两种区域的表示:

内点表示:

区域内的所有像素着同一颜色,而区域外的所有像素具有另外的颜色;

边界表示:

区域边界上的所有像素点具有特定的颜色(可以是填充色),在区域内的所有像素均不能具有这一特定色,而且边界外的像素不能具有与边界相同的颜色。

边界表示的区域的递归填充算法的思想

在给出区域光栅化后的边界位置及边界颜色代码boundary_color后,现在要从多边形内部某一象素(x,y)开始按一定的填充方法对多边形进行填充。

该象素称为种子点。

要求填充的颜色为fill_color。

内点表示的区域的递归填充算法的思想

在给出区域光栅化后的内点的颜色代码oldcolor后,现在要从多边形内部某一象素(x,y)开始按某一种填充方法对多边形进行填充。

要求填充的颜色为newcolor。

两种填充方式

四邻法:

已知象素是区域内的一点,据此向上、下、左、右4个方向测试、填色、扩散。

四邻法

八邻法

八邻法:

已知象素是区域内的一点,据此周围8个方向测试、填色、扩散。

区域的递归填充算法要求区域是连通的,因为只有在连通区域中,才可能将种子点的颜色扩展到区域内的其它点。

区域按连通情况又可分为四连通区域和八连通区域。

四连通区域指的是从区域上一点出发,可通过四个方向,即上、下、左、右移动的组合,在不越出区域的前提下,到达区域内的任意像素。

八连通区域指的是从区域内每一像素出发,可通过八个方向,即上、下、左、右、左上、右上、左下、右下移动的组合,在不越出区域的前提下,到达区域内的任意像素。

四连通区域八连通区域

四邻法的缺点:

当用四邻法填充一个八连通区域时,由于它无法填充对角线上的连通象素,因而可能造成某些区域没有被填上。

但是,如果希望两个区域填不同的颜色,用四邻法就比较合适。

八邻法的缺点:

当用八邻法填充一个四连通区域时,由于它填充是按8个方向进行的,因而可能造成从对角线方向越界,造成意想不到的后果。

一般来说,四邻法比八邻法用得更普遍。

因为,填不满比涂出界更容易补救。

边界表示的4连通区域的递归填充算法:

voidseed_filling(x,y,fill_color,boundary_color)

intx,y,fill_color,boundary_color;

intc;

c=getpixel(x,y);

if(c!

=boundary_color&

&

c!

=fill_color)

putpixel(x,y,fill_color);

seed_filling(x+1,y,fill_color,boundary_color);

seed_filling(x-1,y,fill_color,boundary_color);

seed_filling(x,y+1,fill_color,boundary_color);

seed_filling(x,y-1,fill_color,boundary_color);

内点表示的4连通区域的递归填充算法:

voidFloodFill4(intx,inty,intoldcolor,intnewcolor)

{if(getpixel(x,y)==oldcolor)//属于区域内点oldcolor

{putpixel(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.4.2多边形的扫描线填充算法

简单的种子填充算法中含有4条递归语句,效率太低。

并且当区域过大时会造成堆栈溢出。

解决上述问题的办法是引入扫描线算法,得到了各种改进的算法,即区域的扫描线填充算法。

包括多边形区域的扫描线填充算法、边填充算法、栅栏填充算法、边标志算法和扫描线种子填充算法等。

基本思想:

按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作。

对于一条扫描线填充过程可以分为四个步骤:

●求交(点)

●(交点)排序

●交点配对

●(区间)填色

情况1分析扫描线2、7与多边形的相交情况。

通过以上的分析,我们作出第一次修正。

当扫描线与多边形交于上顶点时,交点计数为0。

当扫描线通过多边形的下顶点时,交点计数为2。

当扫描线通过多边形的左右顶点时,交点计数为1。

情况2、上述修正还不能保证填充的正确,因为对边界上象素的取舍不当会出现所谓的“过填”问题。

“过填”造成边长为2个单位的正方形变为边长为3个单位。

避免出现上述“过填”现象,必须要对多边形的边界象素进行取舍。

1)对扫描线与多边形的相交区间取“左闭右开”。

2)对扫描线与多边形的上下顶点相交时,交点的取舍方法为“下闭上开”,即丢弃上方水平边或上顶点。

多边形扫描线填充算法的思想:

将多边形的顶点进行上述处理之后,用(水平)扫描线由下到上扫描多边形,求出每条扫描线与多边形的交点,将这些交点按x坐标进行排序,将排序后的交点成对取出,按照

左闭右开的方式以给定的颜色画线。

多边形被扫描后,填色也就完成了。

如何去求扫描线与多边形的交点?

活性边表法

把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表(或数组)中,称为活性边表(AEL)。

结点内容

x:

当前扫描线与边的交点坐标

△x:

从当前扫描线到下一条扫描线间x的增量,为1/k,其中k为斜率。

ymax:

该边所交的最高扫描线号ymax

扫描线6的活性边表。

假定当前扫描线与多边形某一条边的交点的x坐标为x,则下一条扫描线与该边的交点不要重计算,只要加一个增量△x。

设该边的直线方程为:

ax+by+c=0;

若y=yi,x=xi;

则当y=yi+1时,

其中

=1/k为常数

当求完当前扫描线与多边形的交点后,应将与下一条扫描线不相交的边从活性边表中删除。

对于那些与下一条扫描线有交点的新边,应及时插入到活性边表中(按x递增排序)。

为了能快速找出与当前扫描线第一次有交点的新边,我们为每一条扫描线建立一个新边表(NEL)

新边表的建立:

先按低端点的y坐标值对所有的边进行分组,若某边的低端点y值为ymin,则该边就放在扫描线y=ymin所对应的表中;

然后用排序方法,按低端点的x坐标值递增的顺序将同一组中的边排列成行。

NEL中的基本元素、结点的构成和AEL相同,每个边结点由以下四个域组成:

其中,各符号的含义为:

⏹ymax:

边的上端点的y坐标

⏹x:

在NEL中表示边的下端点的x坐标,在AEL中表示边与扫描线的交点的x坐标

⏹1/k:

边的斜率的倒数

⏹next:

指向下一条边的指针

上图所示各条扫描线的新边表NEL

当建立了边表NEL后,扫描线多边形填充算法可按如下步骤进行:

(1)初始化AEL,使之为空,取扫描线纵坐标y的初始值为多边形所有顶点中最小的y值。

(2)将NEL中与当前y有关的结点加入至AEL,同时保存AEL中按x值从小到大实现的排序序列。

(3)对于AEL中的扫描线y,在一对交点之间填充所需要的像素值。

(4)从AEL中删掉y>

=ymax的结点。

(5)对于留在AEL中的每个结点,执行xi+1=xi+1/k。

(6)对AEL中的各结点按x值从小到大排序。

(7)y=y+1,成为下一条扫描线的坐标。

(8)若AEL非空,转

(2),否则,停止。

基本原理:

对每一条扫描线,依次求与(经过顶点处理的)多边形各边的交点,将该扫描线上交点右边的所有像素求补。

算法虽然简单易行,但对于复杂图形而言,一些像素的颜色值需反复改变多次,且多边形外的像素处理过多,输入、输出的量比有序边表大的多(可用矩形包围盒提高效率)。

4.4.3边填充算法

栅栏填充算法

对于每条扫描线与多边形的交点,将交点与栅栏之间的扫描线上的像素取补,也就是说,若交点位于栅栏左边,则将交点之右、栅栏之左的所有像素取补;

若交点位于栅栏右边,则将栅栏之右、交点之左的所有像素取补。

多边形外的像素处理大大减少,被重复取补的像素数目也有减少,但仍有一些像素被重复取补。

参见教材图4.3.6

边标志算法:

对多边形边界所在像素置一个特殊标志(对多边形的每条边进行直线扫描转换);

对于每条与多边形相交的扫描线,从左至右逐个访问该扫描线上的像素。

使用一个布尔变量inside来指示当前点的状态,若点在多边形内,则inside为真。

若点在多边形外,则inside为假。

inside的初始值为假,每当当前访问像素为被打上标志的点(即边界点)就把inside取反。

对未打标志的点,inside不变。

若inside为真,则把该像素置为多边形要填充的颜色。

对每个像素只访问一次,硬件执行速度快。

voidedgemark_fill(polydef,color)

多边形定义polydef;

intcolor;

{对多边形polydef每条边进行直线扫描转换;

inside=FALSE;

for(每条与多边形polydef相交的扫描线y)

for(扫描线上每个象素x)

{

if(象素x被打上边标志)

inside=!

(inside);

if(inside!

=FALSE)

drawpixel(x,y,color);

elsedrawpixel(x,y,background);

4.4.4扫描线种子填充算法

算法思想:

在任意不间断区间中只取一个种子像素(不间断区间指在一条扫描线上一组相邻元素),填充当前扫描线上的该段区间;

然后确定与这一区段相邻的上下两条扫描线上位于区域内的区段,并依次把它们保存起来,反复进行这个过程,直到所保存的每个区段都填充完毕。

可以填充有孔区域,对于每一个待填充区段,只需入栈一次,因此提高了区域填充的效率。

(1)初始化:

堆栈置空。

将种子点(x,y)入栈。

(2)出栈:

若栈空则结束。

否则取栈顶元素(x,y),以y作为当前扫描线。

(3)填充并确定种子点所在区段:

从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。

分别标记区段的左、右端点坐标为xl和xr。

(4)并确定新的种子点:

在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的象素。

若存在非边界、未填充的象素,则把每一区间的最右象素作为种子点压入堆栈,返回第

(2)步。

上述算法对于每一个待填充区段,只需压栈一次;

因此,扫描线填充算法提高了区域填充的效率。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2