图形学实验报告四 多边形填充算法

合集下载

多边形填充算法实验报告

多边形填充算法实验报告

学生实验报告
实验课名称:计算机图形学
实验项目名称:多边形填充算法
专业名称:计算机科学与技术
班级:
学号:
学生姓名:
教师姓名:
2016年4月30 日
六.运行结果与分析:
图1:扫描线种子填充算法
图2:种子填充算法
七.实验中遇到的问题、解决方法及体会:
多边形的填充对我来说很困难,因为一开始我不知道要输入什么数据,后来我决定要输入五个点来形成一个五边形,但是输入的顺序是一个大问题。

后来我采取顺序输入的方法,但是程序运行时常常崩溃,结果不尽人意。

最后,我在同班同学的帮助之下,找到了自己的问题,完成了填充。

多边形的平行线填充算法

多边形的平行线填充算法

多边形的平行线填充算法是一种在多边形内部填充平行线的技术。

以下是该算法的基本步骤:
1. 定义一个多边形,可以是一个由一系列点组成的凸多边形,也可以是一个有多个凹边的多边形。

2. 确定填充线的方向和间距。

填充线的方向可以由用户指定,也可以根据多边形的特征自动确定。

填充线的间距则可以根据填充效果的要求进行设置。

3. 计算多边形各点到填充线的距离,将距离小于等于填充线间距的点标记为填充点。

4. 根据填充点的分布情况,将填充点连接成线段,形成填充线。

5. 将填充线与多边形的边界进行交点计算,得到一系列交点。

6. 根据交点的位置关系,将交点连接成线段,形成最终的填充效果。

需要注意的是,对于有多个凹边的多边形,需要进行更复杂的交点计算和线段连接操作,以保证填充效果正确无误。

此外,为了提高填充效率,可以使用一些优化技巧,如排除法、排序算法等。

图形学实验报告四 多边形填充算法

图形学实验报告四 多边形填充算法

