实验2:多边形区域扫描线填充或种子填充
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验2:多边形区域扫描线填充或种子填充
一、实验目的
1.通过实验,进一步理解和掌握几种常用多边形填充算法的基本原理
2.掌握多边形区域填充算法的基本过程
3.掌握在C/C++环境下用多边形填充算法编程实现指定多边形的填充。
二、实验内容
用种子填充算法和扫描线填充算法等任意两种算法实现指定多边形的区域填充。
三、实验原理
种子填充算法又称为边界填充算法。其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止。种子填充算法常用四连通域和八连通域技术进行填充操作。
四向连通填充算法:
a)种子像素压入栈中;
b)如果栈为空,则转e);否则转c);
c)弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;
d)转b);
e)结束。
扫描线填充算法的基本过程如下:当给定种子点(x,y)时,首先填充种子点所在扫描线上的位于给定区域的一个区段,然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。反复这个过程,直到填充结束。
区域填充的扫描线算法可由下列四个步骤实现:
(1)初始化:堆栈置空。将种子点(x,y)入栈。
(2)出栈:若栈空则结束。否则取栈顶元素(x,y),以y作为当前扫描线。
(3)填充并确定种子点所在区段:从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xl和xr。
(4)并确定新的种子点:在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的象素。若存在非边界、未填充的象素,则把每一区间的最右象素作为种子点压入堆栈,返回第(2)步。
四、实验步骤
1.复习有关算法,明确实验目的和要求;
2.依据算法思想,绘制程序流程图(指定填充多边形);
3.设计程序界面,要求操作方便;
4.用C/C++语言编写源程序并调试、执行(最好能用动画显示填充过程);
5.分析实验结果
6.对程序设计过程中出现的问题进行分析与总结;
7.打印源程序或把源程序以文件的形式提交;
8.按格式要求完成实验报告。
五、实验结果及分析
种子填充算法的优点是非常简单,缺点是需要大量栈空间来存储相邻的点。扫描线填充算法就是它的改进的方法。它是通过沿扫描线填充水平像素段,来处理四连通或八连通相邻点,这样就仅仅只需要将每个水平像素段的起始位置压入栈,而不需要将当前位置周围尚未处理的相邻像素都压入栈,从而可以节省大量的栈空间。
六、实验结果
种子填充算法
扫描线填充算法七、实验主要代码
//种子填充算法
void CZhztchView::boundaryfill4(int x, int y, int boundarycolor, int newcolor)
{
int color;
CClientDC dc(this); //获取客户区设备描述表
color=dc.GetPixel(x,y);
if(color!=newcolor&&color!=boundarycolor)
{
dc.SetPixel(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);
}
}
//////////////////////////////////////////////////////////////////// ////////////
//扫描线填充算法
void CZhztchView::OnScanfill()
{
RedrawWindow();
CDC* pDC=GetDC();
CPen newpen(PS_SOLID,3,RGB(255,0,0));
CPen *old=pDC->SelectObject(&newpen);
spt[0]=CPoint(100,100); //绘制多边形区域
spt[1]=CPoint(300,100);
spt[2]=CPoint(250,250);
spt[3]=CPoint(100,250);
spt[4]=CPoint(150,200);
spt[5]=CPoint(90,180);
spt[6]=CPoint(150,150);
spt[7]=CPoint(100,100);
pDC->Polyline(spt,8);
//pDC->SelectObject(old);
//ReleaseDC(pDC);
// TODO: Add your command handler code here
//CDC* pDC=GetDC();
CPen newpen2(PS_SOLID,1,RGB(0,255,0));
CPen *old2=pDC->SelectObject(&newpen2);
int j,k,s = 0;
int p[5]; //每根扫描线交点
int pmin = 0,pmax = 0;
for(int i=0;i<=6;i++)//建立边表
{
edge[i].dx=(float)(spt[i+1].x-spt[i].x)/(spt[i+1].y-spt[i].y);
if(spt[i].y<=spt[i+1].y){
edge[i].num=i;
edge[i].ymin=spt[i].y;
edge[i].ymax=spt[i+1].y;
edge[i].xmin=(float)spt[i].x;
edge[i].xmax=(float)spt[i+1].x;
if(spt[i+1].y > pmax)
pmax = spt[i+1].y;
if(spt[i].y < pmin)
pmin = spt[i].y;
}
else{
edge[i].num=i;
edge[i].ymin=spt[i+1].y;
edge[i].ymax=spt[i].y;
edge[i].xmax=(float)spt[i].x;
edge[i].xmin=(float)spt[i+1].x;
if(spt[i].y > pmax)
pmax = spt[i].y;
if(spt[i+1].y < pmin)
pmin = spt[i+1].y;
}
}
for(int r=1;r<=6;r++) //排序edge(yUpper,xIntersect),结果为从大到小
{
for(int q=0;q<=6-r;q++)
{
if(edge[q].ymin { newedge[0]=edge[q]; edge[q]=edge[q+1]; edge[q+1]=newedge[0]; } } }