VC++多边形的填充.docx

上传人:b****4 文档编号:3143463 上传时间:2022-11-18 格式:DOCX 页数:14 大小:106.09KB
下载 相关 举报
VC++多边形的填充.docx_第1页
第1页 / 共14页
VC++多边形的填充.docx_第2页
第2页 / 共14页
VC++多边形的填充.docx_第3页
第3页 / 共14页
VC++多边形的填充.docx_第4页
第4页 / 共14页
VC++多边形的填充.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

VC++多边形的填充.docx

《VC++多边形的填充.docx》由会员分享,可在线阅读,更多相关《VC++多边形的填充.docx(14页珍藏版)》请在冰豆网上搜索。

VC++多边形的填充.docx

VC++多边形的填充

实验二有效边表填充算法

1.实验目的:

设计有效边表结点和边表结点数据结构

设计有效边表填充算法

编程实现有效边表填充算法

2.实验描述:

下图1所示多边形覆盖了12条扫描线,共有7个顶点和7条边。

7个顶点分别为:

P0(7,8),P1(3,12),P2(1,7),P3(3,1),P4(6,5),P5(8,1),P6(12,9)。

在1024×768的显示分辩率下,将多边形顶点放大为P0(500,400),P1(350,600),P2(250,350),P3(350,50),P4(500,250),P5(600,50),P6(800,450)。

请使用有效边表算法填充该多边形。

图1示例多边形

图2屏幕显示多边形

3.算法设计:

1.根据多边形顶点坐标值,计算扫描线的最大值ScanMax和最小值ScanMin。

2.用多边形覆盖的扫描线动态建立桶结点。

3.循环多边形的所有顶点,根据边的终点y值比起点y值高或边的终点y值比起点y值低两种情况(边的终点y值和起点y值相等的情况属于扫描线,不予考虑),计算每条边的yMin。

在桶中寻找与该yMin相应的桶结点,计算该边表的x|yMin、yMax、k(代表斜率倒数1/k),并依次连接该边表结点到桶结点。

4.对每个桶结点连接的边表,根据x|yMin值的大小进行排序,若x|yMin相等,则按照k由小到大排序。

5.对每个桶结点进行循环,将桶内每个结点的边表合并为有效边表,并进行有效边表循环。

6.从有效边表中取出相邻两条边的交点对进行填充。

填充时设置一个逻辑变量In(初始值为假),每访问一个结点,把In值取反一次,若In为真,则把从当前结点的x值开始到下一结点的x-1值结束的区间用指定颜色填充。

(左闭右开)

7.循环下一桶结点,按照xi+1=xi+k(k的值为1/k)修改有效边表,同时合并桶结点内的新边表,形成新的有效边表。

8.如果桶结点的扫描线值大于等于有效边表中某个结点的yMax值,则放弃该有效边表。

9.当桶结点不为空则转⑸,否则删除桶结点和边结点的头结点,算法结束。

4.源程序:

1)//AET.h和AET..cpp

classAET

{

}

2)//Bucket.h和Bucket.cpp

classBucket

{

}

3)//TestView.h

#include"AET.h"//包含有效边表类

#include"Bucket.h"//包含桶类

#defineNumber7//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中

classCTestView:

publicCView

{

public:

voidPolygonFill();//上闭下开填充多边形

voidCreatBucket();//建立桶结点桶

voidEt();//构造边表

voidAddEdge(AET*);//将边插入AET表

voidEdgeOrder();//对AET表进行排序

protected:

COLORREFGetColor;//调色板

CPointPoint[7];//定义多边形

Bucket*HeadB,*CurrentB;//桶的头结点和当前结点

AETE[Number],*HeadE,*CurrentE,*T1,*T2;//有效边表的结点

4)//TestView.cpp

CTestView:

:

CTestView()

{

//设置多边形的7个顶点

Point[0]=CPoint(550,400);//P0

Point[1]=CPoint(350,600);//P1

Point[2]=CPoint(250,350);//P2

Point[3]=CPoint(350,50);//P3

Point[4]=CPoint(500,250);//P4

Point[5]=CPoint(600,50);//P5

Point[6]=CPoint(800,450);//P6

}

voidCTestView:

:

OnDraw(CDC*pDC)

{

CTestDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

pDC->Polygon(Point,7);//绘制多边形

//输出多边形的顶点编号

pDC->TextOut(550,410,"P0");

pDC->TextOut(350,600,"P1");

pDC->TextOut(230,340,"P2");

pDC->TextOut(350,30,"P3");

pDC->TextOut(490,220,"P4");

pDC->TextOut(600,30,"P5");

pDC->TextOut(805,450,"P6");

}