扫描线种子填充:
public void FillField(int x, int y, Color newColor, uint oldColor, Graphics g) {
if ("".Equals(txtx.Text) || "".Equals(txty.Text)) { return; } else { x = Convert.ToInt32(txtx.Text); y = Convert.ToInt32(txty.Text); } int xl, xr; bool spanNeedFill; myStack.Clear();
个交点。如右图,对 y=8 的扫描线排序 x 坐标得到的表是(2,4,9,13),然后对交点 2 与 4 之间、9 与 13 之间 的所有象素点进行填充。 边界上的象素:“左闭右开”,“下闭上开”(将左边界和下边界的点算为内部,而将右边界和上边界 算为外部) 顶点:“上开下闭”。
几种特殊情况: 1.扫描线交于一顶点,共享的两条边分另处于扫描线的两边,这时交点只取一个,如扫描线 y=3,该点被填 充一次。2.共享交点的两条边处于扫描线的上方,这时交点取二个,如扫描线 y=1,该点被填充一次。 3.共享交点的两条边处于扫描线的下方,这时交点取 0 个,如扫描线 y=9,无交点,不填充。 4.水平边在算法中不起任何作用,可不考虑。 活性边表(提高效率): 为了减少求交的计算量,要利用一条边与相继的两条扫描线的交点的连贯性。在处理一条扫描线时只对活 性边(与它相交的多边形的边)进行求交运算。把交点按 x 增加方向存在一个链表(活性边表)中。活性边: 与当前扫描线相交的边。 活性边表(AEL) :按交点 x 的增量顺序存放在一个链表中,该链表称作活性边表(AEL) 。

《计算机图形学》有序边表填充算法

《计算机图形学》有序边表填充算法

初始化每条扫面线的边链表 */
/*
建“桶” */
edges[scan]->next=NULL;
}
BuildEdgeList(cnt,pts,edges);
/*
建立有序边表 */
active=(Edge *)malloc(sizeof(Edge));
active->next=NULL;
for(scan=scanmin;scan<=scanmax;scan++) /* 扫描每条扫描线, 求活性表 */
当多边形新边表 ET构成后,按下列步骤进行: ① 对每一条扫描线 i ,初始化 ET表的表头指针 ET[i] ; ② 将 ymax = i 的边放入 ET[i] 中; ③ 使 y = 多边形最低的扫描线号; ④ 初始化活性边表 AET为空; ⑤ 循环,直到 AET和 ET 为空。
将新边表 ET 中对应 y 值的新边节点插入到 AET表。 遍历 AET表,将两两配对的交点之间填充给定颜色值。 遍历 AET表,将 ymax= y 的边节点从 AET表中删除,并将 ymax> y 的各边节点 的 x 值递增 Δx;并重新排序。 y 增加 1。
/* 建立扫描线 scan 的活性边表 , 把活性边结点放入扫描线 scan 的结点指针数组
edges[scan] 中*/
{
Edge *p,*q;
p=edges[scan]->next;
/*
查找当前扫描线对应的 y 桶*/
while(p)
/*y
桶不空 */
{q=p->next;
/*
找到最后一个边结点, 插入 */
*edges[])
/* 把边结点 edge, 放到 lower.y 扫描线所在的边结点指针数组 edges[] 中 */

多边形的填充实验经典

多边形的填充实验经典

试验实验一:图形的区域填充一、实验目的区域填充是指先将区域内的一点(常称为种子点)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。

区域填充技术广泛应用于交互式图形、动画和美术画的计算机辅助制作中。

本实验采用递归填充算法或打描线算法实现对光栅图形的区域填充。

通过本实验,可以掌握光栅图形编程的基本原理和方法。

实验内容掌握光栅图形的表示方法,实现种子算法或扫描线算法。

通过程序设计实现上述算法。

建议采用VC++实现OpenGL程序设计。

三、实验原理、方法和手段递归算法在要填充的区域内取一点(X, Y)的当前颜色记为oldcoloo用要填充的颜色ne wcolor去取代,递归函数如下:procedure flood-fill(XXoldcoloLnewcolor:integer); beginif getpixel(fiainebufier,x,y)=oldcolorthen beginsetpixel(fiamebuffer,x,y,newcolor); flood-fill(X.Y+1 .oldcoloLiiewcolor);flood-fill(X.Y^ 1 ,oldcoloi;newcolor); flood-fill(X-l,Y;oldcoloi;newcolor); flood-fill(X+l,Yoldcoloi;newcolor);endend扫描线算法扫描线算法的效率明显高于递归算法,其算法的基本思想如下:(1)(初始化)将算法设置的堆栈置为空,将给定的种子点(x,y)压入堆栈。

(2)(出栈)如果堆栈为空,算法结束;否则取栈顶元素(x,y)作为种子点。

(3)(区段填充)从种子点(x,y)开始沿纵坐标为y的当前扫描线向左右两个方向逐个象素进行填色,其值置为newcoloi;直到抵达边界为止。

(4)(定范围)以XleA和Xn血分别表示在步骤3中填充的区段两端点的横坐标。

(5)(进栈)分别在与当前扫描线相邻的上下两条打描线上,确定位于区间[Xldb Xn 曲]内的给定区域的区段。

计算机图形学实验有效边表填充算法

计算机图形学实验有效边表填充算法

实验二2-2一、实验题目给定四个点绘制图4-44所示的不同转角的两个正方形,使用有效边表算法进行填充,填充效果如图4-45所示,注意采用“左闭右开”和“上闭下开”的原则,使得每个正方形的右边界和下边界没有填充。

二、实验思想有效边表填充算法通过维护边表和有效边表,避开了扫描线与多边形所有边求交的复杂运算。

填充原理是按照扫描线从小到大的移动顺序,计算当前扫描线与有效边的交点,然后把这些交点按x值递增的顺序进行排序、配对,以确定填充区间,最后用指定颜色填充区间内的所有像素,即完成填充工作。

三、实验代码void CTestView::GetMaxX()//获得屏幕宽度{CRect Rect;GetClientRect(&Rect);MaxX=Rect.right;}void CTestView::GetMaxY()//获得屏幕高度{CRect Rect;GetClientRect(&Rect);MaxY=Rect.bottom;}void CTestView::ReadPoint()//读入点表函数{//设置第一个正方形的4个顶点int a=160;P1[0]=CP2(MaxX/4-a,MaxY/2+a);//P0P1[1]=CP2(MaxX/4+a,MaxY/2+a);//P1P1[2]=CP2(MaxX/4+a,MaxY/2-a);//P2P1[3]=CP2(MaxX/4-a,MaxY/2-a);//P3//设置第二个正方形的4个顶点int b=ROUND(sqrt(2)*a);P2[0]=CP2(3*MaxX/4,MaxY/2+b);//P0P2[1]=CP2(3*MaxX/4+b,MaxY/2);//P1P2[2]=CP2(3*MaxX/4,MaxY/2-b);//P2P2[3]=CP2(3*MaxX/4-b,MaxY/2);//P3}void CTestView::DrawRect(CDC *pDC,CP2 *P)//绘制正方形函数{CP2 T;CLine line;for(int i=0;i<4;i++)//边循环{if(i==0){line.MoveTo(pDC,P[i]);T=P[0];}else{line.LineTo(pDC,P[i]);;}}line.LineTo(pDC,T);//闭合}void CTestView::OnMENUIFill(){// TODO: Add your command handler code hereCOLORREF FColor;CColorDialog ccd(RGB(255,0,0));if(ccd.DoModal()==IDOK)//调用调色板选取色{FColor=ccd.GetColor();m_Red=GetRValue(FColor);//获得颜色的红色分量m_Green=GetGValue(FColor);//获得颜色的绿色分量m_Blue=GetBValue(FColor);//获得颜色的蓝色分量}RedrawWindow();//刷新屏幕FillRect(P1);//填充正方形1FillRect(P2);//填充正方形2}void CTestView::FillRect(CP2 *P)//填充正方形函数{CFill fill;CPi2 Point[4];for(int i=0;i<4;i++){Point[i].x=P[i].x;Point[i].y=ROUND(P[i].y);Point[i].c=CRGB(double(m_Red)/255.0,double(m_Green)/255.0,double(m_Blue)/255.0);}CDC *pDC=GetDC();fill.SetPoint(Point,4);//填充正方形fill.CreateBucket();fill.CreateEdge();fill.Gouraud(pDC);ReleaseDC(pDC);}四、实验截图。

计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验————————————————————————————————作者: ————————————————————————————————日期:ﻩ《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:四连通区域种子填充算法实验时间:2016年12月8日实验地点:信息学院2204实验目的:掌握种子填充算法的原理,并会用种子填充算法和opengl并结合使用c++语言编写程序绘制多边形。

实验原理:种子填充算法又称为边界填充算法。

其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。

如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止。

内点的检测条件:if(interiorColor!=bo rderColor&&interiorColor!=fillColor)。

种子填充算法常用四连通域和八连通域技术进行填充操作。

从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。

用这种方法填充的区域就称为四连通域;这种填充方法称为四向连通算法。

从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素。

用这种方法填充的区域就称为八连通域;这种填充方法称为八向连通算法。

一般来说,八向连通算法可以填充四向连通区域,而四向连通算法有时不能填充八向连通区域。

四向连通填充算法:a)种子像素压入栈中;b)如果栈为空,则转e);否则转c);c) 弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;d)转b);e)结束。

四连通填充算法利用到了递归的思想。

