多边形区域填充算法
void po_fill(ET<int> &etp, int ep, int color) //多边形填充函数的实现
{
int i=1; //i作为控制变量标识扫描线
while(i<ep-1)
{
if(etp.a[i]!=NULL)
{
Enode<int> *p,*r;
p=etp.a[i];
r=etp.a[0];
{
stack_list *new_node;
new_node=new stack_list();
new_node->x=xx;
new_node->y=yy;
new_node->next=stack;
stack=new_node;
}
//pop an element
void pop(int &xx,int &yy)
int color=5; //color用于标识填充颜色
ET<int> et(e);
et.Insert(2,5,8,4/3);
et.Insert(2,5,8,-4/3);
et.Insert(5,10,15,-1);
et.Insert(5,10,4,6/5); //根据初始数据建立边表
po_fill(et, e, color); //调用填充函数
int n; //覆盖该多边形的扫描线的总数,从0开始计数
Enode<T> **a;
}; //定义了边表类
template <class T>
ET<T>::ET(int mSize)
{
n=mSize;
a=new Enode<T> *[n];
for(int i=0;i<n;i++) a[i]=0;
} //ET边表的初始化
1
2
3
4
5
6
15.用扫描线种子填充算法,编写一个填充多边形区域的程序。
该测试多边形的各个端点坐标分别为:
A(50, 150),B(50, 100),C(100, 50),D(250, 50),E(200, 150);
F(100, 100),G(100, 75),H(175, 135);
/****************************************************************************
{
putpixel(x0,y,4);
x0=x0-1;
}
xl=x0+1;//记录最左值
xlold=xl;//再记录一次最左值,以备后用
y0=y+1;//go up向上移一条扫描线
go2=0;//go2也只是一个用来标记的变量
while(xr>xl&&go==0)//查找上一条线的最右值,并记录为xr
{
} //把一对相邻结点的xi区间范围进行填充
}
if(etp.a[0]!=NULL)
{
Enode<int> *w;
int s=1;
while(s)
{
Enode<int> *z=NULL;
w=etp.a[0];
s=0;
while(w && w->ymax!=i)
{
z=w; w=w->next;
}
if(!w) break;
int x;
int y;
stack_node *next;
};
typedef stack_node stack_list;
typedef stack_list *link;//用单链表来表示堆栈
link stack = 0; //stack标识栈顶指针
//push an element
void push(int xx,int yy)
if(z) z->next=w->next;
else etp.a[0]=w->next;
delete w;
s=1;
} //删去AET表中i值已经等于ymax的结点记录
if(etp.a[0])
{
Enode<int> *u,*v;
u=etp.a[0];
while(u)
{
v=u;
u=u->next;
v->xi=v->xi+v->m;
int go=0,go2=0;
int i=0;
push(x,y);//种子像素入栈
while(stack!=0)//如果栈不空则循环,stack==0表示栈空
{
go=0; //go只是一个标记
pop(x,y); //从栈中将栈顶元素弹出
putpixel(x,y,4); //将该点置色
x0=x+1;//取种子右边的像素
while(getpixel(x0,y)!=4)//fill right填充右边像素
{
putpixel(x0,y,4);
x0=x0+1;
}
xr=x0-1;//记录最右值
xrold=xr;//再记录一次最右值,以备后用
x0=x-1;//取种子左边的像素
while(getpixel(x0,y)!=4)//fill left填充左边像素
扫描的次序:先上后下
进栈的次序:先右后左
测试数据:
第一个多边形:A(50, 150),B(50, 100),C(100, 50),D(250, 50),E(200, 150);
第二个多边形:F(100, 100),G(100, 75),H(175, 135);
*****************************************************************************/
if(r->xi>q->xi) {etp.a[0]=q; q->next=r;}
else {
while(q->xi>r->xi && r->next)
r=r->next;
if(r->next) {q->next=r->next; r->next=q; }
else {r->next=q; q->next=NULL;}
[注]边关系的建立可通过邻接矩阵的数据结构实现,权值可以为该矩阵行编号对应点的y坐标值,ET边表采用邻接表的数据结构
第2步:根据ET表构建AET表,并逐行完成多边形填充,具体的C++代码如下:
(1)建立头文件base_class.h,主要是边表结点结构体和ET边表类的实现
enum ResultCode{Success, Failure};
14.已知多边形各顶点坐标为(2, 2)(2, 4)(8, 6)(12, 2)(8, 1)(6T及全部AET内容。
解:如图所示:
则该多边形的ET表为:
6
5
4
3
2
1
该多边形的AET指针的内容为:(每条扫描线均有3行指针链,第1行表示将ET表加入AET中,第2行表示从AET表中删去yi=ymax,第3行表示xi=xi+1/m后,学生只要写出第2行即可)
template <class T>
ET<T>::~ET()
{
Enode<T> *p, *q;
delete a[0];
for(int i=1;i<n;i++)
{
p=a[i]; q=p;
while(p)
{
p=p->next;
delete q;
q=p;
}
}
delete []a;
} //析构函数负责回收内存空间
}
}
p=p->next;
}
} //按照xi值的大小将当前ET表中的记录放置到AET表中
Enode<int> *f,*g;
if(etp.a[0])
{
f=etp.a[0];
while(f->next)
{
g=f;
f=f->next;
for(int j=g->xi;j<=g->next->xi;j++)
putpixel(j,i,color);
}
} //用xi+m来替代原有的xi
}
i++; //进入下一条扫描线
}
}
void main()//主函数的实现
{
int gdriver, gmode;
gdriver=DETECT;
gmode=VGAHI;
initgraph(&gdriver, &gmode,""); //图形系统初始化
int e=11;
本程序实现区域填充功能,首先输入多边形顶点的个数,回车,
然后依次输入各顶点的坐标格式如下:100,123回车
一定要在中间用逗号隔开噢,输完最后一个点后,屏幕上会依次
画出各条边,最后填充满
程序还不完善,比如颜色值应该用变量表示以易于修改,画多边形和求种子点
应该做成独立的函数等等,以后再做上吧,这是细节的问题
template <class T>
ResultCode ET<T>::Insert(int u, T ymax, float xi, float m)
{
if(u<0||u>n-1) return Failure;