多边形填充
int yMax;
double k;
CP2 ps;
CP2 pe;
CAET *pNext;
};
class CBucket
{
public:
CBucket();
virtual~CBucket();
public:
int ScanLine;
CAET *pET;
CBucket*pNext;
};
class CFillPoly
e)对当前扫描线的有效边表按x值递增的顺序进行排序、配对,以确定填充区间;根据“左闭右开”的原则,对两两配对的填充空间进行像素填充。
f)继续回到步骤b。
1)新建多边形填充类CFillPoly头文件
首先声明二维点类“CP2”、边表类“CAET”和桶表类“CBucket”,用于存储和传递多边形“桶表和边表”数据。多边形填充类中主要包括存放多边形顶点数据、有效边表结点指针和桶表结点指针的成员变量,以及创建桶表、边表、有效边表排序和填充多边形等成员函数。“FillPoly.h”头文件中具体类型声明代码如下:
3)调用设计实现的多边形填充类,对菱形线框进行颜色填充。
三实验步骤
第1步:创建MFC应用程序框架
参照第一章的步骤建立空的MFC应用程序框架。
第2步:设计实现直线绘制类
设计实现多边形填充类
1)有效边表填充算法原理
在多边形填充过程中,常采用:“下闭上开”和“左闭右开”的原则对边界像素进行处理。有效边表填充算法通过维护“桶表和边表”数据,节省了有效数据存储空间,避免了扫描线与多边形所有边求交的运算耗时。
{
for(pCurrentE=pCurrentB->pET;pCurrentE!=NULL;pCurrentE=pCurrentE->pNext)
{
pEdge=new CAET;
pEdge->x=pCurrentE->x;
pEdge->yMax=pCurrentE->yMax;
pEdge->k=pCurrentE->k;
pHeadE=NULL;
}
CFillPoly::~CFillPoly ()
{
if(P!=NULL)
{
delete[]P;
P=NULL;
}
ClearMemory();
}
void CFillPoly::SetPoint(CP2*p,int m)
{
P=new CP2[m];
for(int i=0;i<m;i++)
{
yMax=P[i].y;
}
}
for(int y=yMin;y<=yMax;y++)
{
if(yMin==y)
{
pHeadB=new CBucket;
pCurrentB=pHeadB;
pCurrentB->ScanLine=yMin;
pCurrentB->pET=NULL;
pCurrentB->pNext=NULL;
{
this->x=x;
this->y=y;
}
CAET::CAET()
{}
CAET::~CAET()
{}
CBucket::CBucket()
{}
CBucket::~CBucket ()
{}
CFillPoly::CFillPoly()
{
PNum=0;
P=NULL;
pEdge=NULL;
pHeadB=NULL;
}
}
if(P[i].y!=P[j].y)
{
pCurrentE=pCurrentB->pET;
if(pCurrentE==NULL)
{
pCurrentE=pEdge;
pCurrentB->pET=pCurrentE;
}
else
{
while(pCurrentE->pNext!=NULL)
{
pCurrentE=pCurrentE->pNext;
#pragma once
class CP2
{
public:
CP2 ();
virtual~CP2 ();
CP2 (double,int);
double x;
int y;
COLORREF c;
};
class CAET
{
public:
CAET ();
virtual~CAET();
public:
double x;
}
}
for(pT1=pHeadE;pT1!=NULL;pT1=pT1->pNext)
{
pT1->x=pT1->x+pT1->k;
}
}
}
void CFillPoly::AddET(CAET*pNewEdge)
{
CAET*pCE=pHeadE;
if(pCE==NULL)
{
pHeadE=pNewEdge;
{
public:
CFillPoly ();
virtual~CFillPoly ();
void SetPoint(CP2*p,int);
void CreateBucket();
void CreateEdge();
void AddET(CAET*);
void ETOrder();
void PlaneFill(CDC*);
{
if(FALSE==bInFlag)
{
xb=pT1->x;
bInFlag=TRUE;
}
else
{
xe=pT1->x;
for(double x=xb;x<xe;x++)
{
pDC->SetPixelV(Round(x),pCurrentB->ScanLine,pT1->ps.c);
}
bInFlag=FALSE;
pEdge->ps=P[i];
pEdge->pe=P[j];
pEdge->pNext=NULL;
while(pCurrentB->ScanLine!=P[i].y)
{
pCurrentB=pCurrentB->pNext;
}
}
if(P[j].y<P[i].y)
{
pEdge=new CAET;
pEdge->x=P[j].x;
计算机图形学实验报告
班级:
学号:
姓名:
实验三多边形填充
一 实验目的
1)掌握多边形的有效边表填充算法;
2)掌握边界像素处理原则;
3)掌握菱形图形的填充方法。
二 实验要求
1)设计实现多边形填充类,可以设置顶点序列,调用填充函数。
2)多边形填充采用有效边表填充算法进行实现,通过建立多边形的桶表和边表数据,按照算法步骤依次扫描填充;
x|ymin
ymax
1/k
next
图1 边表结点数据结构
有效边表填充算法实现步骤为:
a)根据多边形的顶点序列,建立其“桶表和边表”数据。
b)按照扫描线从小到大的移动顺序,取出当前扫描线对应桶的边表数据。
c)如果“桶表”数据已经取完,则填充结束;否则,继续后续填充操作。
d)将当前桶里的边表数据加入到有效边表,根据“下闭上开”的原则,删除已经到ymax的无效边。
DeleteAETChain(pBucket->pET);
delete pBucket;
pBucket=pBucketTemp;
}
pHeadB=NULL;
pHeadE=NULL;
}
void CFillPoly::DeleteAETChain(CAET*pAET)
{
while (pAET!=NULL)
{
for(int i=0;i<PNum;i++)
{
pCurrentB=pHeadB;
int j=(i+1)%PNum;
if(P[i].y<P[j].y)
{
pEdge=new CAET;
pEdge->x=P[i].x;
pEdge->yMax=P[j].y;
pEdge->k=(P[j].x-P[i].x)/(P[j].y-P[i].y);
{
CAET *pAETTEmp=pT1;
pT1=pT1->pNext;
delete pAETTEmp;
pHeadE=pT1;
if(pHeadE==NULL)
return;
}
if(pT1->pNext!=NULL)
{
pT2=pT1;
pT1=pT2->pNext;
}
while(pT1!=NULL)
{
if(pCurrentB->ScanLine>=pT1->yMax)
pT1=pT1->pNext;
}
}
}
}
void CFillPoly::ClearMemory()
{
DeleteAETChain(pHeadE);
CBucket*pBucket=pHeadB;
while (pBucket!=NULL)
{
CBucket*pBucketTemp=pBucket->pNext;
pEdge->ps=pCurrentE->ps;
pEdge->pe=pCurrentE->pe;