本实验只包括四连通填充算法程序代码:#include<glut.h>#include<stdlib.h>#include<math.h>#include<windows.h>voidinit(void){ glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,300.0,0.0,300.0);}void setPixel(intx,inty,longfillColor){ glColor3f(fillColor<<16,fillColor<<8,fillColor);glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}voidboundaryFill4(int x,inty,long fillColor,long borderColor){ unsignedchar params[3];long interiorColor;glReadPixels(x,y,1,1,GL_RGB,GL_UNSIGNED_BYTE,par ams);interiorColor=RGB(params[0],params[1],params[2]);if(interiorColor!=borderColor&&interiorColor!=fillColor){ setPixel(x,y,fillColor);boundaryFill4(x+1,y,fillColor,borderColor);boundaryFill4(x-1,y,fillColor,borderColor); boundaryFill4(x,y+1,fillColor,borderColor);boundaryFill4(x,y-1,fillColor,borderColor);} }voidlineSegment(void) {long borderColor=RGB(255,0,0);longfillColor=RGB(0,0,255);glClear(GL_COLOR_BUFFER_BIT); glColor3f(255,0,0); glBegin(GL_LINE_LOOP);glVertex2i(0,40);glVertex2i(20,0);glVertex2i(60,0);glVertex2i(80,40);glVertex2i(60,80);glVertex2i(20,80);glEnd();boundaryFill4(60,60,fillColor,borderColor);glFlush();}voidmain(int argc,char**argv){glutInit(&ar gc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(150,100);glutInitWindowSize(300,300);glutCreateWindow("种子填充");init();glutDisplayFunc(lineSegment);glutMainLoop();}上实验课时机房的实验结果:后来的实验结果:glVertex2i(0,40);glVertex2i(20,0);glVertex2i(60,0);glVertex2i(80,40);glVertex2i(60,80);glVertex2i(20,80);glEnd();boundaryFill4(60,60,fillColor,borderColor);以上这段程序改成如下glVertex2i(90,40);glVertex2i(120, 100);glVertex2i(90,160);glVertex2i(60, 160);glVertex2i(60, 40);glEnd();boundaryFill4(70,60,fillColor,borderColor); 改变参数后:再把glVertex2i(90,40);glVertex2i(120, 100);glVertex2i(90,160);glVertex2i(60, 160);glVertex2i(60, 40);glEnd();boundaryFill4(70,60,fillColor,borderColor);改成glVertex2i(100, 100);glVertex2i(200, 100);glVertex2i(150,150);//glVertex2i(60, 160);//glVertex2i(60, 40);glEnd();boundaryFill4(150,120,fillColor,borderColor);后的结果如下图:实验总结:通过多组数据的测试,知道了上面算法的正确,普适性。

计算机图形学实验四 区域填充算法的实现

计算机图形学实验四   区域填充算法的实现

实验四区域填充算法的实现班级 08信计2班学号 20080502082 姓名分数一、实验目的和要求:1、理解区域的表示和类型。

2、能正确区分四连通和八连通的区域3、了解区域填充的实验原理。

4、利用C++实现区域填充的递归算法。

二、实验内容:1假设在多边形内有一像素已知,由此出发利用连通性找到区域内所有像素。

2 取(x,y)为种子点将整个区域填充为新的颜色。

3 进行递归填充。

三、实验结果分析区域填充属性包括填充样式,填充颜色和填充图案的类型。

C语言中定义了某种图形后,即可调用-floodfill函数,对指定区域进行填充. 程序代码#define pi 3.141592#define MAX(a,b) (a>b)? a:b#define MIN(a,b) (a<b)? a:b#include "graphics.h"#include "math.h"struct edge {int ymax;float x;float delat;struct edge * pedge; };struct point{int x;int y;} ;struct et { struct edge * pedge;int n;};struct edge g_aet[10];struct edge dge[10];struct et g_et[10];struct point point1,point2;int ZUO(float x){ if((int)x==x)return (int)x;return (int)x+1;}int YOU(float x){ if((int)x==x)return (int)x-1;return (int)x;}int k=400,l=0;void draw1(){int i,t,j,a,c,p,z; float b;struct edge temp;for(i=k;i<=l;i++){a=0;for(t=0;t<=9;t++){ if(g_et[t].n==i) break;}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break;}if(t!=10){ g_aet[j].ymax=g_et[t].pedge->ymax;g_aet[j].x=g_et[t].pedge->x;g_aet[j].delat=g_et[t].pedge->delat;if(g_et[t].pedge->pedge!=0){g_aet[j+1].ymax=g_et[t].pedge->pedge->ymax;g_aet[j+1].x=g_et[t].pedge->pedge->x;g_aet[j+1].delat=g_et[t].pedge->pedge->delat; }}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break; }j--;for(t=0;t<=j;t++){ for(z=0;z<=j-1;z++){if(g_aet[z].x>g_aet[z+1].x){ temp.ymax=g_aet[z].ymax;temp.x=g_aet[z].x;temp.delat=g_aet[z].delat;g_aet[z].ymax=g_aet[z+1].ymax;g_aet[z].x=g_aet[z+1].x;g_aet[z].delat=g_aet[z+1].delat;g_aet[z+1].ymax=temp.ymax;g_aet[z+1].x=temp.x;g_aet[z+1].delat=temp.delat;}}}for(j=0;j<=9;j++){ if(g_aet[j].ymax==0) break; }j--;for(p=0;p<=j;p++){ a++;if(a%2!=0)b=g_aet[p].x;else{for(c=ZUO(b);c<=YOU(g_aet[p].x);c++)putpixel(c,i,2);}}for(t=0;t<=j;t++){ if(g_aet[t].ymax==(i+1)){ g_aet[t].ymax=0;g_aet[t].x=0;g_aet[t].delat=0;}g_aet[t].x+=g_aet[t].delat;}for(t=0;t<=j;t++){ for(z=0;z<=j-1;z++){if(g_aet[z].x<g_aet[z+1].x){ temp.ymax=g_aet[z].ymax;temp.x=g_aet[z].x;temp.delat=g_aet[z].delat;g_aet[z].ymax=g_aet[z+1].ymax;g_aet[z].x=g_aet[z+1].x;g_aet[z].delat=g_aet[z+1].delat;g_aet[z+1].ymax=temp.ymax;g_aet[z+1].x=temp.x;g_aet[z+1].delat=temp.delat;}}}}}void generate(){int i,y,n=1,m,q,p;float x;for(i=0;i<=9;i++){if(n==1){ point2.x=point1.x=300;point2.y=point1.y=200;n++;}else{ if(n%2==0){ x=40*cos(i*pi/5)+200;y=40*sin(i*pi/5)+200;}else{ x=100*cos(i*pi/5)+200;y=100*sin(i*pi/5)+200;}if(point1.y==y) { n++; continue;}m=MIN(point1.y,y);if(x==point1.x){ dge[i-1].delat=0;dge[i-1].ymax=MAX(point1.y,y);dge[i-1].x=x;dge[i-1].pedge=0;for(q=0;q<=9;q++){ if(g_et[q].n==m) break;}if(q==10){g_et[i-1].pedge=&dge[i-1];g_et[i-1].n=m;}else{g_et[q].pedge->pedge=&dge[i-1];g_et[i-1].n=0;}}else{dge[i-1].delat=(float)(x-point1.x)/(y-point1.y);dge[i-1].ymax=MAX(point1.y,y);if(point1.y>y) dge[i-1].x=x;else {dge[i-1].x=point1.x; }dge[i-1].pedge=0;for(q=0;q<=9;q++){ if(g_et[q].n==m) break;}if(q==10){ g_et[i-1].pedge=&dge[i-1];g_et[i-1].n=m;}else{g_et[q].pedge->pedge=&dge[i-1];g_et[i-1].n=0;}}p=MAX(point1.y,y);k=MIN(k,m);l=MAX(l,p);point1.x=x;point1.y=y;n++;}}if(point1.y==point2.y) return;else{if(point2.x==point1.x){dge[i-1].delat=0;dge[i-1].ymax=MAX(point1.y,point2.y);dge[i-1].x=point2.x;}else{ dge[i-1].ymax=MAX(point1.y,point2.y);if(point1.y>point2.y) dge[i-1].x=point2.x;else {dge[i-1].x=point1.x;}dge[i-1].delat=(float)(point2.x-point1.x)/(point2.y-point1.y);}}m=MIN(point1.y,point2.y);k=MIN(k,m);l=MAX(l,dge[i-1].ymax);g_et[i-1].n=m;g_et[i-1].pedge=&dge[i-1];}void main(){ int driver=DETECT,mode; int i; registerbgidriver(EGA VGA_driver);initgraph(&driver,&mode,"\\tc");initgraph(&driver,&mode,"\\tc");for(i=0;i<=9;i++){ g_aet[i].ymax=0; g_aet[i].x=0; g_aet[i].delat=0;g_et[i].pedge=0;}generate();draw1();circle(200,200,100); circle(200,200,40);getch();closegraph();}。

