区域填充算法.docx
《区域填充算法.docx》由会员分享,可在线阅读,更多相关《区域填充算法.docx(24页珍藏版)》请在冰豆网上搜索。
区域填充算法
XX大学计算机科学与技术学院
计算机科学与技术系上机实验报告
课程名称:
计算机图形学
班级:
实验日期:
2012-04-22
姓名:
学号:
指导教师:
实验序号:
4
实验成绩:
一、实验名称
1.多边形的扫描转换算法;
2.区域填充算法。
二、实验目的及要求
1.通过实验,进一步理解和掌握多边形的扫描转换算法和区域填充算法;
2.掌握以上算法实现的基本过程;
3.通过编程,会在TC或VC或Matlab环境下实现多边形的扫描转换算法和区域填充算法。
三、实验环境
1.Win7
2.VisualStudio2010
四、实验内容
1.写出多边形的扫描转换算法和区域填充算法的基本思想和公式。
并比较其特点。
2.编写用多边形的扫描转换算法和区域填充算法的程序。
并比较其结果。
3.写出上机报告
五、实验步骤及算法描述
1.依据算法、步骤编写源程序;
2.编辑源程序并进行调试;
3.进行运行测试,并结合情况进行调整;
4.对运行结果进行保存与分析;
5.打印源程序或把源程序以文件的形式提交;
6.按格式书写实验报告。
六、调试过程及实验结果
程序运行截图:
扫描线转换算法
区域填充算法
七、总结
通过这次试验,是我对多边形的扫描转换算法和区域填充算法有了更深的理解,对于两个算法个人感觉都是很精辟的,在编写程序的过程中遇到了一些困难,但是经过细心的调试和参考教课书上的算法思想,总算是实现了,总的来说这次试验锻炼了自己的编程实践能力,收获良多!
八、附录
核心代码:
多边形扫描线算法:
#region多边形扫描线算法及其相关辅助算法
#region多边形扫描线算法
publicvoidpolyFill(Graphicsg,Polygonpolygon,Colorc)
{
int[][]iMatrix=polyFill(g,polygon,c,null);
}
publicint[][]polyFill(Graphicsg,Polygonpolygon,Colorc,int[][]iMatrix)
{
intiScanLine=polygon.Y[polygon.getMaxY()]-polygon.Y[polygon.getMinY()]+1;
Console.WriteLine(iScanLine);
//新边表头指针NET[i]
ArrayList[]NET=newArrayList[iScanLine];
for(inti=0;i{
//初始化新边表头指针NET[i];
NET[i]=newArrayList();
//把Ymin=i的边放进边表NET[i];
Console.WriteLine("polygon.Y[polygon.getMinY()]+i="+(polygon.Y[polygon.getMinY()]+i));
NET[i]=polygon.getYmin(polygon.Y[polygon.getMinY()]+i);
}
//Y=最低扫描线号;
inty=polygon.Y[polygon.getMinY()];
Console.WriteLine("polygon.Y[polygon.getMinY()]="+polygon.Y[polygon.getMinY()]);
//初始化活性边表AET为空;
ArrayListAET=newArrayList();
for(inti=0;i{
//把NET[i]中的边节点用插入排序法插入AET表,使之按x坐标递增顺序排列;
InsertItem(AET,NET[i]);
//遍历AET表,把配对交点区间(左闭右开)上的象素(x,y),用drawpixel(x,y,color)改写象素值;
for(intj=0;j{
Console.WriteLine("i="+i);
OutAET(AET);
//OutAET((ArrayList)AET[j+1]);
intx1=(int)(getItemX((ArrayList)AET[j])+0.5);
intx2=(int)(getItemX((ArrayList)AET[j+1])+0.5);
inty1=i+y;
if(x1==x2)
{
if(iMatrix==null)
BaseDraw.drawPixel(g,x1,y1,c);
else
{
iMatrix=setMatrixEle(iMatrix,polygon,x1,y1,1);
}
if(AET.Count%2==0)
{
//BaseDraw.drawPixel(g,x1,y1,c);
j++;
}
}
else
{
Console.WriteLine("y1="+y1+"\tx1="+x1+"\tx2="+x2);
for(intl=x1;l<=x2;l++)
{
if(iMatrix==null)
BaseDraw.drawPixel(g,l,y1,c);
else
{
iMatrix=setMatrixEle(iMatrix,polygon,l,y1,1);
}
}
j++;
}
}
//Console.WriteLine("draw=======================");
//OutAET(AET);
//遍历AET表,把Ymax=i的结点从AET表中删除,并把Ymax>i结点的x值递增△x;
Stackstack=newStack();
for(intj=0;j{
//UpdateItemX(AET,j);
//OutAET(AET);
if(getItemYmax((ArrayList)AET[j])==i+y)
{
stack.Push(j);
Console.WriteLine("deletei="+i+"\tj="+j+"\t(y+j)="+(y+j)+"Ymax="+getItemYmax((ArrayList)AET[j]));
//AET.RemoveAt(j);
}
elseif(getItemYmax((ArrayList)AET[j])>i+y)
UpdateItemX(AET,j);
}
while(stack.Count>0)
{
inte=(int)stack.Pop();
AET.RemoveAt(e);
}
//OutAET(AET);
}
returniMatrix;
}
#endregion
#region对活性边表进行插入的同时排序
///
///对活性边表进行插入的同时排序
///
///原活性边表
///要插入的新边
protectedvoidInsertItem(ArrayLista1,ArrayLista2)
{
//第一步把a2中元素全部插入到a1
if(a2!
=null||a2.Count!
=0)
for(inti=0;i{
a1.Add(a2[i]);
}
//第二步用对a1元素进行排序
for(inti=a1.Count-1;i>0;i--)
{
for(intj=a1.Count-1;j>a1.Count-1-i;j--)
{
if(getItemX((ArrayList)a1[j-1])>getItemX((ArrayList)a1[j]))
{
ArrayListtemp=(ArrayList)a1[j-1];
a1[j-1]=a1[j];
a1[j]=temp;
}
}
}
}
#endregion
#region获得ArrayList元素的x值
///
///获得ArrayList元素的x值
///
///
///
protectedfloatgetItemX(ArrayListlst)
{
if(lst==null)
return0;
return(float)lst[0];
}
#endregion
#region获得ArrayList元素的Ymax值
///
///获得ArrayList元素的Ymax值
///
///
///
protectedintgetItemYmax(ArrayListlst)
{
if(lst==null)
return0;
return(int)lst[2];
}
#endregion
#region获得ArrayList元素的△x值
///
///获得ArrayList元素的△x值
///
///
///
protectedfloatgetItemtx(ArrayListlst)
{
if(lst==null)
return0;
return(float)lst[1];
}
#endregion
#region更新ArrayList元素的x值使X=X+△x
///
///更新ArrayList元素的x值使X=X+△x
///
///
protectedvoidUpdateItemX(ArrayListlst,intindex)
{
if(lst==null)
return;
if(index>=lst.Count)
{
Console.WriteLine("Err");
return;
}
try
{
//Console.WriteLine("index="+index);
ArrayListl=(ArrayList)lst[index];
floatx=(float)l[0];
floattx=(float)l[1];
//四舍五入计算x
x=x+tx;
l[0]=x;
lst[index]=l;
}
catch{}
}
#endregion
#region输出活性边表,以便观察
protectedvoidOutAET(ArrayListaet)
{
if(aet==null)
Console.WriteLine("\nEmpty!
\n");
else
{
Console.WriteLine("=========================================");
for(inti=0;i{
ArrayLista=(ArrayList)aet[i];
Console.Write(getItemX(a)+""+a[1].ToString()+""+a[2].ToString()+"==");
}
Console.WriteLine("");
Console.WriteLine("-----------------------------------------");
}
}
#endregion
#endregion
区域填充算法:
#region区域填充算法及其相关辅助算法
#region区域填充扫描线算法
publicvoidScanLineFill4(Graphicsg,Polygonpolygon,intx,inty,Colorc1,Colorc2)
{
#region旧算法无用
/*
//首先把多边形区域用直线画出来
//drawPolygon(g,polygon,c);
//然后填充
HashtablehashX=polygon.getX();
intiScanLine=polygon.Y[polygon.getMaxY()]-polygon.Y[polygon.getMinY()]+1;
Console.WriteLine(iScanLine);
for(inti=0;i{
intsy=i+polygon.Y[polygon.getMinY()];
ArrayListarr=(ArrayList)hashX[sy];
for(intj=0;j{
Console.Write(arr[j].ToString()+"\t");
}
Console.WriteLine("");
}
*/
#endregion
//首先画轮廓
//drawPolygon(g,polygon,c1);
int[][]iPoly=polygon.getMatrix();
iPoly=this.polyFill(null,polygon,c1,iPoly);
OutMatrix(iPoly);
intxl,xr;
boolspanNeedFill;
Pointpt=newPoint(x,y);
Stackstack=newStack();
//pt.X=x;pt.Y=y;
stack.Push(pt);
while(stack.Count>0)
{
pt=(Point)stack.Pop();
y=pt.Y;
x=pt.X;
//iPoly=setMatrixEle(iPoly,polygon,x,y,2);
while(ChkMtxEle(iPoly,polygon,x,y)==1)//向左填充
{
BaseDraw.drawPixel(g,x,y,Color.Red);
iPoly=setMatrixEle(iPoly,polygon,x,y,2);
x++;
}
xr=x-1;
x=pt.X-1;
while(ChkMtxEle(iPoly,polygon,x,y)==1)//向右填充
{
BaseDraw.drawPixel(g,x,y,Color.Red);
iPoly=setMatrixEle(iPoly,polygon,x,y,2);
x--;
}
xl=x+1;
//OutMatrix(iPoly);
//Console.WriteLine("stack.Count="+stack.Count);
//处理上面一条线
x=xl;
y=y+1;
while(x{
spanNeedFill=false;
while(ChkMtxEle(iPoly,polygon,x,y)==1)
{
spanNeedFill=true;
x++;
}
if(spanNeedFill)
{
pt.X=x-1;
pt.Y=y;
stack.Push(pt);
spanNeedFill=false;
}
while(ChkMtxEle(iPoly,polygon,x,y)!
=1&&xx++;
}//Endofwhile(x//处理下面一条扫描线
x=xl;
y=y-2;
while(x{
spanNeedFill=false;
while(ChkMtxEle(iPoly,polygon,x,y)==1)
{
spanNeedFill=true;
x++;
}
if(spanNeedFill)
{
pt.X=x-1;
pt.Y=y;
stack.Push(pt);
spanNeedFill=false;
}
while(ChkMtxEle(iPoly,polygon,x,y)!
=1&&xx++;
}//Endofwhile(x}
}
publicvoidScanLineFill4(Graphicsg,intx,inty,Colorc1,Colorc2)
{
ScanLineFill4(g,this,x,y,c1,c2);
}
#endregion
#region检查某个点是否是边界点
///
///检查某个点是否是边界点
///
///矩阵点
///多边形
///x坐标
///y坐标
///
protectedintChkMtxEle(int[][]iMatrix,Polygonpoly,intx,inty)
{
x-=poly.X[poly.getMinX()];
y-=poly.Y[poly.getMinY()];
if(0<=y&&y=0&&xreturniMatrix[y][x];
else
return0;
}
#endregion
#region设置矩阵某个点的值
///
///设置矩阵某个点的值
///
///矩阵
///x坐标
///y坐标
///
protectedint[][]setMatrixEle(int[][]iMatrix,Polygonpoly,intx,inty,intiVal)
{
x-=poly.X[poly.getMinX()];
y-=poly.Y[poly.getMinY()];
iMatrix[y][x]=iVal;
returniMatrix;
}
#endregion
#region返回多边形交点矩阵
///
///返回多边形交点矩阵
///
///
publicint[][]getMatrix()
{
int[][]iPoly=newint[Y[getMaxY()]-Y[getMinY()]+1][];
for(inti=0;i