voidCTestView:

:

OnMenuAET()//菜单函数

{

AfxGetMainWnd()->SetWindowText("多边形有效边表填充算法");//显示标题

CColorDialogccd(GetColor);

if(ccd.DoModal()==IDOK)//调用调色板选取前景色

{

GetColor=ccd.GetColor();

}

RedrawWindow();//刷新屏幕

CreatBucket();//初始化桶

Et();//建立边表

PolygonFill();//多边形填充

}

voidCTestView:

:

CreatBucket()//初始化桶

{

intScanMin,ScanMax;//确定扫描线的最小值和最大值

ScanMax=ScanMin=Point[0].y;

for(inti=1;i

{

if(Point[i].y

{

ScanMin=Point[i].y;//扫描线的最小值

}

if(Point[i].y>ScanMax)

{

ScanMax=Point[i].y;//扫描线的最大值

}

}

for(i=ScanMin;i<=ScanMax;i++)//建立桶结点

{

if(ScanMin==i)//桶头结点,以所有点的最小的Ymin值作为桶表的头结点

{

HeadB=newBucket;//建立桶的头结点

CurrentB=HeadB;//CurrentB为Bucket当前结点指针

CurrentB->ScanLine=ScanMin;

CurrentB->p=NULL;//没有连接边链表

CurrentB->next=NULL;

}

else//建立桶的其它结点

{

CurrentB->next=newBucket;//新建一个桶结点

CurrentB=CurrentB->next;//使CurrentB指向新建的桶结点

CurrentB->ScanLine=i;

CurrentB->p=NULL;//没有连接边链表

CurrentB->next=NULL;

}

}

//桶表的顺序是从小到大

}

//桶表是每一个扫描线对应一个结点,每一个桶表结点连接一个边链表

voidCTestView:

:

Et()//构造边表

{

for(inti=0;i

{

CurrentB=HeadB;//从桶链表的头结点开始循环

intj=i+1;//边的第二个顶点,Point[i]和Point[j]构成边

if(j==Number)j=0;//保证多边形的闭合

if(Point[j].y>Point[i].y)//终点比起点高

{

while(CurrentB->ScanLine!

=Point[i].y)//在桶内寻找该边的yMin

{

CurrentB=CurrentB->next;//移到下一个桶结点

}

E[i].x=Point[i].x;//计算AET表的值

E[i].yMax=Point[j].y;

E[i].k=double((Point[j].x-Point[i].x))/(Point[j].y-Point[i].y);//代表1/k

E[i].next=NULL;

CurrentE=CurrentB->p;//获得桶上链接边表的地址

if(CurrentB->p==NULL)//当前桶结点上没有链接边结点

{

CurrentE=&E[i];//赋边的起始地址

CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中

}

else

{

//什么情况下会将不为空?

当有两个点的纵坐标是一样的时候会产生这种情况,所以之后要对桶表对应的边表中的每个结点进行按X的排序

while(CurrentE->next!

=NULL)//如果当前边已连有边结点

{

CurrentE=CurrentE->next;//移动指针到当前边的最后一个边结点

}

CurrentE->next=&E[i];//把当前边接上去

}

}

if(Point[j].y

{

while(CurrentB->ScanLine!

=Point[j].y)

{

CurrentB=CurrentB->next;

}

E[i].x=Point[j].x;

E[i].yMax=Point[i].y;

E[i].k=double((Point[i].x-Point[j].x))/(Point[i].y-Point[j].y);

E[i].next=NULL;

CurrentE=CurrentB->p;

if(CurrentE==NULL)

{

CurrentE=&E[i];

CurrentB->p=CurrentE;

}

else

{

while(CurrentE->next!

=NULL)

{

CurrentE=CurrentE->next;

}

CurrentE->next=&E[i];

}

}

}

CurrentB=NULL;

CurrentE=NULL;

}

voidCTestView:

:

AddEdge(AET*NewEdge)//插入临时边表函数

{

T1=HeadE;

if(T1==NULL)//边表为空,将边表置为TempEdge

{

T1=NewEdge;

HeadE=T1;

}

else

{

while(T1->next!

=NULL)//边表不为空,将TempEdge连在该边之后

{

T1=T1->next;

}

T1->next=NewEdge;

}

}

voidCTestView:

:

EdgeOrder()//对边表进行排序函数

{

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

当前位置:首页 > 成人教育 > 远程网络教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1