计算机图形学 有效边表填充算法实验报告

计算机图形学 有效边表填充算法实验报告

实验题目: 实验二有效边表填充算法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)建立AET和BUCKET类;(2)初始化桶, 并在建立桶结点时为其表示的扫描线初始化为带头结点的链表;(3)对每个桶结点进行循环, 将桶内每个结点的边表合并为有效边表, 并进行有效边表循环;(4)按照扫描线从小到大的移动顺序, 计算当前扫描线与多边形各边的交点, 然后把这些交点按X值递增的顺序进行排序, 配对, 以确定填充区间;(5)用指定颜色点亮填充区间内的所有像素, 即完成填充工作。

4.源程序:1)//AET.hclass AET{public:AET();virtual ~AET();double x;int yMax;double k;//代替1/kAET *next;};//AET..cppAET::AET(){}AET::~AET(){}2) //Bucket.h#include "AET.h"class Bucket{public:Bucket();virtual ~Bucket();int ScanLine;AET *p;//桶上的边表指针Bucket *next;};// Bucket.cppBucket::Bucket(){}Bucket::~Bucket(){}3)//TestView.h#include "AET.h"//包含有效边表类#include "Bucket.h"//包含桶类#define Number 7//N为闭合多边形顶点数, 顶点存放在整型二维数组Point[N]中class CTestView : public CView{。

多边形填充算法-有序边表法(扫描线算法)

多边形填充算法-有序边表法(扫描线算法)

多边形填充算法-有序边表法(扫描线算法)1.算法的基本思想(扫描线连贯性原理): 对于⼀个给定的多边形,⽤⼀组⽔平(垂直)的扫描线进⾏扫描,对每⼀条扫描线均可求出与多边形边的交点,这些交点将扫描线分割成落在多边形内部的线段和落在多边形外部的线段;并且⼆者相间排列。

于是,将落在多边形内部的线段上的所有象素点赋以给定的⾊彩值。

算法中不需要检验每⼀个象素点,⽽只考虑与多边形边相交的交点分割后的扫描线段。

2.算法求解:对于每⼀条扫描线的处理:1)求交点:⾸先求出扫描线与多边形各边的交点;2)交点排序:将这些交点按X坐标递增顺序排序;3)交点匹配:即从左到右确定落在多边形内部的那些线段;4)区间填充:填充落在多边形内部的线段。

3.求交点的⽅法最简单的办法:将多边形的所有边放在⼀个表中,在处理每条扫描线时,从表中顺序取出所有的边,分别求这些边与扫描线的交点。

不使⽤该⽅法的原因:将做⼀些⽆益的求交点动作,因为扫描线并不⼀定与多边形的边相交,扫描线只与部分甚⾄较少的边相交;因此,在进⾏扫描线与多边形边求交点时,应只求那些与扫描线相交的边的交点。

确定与扫描线相交的边:⽤边表来确定哪些边是下⼀条扫描线求交计算时应该加⼊运算的。

4.边表(ET):ET的意义在于为扫描线提供待加⼊的新边信息。

建⽴边的分类表ET(Edge Table),每个结点结构如下:(Ymax ,ΔX ,X Ymin,)Ymax:边的最⼤Y值;ΔX:从当前扫描线到下⼀条扫描线之间的X增量(dX/ dY);X Ymin:边的下端点的X坐标;next:指针,指向下⼀条边。

边的分类表可以这样建⽴:先按下端点的纵坐标(y值)对所有边作桶分类,再将同⼀组中的边按下端点X坐标递增的顺序进⾏排序, X坐标还相同的按ΔX递增的顺序进⾏排序。

5.活性边表AET把与当前扫描线相交的边称活化边AEL(Active Edge List) 。

组成的表称为活性表AET,其数据域组成如下:Ymax :存放边的上端点Y坐标;X :边与当前扫描线交点的X坐标;ΔX ,next指针:同边表。

计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验

《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:四连通区域种子填充算法实验时间:2016年12月8日实验地点:信息学院2204实验目的:掌握种子填充算法的原理,并会用种子填充算法和opengl并结合使用c++语言编写程序绘制多边形。

实验原理:种子填充算法又称为边界填充算法。

其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。

如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止.内点的检测条件:if(interiorColor!=borderColor&&interiorColor!=fillColor)。

种子填充算法常用四连通域和八连通域技术进行填充操作。

从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。

用这种方法填充的区域就称为四连通域;这种填充方法称为四向连通算法。

从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素.用这种方法填充的区域就称为八连通域;这种填充方法称为八向连通算法。

一般来说,八向连通算法可以填充四向连通区域,而四向连通算法有时不能填充八向连通区域。

四向连通填充算法:a) 种子像素压入栈中;b) 如果栈为空,则转e);否则转c);c) 弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;d) 转b);e) 结束。

四连通填充算法利用到了递归的思想。

本实验只包括四连通填充算法程序代码:#include〈glut。

h>#include〈stdlib.h〉#include〈math。

h>#include〈windows。

h〉void init(void){ glClearColor(1。

0,1.0,1。

0,0。

0); glMatrixMode(GL_PROJECTION);gluOrtho2D(0。

计算机图形学作业实验报告

计算机图形学作业实验报告

计算机图形学实验报告班级:学号:姓名:指导教师:完成日期:实验一:多边形填充一、实验目的了解多边形属性,熟悉相关函数的调用。

二、实验内容步骤和实现:首先进行初始化工作,进行显示模式(单缓冲区)和窗口等设定,主要实现根据两个函数,一个是指定场景绘制函数,glutDisplayFunc(Paint),paint函数中设置了两个三角形,一个填充,一个不填充。

用到了启用多边形点画模式glEnable(GL_POL YGON_STIPPLE)的函数,和指定多边形点画模式(填充) glPolygonStipple(fly)的函数。

另外一个就是循环执行OpenGl命令的glutMainLoop()函数。

三、实验结果四、源程序// POL Y_STIPPLE.C#include <gl/glut.h>void makeObject() // 定义一个三角形{ glBegin(GL_TRIANGLES); // 开始定义三角形// 按逆时针方向指定三角形的顶点坐标glVertex2f(-0.95, -0.95);glVertex2f(0.95, -0.95);glVertex2f(0, 0.95);glEnd(); // 三角形定义结束}void display(){ GLsizei w = glutGet(GLUT_WINDOW_WIDTH); // 程序窗口宽度GLsizei h = glutGet(GLUT_WINDOW_HEIGHT); // 程序窗口高度GLubyte fly[] = // 第二个三角形点画模式的mask值{ 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // 0X03, 0X80, 0X01, 0XC0, 0X06, 0XC0, 0X03, 0X60, //0X04, 0X60, 0X06, 0X20, 0X04, 0X30, 0X0C, 0X20, //0X04, 0X18, 0X18, 0X20, 0X04, 0X0C, 0X30, 0X20, //0X04, 0X06, 0X60, 0X20, 0X44, 0X03, 0XC0, 0X22, //0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22, //0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22, //0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22, //0X66, 0X01, 0X80, 0X66, 0X33, 0X01, 0X80, 0XCC, //0X19, 0X81, 0X81, 0X98, 0X0C, 0XC1, 0X83, 0X30, //0X07, 0XE1, 0X87, 0XE0, 0X03, 0X3F, 0XFC, 0XC0, //0X03, 0X31, 0X8C, 0XC0, 0X03, 0X33, 0XCC, 0XC0, //0X06, 0X64, 0X26, 0X60, 0X0C, 0XCC, 0X33, 0X30, //0X18, 0XCC, 0X33, 0X18, 0X10, 0XC4, 0X23, 0X08, //0X10, 0X63, 0XC6, 0X08, 0X10, 0X30, 0X0C, 0X08, //0X10, 0X18, 0X18, 0X08, 0X10, 0X00, 0X00, 0X08 };glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区glViewport(0, 0, w / 2, h); // 第一个视口,显示第一个三角形glColor3f(1, 1, 1); // 设置颜色,白色,默认值makeObject(); // 第一个三角形glViewport(w / 2, 0, w / 2, h); // 第二个视口,显示第二个三角形glColor3f(1, 0, 0); // 设置颜色,红色glEnable(GL_POL YGON_STIPPLE); // 启用多边形点画模式glPolygonStipple(fly); // 指定多边形点画模式(填充)makeObject(); // 第二个三角形glDisable(GL_POL YGON_STIPPLE); // 关闭多边形点画模式glFlush(); // 强制OpenGL命令序列在有限的时间内完成执行}int main(){ glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);// 设置程序窗口的显示模式(单缓冲区、RGBA颜色模型)glutInitWindowPosition(100, 100); // 程序窗口的位置glutInitWindowSize(300, 150); // 程序窗口的大小glutCreateWindow("一个填充多边形的例子!"); // 窗口的标题glutDisplayFunc(display); // 指定场景绘制函数glutMainLoop(); // 开始循环执行OpenGL命令}实验二:基本图元绘制二、实验目的了解OpenGL图形软件包绘制图形的基本过程及其程序框架,并在已有的程序框架中添加代码实现直线和圆的生成算法,演示直线和圆的生成过程,从而加深对直线和圆等基本图形生成算法的理解。

第4章多边形填充算法

第4章多边形填充算法

E2
E5
E3 E4
边缘填充算法示意图
1.边缘填充算法(正负相消法) 基本原理是:对每一条扫描线,依次求与多边形各边 的交点,将该扫描线上交点右边的所有像素求补。多 边形所有边处理完毕,填充即完成。
优点:简单易行 缺点:多边形外的像素处 理过多,输入输出量大
算法改进
• ቤተ መጻሕፍቲ ባይዱ围盒 • 栅栏
带包围盒的多边形
第4章 多边形填充算法
4.3 边缘填充算法
4.3.1 填充原理
• 求出多边形的每条边与扫描线的交点 • 将交点右侧的所有像素颜色全部取为补
色。 • 按任意顺序处理完多边形的所有边。
4.3.2 填充过程
假定边的访问顺序为E0、E1、E2、E3、E4、E5和E6。
P1(x1,y1)
E1
E0
E6
P0(x0,y0)
缺点:某些像素被重复取补
3.边标志填充算法
基本思想:先用一种特殊的颜色在帧缓存中将多边形 的边界(水平边除外)勾画出来,然后将着色的像素点依x 坐标递增的顺序两两配对,再将每一对像素所构成的扫描线 区间内的所有像素置为填充色。
3.边标志填充算法
①打标记:对多边形边界所在像素置一个特殊标志。按照 “下闭上开”的原则处理局部最低点为两个交点,局部 最高点为0个交点。
② 填充:对于每条与多边形相交的扫描线,依照“左闭 右开”的原则从左至右逐个访问该扫描线上的像素,并 着色。
3.边标志填充算法
栅栏填充算法
栅栏:一条过多边形顶点且与扫描线垂直的直线,它将 多边形分成两半,只要将栅栏与多边形之间的像素求补 即可。
缺点:某些像素被重复取补
栅栏填充算法
基本原理:对于每条扫描线与多边形的交点,将交点与栅栏 之间的扫描线上的像素取补,也就是说,若交点位于栅 栏左边,则将交点之右、栅栏之左的所有像素取补;若 交点位于栅栏右边,则将栅栏之右、交点之左的所有像 素取补。

计算机图形学学习报告

计算机图形学学习报告

《计算机图形学》课程学习报告班级学号:102055208学生姓名:牛慧敏一、算法名称多边形边缘填充算法二、算法理论知识1) 根据示例多边形顶点坐标值,计算多边形的最大、最小x 坐标,最大、最小y 坐标。

2) 使用CLine 类对象绘制多边形及其包围盒。

3) 填充色FClr 为调色板上取得的颜色,背景色BCr 为白色。

4) 对于每一条边,y 从ymin 开始,执行下面的循环。

5) X 从扫描线与边的交点处开始到包围盒右边界,先获得(x,y)位置的像素颜色,如果是填充色,则置为背景色,否则使用填充色填充,执行x=x+1/k,计算下一个扫描线与边交点的x 坐标。

6) 如果y=ymin ,则结束循环,否则y+1后转(5)。

三、算法功能说明1) 绘制示例多边形及其包围盒。

2) 用于填充示例多边形。

四、算法程序流程图否 是五、算法执行结果绘制多边形 读取多边形点表,并保存需要填充的颜色是否填充填充多边一、算法名称金刚石图案算法二、算法理论知识1) 读入圆的等分点的个数n 与圆的半径r 。

2) 根据等分点个数计算金刚是图案的等分角θ=2π/n 。

3) 计算金刚石图案的起始角α=π/2-θ。

α是用于调整金刚石图案的起始位置。

4) 将园等分后的定点坐标存储于数组P 中。

5) 设计一个二重循环,代表起点的外层整型变量j 从j=i+1循环到j=n-1.以p[i]为起点,以p[j]为终点连接各线段构成金刚石图案。

三、算法功能说明1) 可以自定义圆的等分点个数和圆的半径,并绘制金刚石的图案。

2) 自定义屏幕二位坐标系,原点位于客户区中心,x 轴水平向右为正,y轴垂直向上为正。

以二位坐标系原点为圆心绘制半径为r 的圆,将圆的n 等分点使用直线段批次连接形成金刚石图案。

四、算法程序流程图五、算法执行结果输入圆的等分点个数n 和圆的半径人r 确定坐标系的原点 计算等分点坐标,依次各连接等分点,则金刚石图案绘制完成 5<N<50 &&200<r<500 否 是。

多边形的边缘填充算法

多边形的边缘填充算法

多边形的边缘填充算法1.实验目的:在一个区域的内部填上不同的灰度或色彩2试验步骤:实验基本思想:逐边向右求补。

可以按任意顺序处理多边形的每条边。

在处理每条边时,首先求出该边与扫描线的交点,然后将每一条扫描线上交点右方的所有像素取补。

多边形的所有边处理完毕之后,填充即完成。

3实验程序(算法思想):1、找出扫描线的范围2、建立边角桶(1)建立空桶(2)遍历多边形各边,根据边的r较小端输入桶中。

3、扫描填充#include "ggltools.h"void gltRasterText(double x, double y, const char *text, void *font){if(text == NULL) return ;glRasterPos2d(x, y);for(int i=0; text[i] != '\0'; i++){glutBitmapCharacter(font, text[i]);}}void gltLine2d(double x0, double y0, double x1, double y1){glBegin(GL_LINES);glVertex2d(x0, y0);glVertex2d(x1, y1);glEnd();}void gltRect2d(double x0, double y0, double x1, double y1)glBegin(GL_LINE_STRIP);glVertex2d(x0, y0);glVertex2d(x1, y0);glVertex2d(x1, y1);glVertex2d(x0, y1);glVertex2d(x0, y0);glEnd();}char gltClipCode(const GPoint2d &pt, const GPoint2d &top, const GPoint2d &bottom) {char code = 0;if(pt.y() > top.y()) code |= 0x01;else if(pt.y() < bottom.y()) code |= 0x02;if(pt.x() > bottom.x()) code |= 0x04;else if(pt.x() < top.x()) code |= 0x08;return code;}template <class T>void swap(T &a , T &b){T t =a;a=b;b=t;}bool gltLineClip2d(GPoint2d &pt0, GPoint2d &pt1,const GPoint2d &top, const GPoint2d &bottom){char c0,c1;double x,y;while (true){c0=gltClipCode(pt0,top,bottom);c1=gltClipCode(pt1,top,bottom);if (c0 & c1) return false;if (c0==0&&c1==0)return true;if(c0==0){swap(pt0,pt1);swap(c0,c1);}if(c0 & 0x01)//点在yt 上方;{y=top.y();x=pt0.x()+(y-pt0.y())*(pt1.x()-pt0.x())/(pt1.y()-pt0.y());}else if (c0 & 0x02){y=bottom.y();x=pt0.x()+(y-pt0.y())*(pt1.x()-pt0.x())/(pt1.y()-pt0.y());}else if(c0 & 0x04){x=bottom.x();y=pt0.y()+(x-pt0.x())*(pt1.y()-pt0.y())/(pt1.x()-pt0.x());}else if(c0 & 0x08){x=top.x();y=pt0.y()+(x-pt0.x())*(pt1.y()-pt0.y())/(pt1.x()-pt0.x());}pt0.set(x,y);}return false;}4.实验输出结果:。

(计算机图形学)多边形区域扫描线填充或种子填充

(计算机图形学)多边形区域扫描线填充或种子填充

实验2:多边形区域扫描线填充或种子填充实验类型:验证、设计所需时间:3学时主要实验内容及要求:实现多边形区域扫描线填充的有序边表算法,并将实现的算法应用于任意多边形的填充,要求多边形的顶点由键盘输入或鼠标拾取,填充要准确,不能多填也不能少填。

要求掌握边形区域扫描线填充的有序边表算法的基本原理和算法设计,画出算法实现的程序流程图,使用C或者VC++实现算法,并演示。

参考试验步骤:1)分析多边形区域扫描线填充算法的原理,确定算法流程①初始化:构造边表,AET表置空②将第一个不空的ET表中的边插入AET表③由AET表取出交点进行配对(奇偶)获得填充区间,依次对这些填充区间着色④y=y i+1时,根据x=x i+1/k修改AET表所有结点中交点的x坐标。

同时如果相应的ET表不空,则将其中的结点插入AET表,形成新的AET表⑤AET表不空,则转(3),否则结束。

2)编程实现①首先确定多边形顶点和ET/AET表中结点的结构②编写链表相关操作(如链表结点插入、删除和排序等)③根据1)中的算法结合上述已有的链表操作函数实现多边形区域扫描线填充的主体功能④编写主函数,测试该算法源代码:#include<gl/glut.h>#include<iostream>using namespace std;typedef struct dePt{int x;int y;}dePt;void fill(GLint x1,GLint y1,GLint z1){glBegin(GL_POINTS);glVertex3f(x1,y1,0.0f);glEnd();}typedef struct Edge{int yUpper;float xIntersect, dxPerScan;struct Edge *next;}Edge;void insertEdge(Edge *list, Edge *edge){Edge *p,*q=list;p=q->next;while(p!=NULL){if(edge->xIntersect<p->xIntersect)p=NULL;else{q=p;p=p->next;}}edge->next=q->next;q->next=edge;}int yNext(int k, int cnt, dePt*pts){int j;if((k+1)>(cnt-1))j=0;elsej=k+1;while(pts[k].y==pts[j].y)if((j+1)>(cnt-1))j=0;else j++;return (pts[j].y);}void makeEdgeRec(dePt lower, dePt upper,int yComp,Edge *edge,Edge *edges[]) {edge->dxPerScan=(float)(upper.x-lower.x)/(upper.y-lower.y);edge->xIntersect=lower.x;if(upper.y<yComp)edge->yUpper=upper.y-1;elseedge->yUpper=upper.y;insertEdge(edges[lower.y],edge);}void buildEdgeList(int cnt,dePt *pts,Edge *edges[]){Edge *edge;dePt v1,v2;int i,yPrev=pts[cnt-2].y;v1.x=pts[cnt-1].x;v1.y=pts[cnt-1].y;for(i=0;i<cnt;i++){v2=pts[i];if(v1.y!=v2.y){edge=(Edge *)malloc(sizeof(Edge));if(v1.y<v2.y)makeEdgeRec(v1,v2,yNext(i,cnt,pts),edge,edges);elsemakeEdgeRec(v2,v1,yPrev,edge,edges);}yPrev=v1.y;v1=v2;}}void buildActiveList(int scan,Edge *active,Edge *edges[]) {Edge *p,*q;p=edges[scan]->next;while(p){q=p->next;insertEdge(active,p);p=q;}}void fillScan(int scan,Edge *active){Edge *p1,*p2;int i;p1=active->next;while(p1){p2=p1->next;for(i=p1->xIntersect;i<p2->xIntersect;i++)fill((int)i,scan,3);p1=p2->next;}}void deleteAfter(Edge *q){Edge *p=q->next;q->next=p->next;free(p);}void updateActiveList(int scan,Edge *active) {Edge *q=active, *p=active->next;while(p)if(scan>=p->yUpper){p=p->next;deleteAfter(q);}else{p->xIntersect=p->xIntersect+p->dxPerScan; q=p;p=p->next;}}void resortActiveList(Edge *active){Edge *q,*p=active->next;active->next=NULL;while(p){q=p->next;insertEdge(active,p);p=q;}}void scanFill(int cnt,dePt *pts){Edge *edges[1024],*active;int i,scan;for(i=0;i<1024;i++){edges[i]=(Edge *)malloc(sizeof(Edge)); edges[i]->next=NULL;}buildEdgeList(cnt,pts,edges);active=(Edge *)malloc(sizeof(Edge)); active->next=NULL;for(scan=0;scan<1024;scan++)buildActiveList(scan,active,edges);if(active->next){fillScan(scan,active);updateActiveList(scan,active);resortActiveList(active);}}}void ChangeSize(GLsizei w,GLsizei h){GLfloat nRange=400.0f;if(h==0) h=1;glViewport(0,0,w,h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w<=h)glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-nRange,nRange);elseglOrtho(-nRange*h/w,nRange*h/w,-nRange,nRange,-nRange,nRange); glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void Display(void){glClear(GL_COLOR_BUFFER_BIT);glLineWidth(5.0);int n,x,y,i;cout<<"请输入多边形顶点数:"<<endl;cin>>n;dePt *t=new dePt[n];for(i=0;i<n;i++){cout<<"请输入第"<<i+1<<"个顶点坐标"<<endl;cin>>x>>y;t[i].x=x;t[i].y=y;glVertex2i(t[i].x,t[i].y);} glEnd();glFlush();scanFill(n,t);glFlush();}void SetupRC()glClearColor(1.0f,1.0f,1.0f,1.0f); glColor3f(1.0f,0.0f,0.0f);}实验结果:。

计算机图形学-实验报告2-多边形有效边表填充算法

计算机图形学-实验报告2-多边形有效边表填充算法
(8)循环下一甬结点,按照xi+1=xi+k修改有效边表,同时合并甬结点内的新边表,形成新的有效边表。
(9)如果甬结点的扫描线值大于等于有效边表中的结点值ymax,则该边为无效边。
(10)当甬结点不为空则转(6)否则删除甬表和边表的头结点,算法结束。
(11)实验结果及分析:
实验地点
软件实验室
指导教师
(3)动态链表的排序算法
二、实验内容:
三、自定义屏幕二维坐标系,原点位于客户区中心,x轴水平向右为正,y轴垂直向上为正。
四、在屏幕客户区内使用cline类绘制示例多边形边界。
五、设置屏幕背景色为白死,调用windows的颜色对话框选择填充色使用单一颜色填充多边形。
六、使用有效边表填充算法填充示例多边形内部及边界。
(5)对每个甬结点链接的边表,根据x|ymin值的大小进行排序,若x|ymin相等,则按照k由小到大排序。
(6)循环访问每个甬结点,将甬内每个结点的边表合并成有效边表,并循环访问有限边表。
(7)从有效边表中取出扫描线上相邻两条边的结点对进行配对。填充时设置一个逻辑变量binflag,每访问一个结点,把binflag值取反一次,若binflag为真,则把从当前结点的x值开始到下一结点x值结束的区间用指定的颜色填充。
七、实验步骤:
(1)调用颜色对话框读取填充色。
(2)根据示例多边形顶点坐标值,计算扫描线的最大值ScanMax和最小值ScanMin。
(3)用多边形覆盖的扫描线动态建立甬结点。
(4)循环访问多边形的所有顶点,根据边的顶点y值比起点y值高或边的终点y值比起点y值低两种情况,计算每条边的ymin。在甬中寻找与该ymin相对应的甬结点计算该边表示的x|ymin,ymax,k,并依据次链接该边表结点到甬结点。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4.水平边在算法中不起任何作用,可不考虑。
活性边表(提高效率):
为了减少求交的计算量,要利用一条边与相继的两条扫描线的交点的连贯性。在处理一条扫描线时只对活性边(与它相交的多边形的边)进行求交运算。把交点按x增加方向存在一个链表(活性边表)中。
活性边:与当前扫描线相交的边。
活性边表(AEL):按交点x的增量顺序存放在一个链表中,该链表称作活性边表(AEL)。
贵州大学实验报告
学院:计算机科学与信息学院 专业:计算机科学与技术 班级:101姓名 Nhomakorabea学号
实验组
4
实验时间
2013.4.25
指导教师
吴云
成绩
实验项目名称
多边形填充算法
实验目的
使学生掌握光栅显示系统中多边形的扫描转换和区域填充算法。掌握4连通区域的扩展性。
实验要求
实现多边形的扫描转换算法和区域填充算法
实验原理
pty = y;
{
x++;
}
}
x = xl;
y = y - 2;
while(x <= xr)
{
spanNeedFill =false;
while(bitmap.GetPixel(g, x, y) == oldColor)
{
spanNeedFill =true;
x++;
}
if(spanNeedFill)
{
ptx = x - 1;
myStack.Clear();
intptx = x;
intpty = y;
myStack.Push(ptx);
myStack.Push(pty);
while(myStack.Count != 0)
{
pty = (int)myStack.Pop();
ptx = (int)myStack.Pop();
{
if ("".Equals(txtx.Text) || "".Equals(txty.Text))
{
return;
}
else
{
x = Convert.ToInt32(txtx.Text);
y = Convert.ToInt32(txty.Text);
}
intxl, xr;
boolspanNeedFill;
–求出扫描线与多边形所有边的交点;
–把这些交点的x坐标值以升序排列;
–对每一对交点间的区域进行填充。
–第三个步骤是从奇数个交点出发到偶数个交点。如右图,对y=8的扫描线排序x坐标得到的表是(2,4,9,13),然后对交点2与4之间、9与13之间的所有象素点进行填充。
几点规则:
边界上的象素:“左闭右开”,“下闭上开”(将左边界和下边界的点算为内部,而将右边界和上边界算为外部)
利用相邻像素之间的连贯性,提高算法效率。根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。
处理对象:非自交多边形(边与边之间除了顶点外无其它交点)
判断扫描线上的点是否在多边形之内,根据多边形区域连续性,分为3个步骤:
顶点:“上开下闭”。
几种特殊情况:
1.扫描线交于一顶点,共享的两条边分另处于扫描线的两边,这时交点只取一个,如扫描线y=3,该点被填充一次。
2.共享交点的两条边处于扫描线的上方,这时交点取二个,如扫描线y=1,该点被填充一次。
3.共享交点的两条边处于扫描线的下方,这时交点取0个,如扫描线y=9,无交点,不填充。
x = ptx;
y = pty;
while(bitmap.GetPixel(g, x, y) == oldColor)
{
bitmap.SetPixel(g, x, y,ColorTranslator.ToWin32(newColor));
x++;
}
xr = x - 1;
x = ptx - 1;
while(bitmap.GetPixel(g, x, y) == oldColor)
1、四向连通区域:各象素在水平垂直四个方向是边通的。即从区域内任一点出发,可水平/垂直移动到达区域内任一点。
2、八向连通区域:各象素在水平、垂直、及四个对角线方向都是是边通的。即从区域内任一点出发,可水平、垂直、及四个对角线方向移动到达区域内任一点。
测试对象为象素段 ,对区域内的每一象素段,只保留其最右边(或左边)的象素作为种子象素.区域填充(扫描线算法):
–目标:减少递归层次
–适用于内点表示的4连通区域
基本过程:
当给定种子点时,首先填充种子点所在的扫描线上的位于给定区域的一个区段,然后确定与这一区段相通的上下两条扫描线上位于给定区域内的区段,并依次保存下来。反复这个过程,直到填充结束。
算法步骤:
1、填充并确定种子区段;
2、初始化:将种子区段压入堆栈;
种子填充算法首先假定区域由封闭轮廓线围成,且轮廓线内某点是已知的,然后开始搜索与种子点相邻且位于轮廓线内的点。如果这相邻 点不在轮廓线内,则已达到轮廓线的边界;如果相邻点在轮廓线之内,则这相邻点成为新的种子点,继续搜索下去。只适用于光栅扫描设备。
区域分类(区域采用边界定义,即区域边界上与边界外的象素取相同值,区域内部的点取不同值)
3、出栈:如果堆栈为空,则算法结束;否则取栈顶元素y,xLeft,xRight),以纵坐标为y的扫描线为当前扫描线,[xLeft, xRight]为搜索区间;
4、填充并确定新的区段 。
扫描线种子填充:
publicvoidFillField(intx,inty,ColornewColor,uintoldColor,Graphicsg)
{
bitmap.SetPixel(g, x, y,ColorTranslator.ToWin32(newColor));
x--;
}
xl = x + 1;
x = xl;
y = y + 1;
while(x <= xr)
{
spanNeedFill =false;
while(bitmap.GetPixel(g, x, y) == oldColor)
{
spanNeedFill =true;
x++;
}
if(spanNeedFill)
{
ptx = x - 1;
pty = y;
myStack.Push(ptx);
myStack.Push(pty);
spanNeedFill =false;
}
while(bitmap.GetPixel(g, x, y) != oldColor && x <= xr)
相关文档
最新文档