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

} /* polyfill */
桶结构
用于存放按照一定的规则(顺序)排列的若 干组数据或处理对象。
通常情况下,桶采用向量形式和链表形式构 造的一种数据结构。
6.边界标志算法
边界标志算法的基本思想是:在帧缓冲器中 对多边形的每条边进行直线扫描转换,亦即对多 边形边界所经过的象素打上标志。然后再采用和 扫描线算法类似的方法将位于多边形内的各个区 段着上所需颜色。对每条与多边形相交的扫描线 依从左到右的顺序,逐个访问该扫描线上的象素。 使用一个布尔量inside来指示当前点是否在多边形 内的状态。Inside的初值为假,每当当前访问的 象素为被打上边标志的点,就把inside取反。对未 打标志的象素,inside不变。若访问当前象素时, inside为真,说明该象素在多边形内,则把该象素 置为填充颜色。
扫描线6的活性边表 扫描线7的活性边表
为了方便活性边表的建立与更新,我们为 每一条扫描线建立一个新边表(NET),存放 在该扫描线第一次出现的边。也就是说,若 某边的较低端点为ymin,则该边就放在扫描 线ymin的新边表中。
扫描线多边形填充算法的主要步骤
▪ 建立NET(NewEdgeList) ▪ 从最低扫描线开始到最高扫描线循环: ➢ 建立或调整AET(ActiveEdgeList); ➢ 按照AET中的接点顺序填充;
准备工作: typedef struct { int x,y;} seed; typedef struct { seed s[6400];int top;} seedstack;
VC++程序实现
可以直接利用函数的递归调用来实现.
设(x,y)为内点表示的4连通区域内的一点, oldcolor为区域的原色,要将整个区域填充为新 的颜色newcolor。
计算机图形学图形区域填充效果

// Fill.cpp : implementation file
#include "stdafx.h"
#include "FloodFill.h"
#include "Fill.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
(1)种子填充算法原理
在多边形内部找到一个已知的象素点作为种子点,由此开始,利用区域的连通性找到多边形内部的 其它所有象素点进行填充。
(i)四向连通区域
①四向连通区域概念:从区域上任一点出发,在不超出区域边界的前提下,可通过4个方向:上、下、左、右的移动组合到达区域中的任意象素点,称此区域为四向连通区域。
{
//有需要填充的区域
if(spanNeedFill==FALSE)
{
spanNeedFill = TRUE;
}
x++;
}
if(spanNeedFill)
{
CPoint rightp(x-1,y);
stack.Push(x-1);
stack.Push(y);
spanNeedFill = FALSE;
virtual ~CStack();
};
#endif // !defined(AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_)
CStack.cpp参考代码:
// Stack.cpp: implementation of the CStack class.
#if !defined(AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_) #define AFX_STACK_H__D198F788_4ED1_4C09_98E5_433BAB24D864__INCLUDED_
fill相关知识点

填充(Fill)相关知识点填充(Fill)是一种常见的计算机图形学技术,用于在图像或物体的内部或边界区域中填充颜色或纹理。
填充技术在许多领域中被广泛应用,如图像处理、计算机辅助设计(CAD)和计算机游戏开发等。
本文将介绍填充相关的知识点,从基本原理到常见算法,让读者对填充技术有一个全面的了解。
基本原理填充技术的基本原理是通过某种规则或算法,在给定的区域内部或边界上填充颜色或纹理。
这个区域可以是一个简单的几何形状,如矩形或圆形,也可以是一个复杂的多边形。
填充通常从区域内部的某个点开始,按照一定的规则或算法进行扩散,直到填充满整个区域。
基本算法以下是一些常见的填充算法:扫描线填充算法扫描线填充算法是一种基于扫描线的填充方法。
它通过将扫描线与区域的边界进行比较,确定扫描线与区域的交点,并根据规则填充扫描线上的像素。
该算法的优点是简单易懂,并且适用于任意形状的区域。
边界填充算法边界填充算法是一种基于区域边界的填充方法。
它通过检测区域的边界像素,并根据规则填充区域内部的像素。
该算法的优点是填充效果清晰,但对于复杂的区域边界可能会存在一些问题。
种子填充算法种子填充算法是一种基于种子点的填充方法。
它通过选择一个种子点作为起始点,并按照一定的规则或算法进行扩散填充。
种子填充算法适用于复杂的区域填充,但可能存在堆栈溢出的问题。
填充的应用领域填充技术在许多领域中都有广泛的应用,以下是其中一些常见的应用领域:图像处理在图像处理中,填充技术可以用于图像的增强、修复和合成等方面。
例如,可以使用填充技术修复图像中的缺陷、填充图像的边界以及合成多个图像。
计算机辅助设计(CAD)在计算机辅助设计中,填充技术可以用于填充图形对象的内部或边界,以增加图形的真实感和细节。
例如,可以使用填充技术填充建筑物的内部、道路的纹理以及地形的颜色。
计算机游戏开发在计算机游戏开发中,填充技术可以用于填充游戏场景的地形、角色的纹理以及特效的颜色。
通过使用填充技术,可以使游戏画面更加精美和逼真。
多边形填充算法

多边形填充算法
多边形填充算法是一种计算机图形学中的算法,用于将一个封闭的多边形区域(如矩形、三角形、梯形等)填充成指定的颜色。
在计算机图形学中,多边形是由一系列线段(边)连接成的封闭区域。
填充算法的目的是在多边形的内部填充指定的颜色。
这种算法通常用于计算机辅助设计、计算机游戏开发、计算机动画、计算机视觉等领域。
填充算法有多种实现方法,包括扫描线填充、种子填充、边界填充、区域分割等。
其中,扫描线填充是最常见的一种算法,它的基本思想是从多边形的最上面一行开始,逐行向下扫描,同时记录扫描线和多边形之间的交点。
当扫描线与多边形的边相交时,根据交点的奇偶性来判断该点是否在多边形内部。
如果是奇数个交点,则该点在多边形内部,需要进行填充;如果是偶数个交点,则该点在多边形外部,不需要填充。
种子填充是另一种常见的填充算法,它的基本思想是从多边形内部的一个点(种子)开始,向外扩散填充。
在扩散过程中,同时记录已经填充过的像素点,避免重复填充。
这种算法的优点是填充速度较快,但容易出现填充区域不封闭、填充效果不理想等问题。
边界填充和区域分割是另外两种填充算法,它们的实现方式比较复杂,但可以处
理比较复杂的填充情况,例如多个子多边形共同填充、奇异多边形填充等。
总的来说,多边形填充算法在计算机图形学中具有重要的应用价值和研究意义,不同的填充算法各有优缺点,需要根据具体的需求和应用场景来选择合适的算法。
计算机图形学 区域填充算法的实现

实验四区域填充算法的实现班级 08信计2班学号 20080502088 姓名许延恒分数一、实验目的和要求:1、理解区域的表示和类型。
2、能正确区分四连通和八连通的区域3、了解区域填充的实验原理。
4、利用C++实现区域填充的递归算法。
二、实验内容:1假设在多边形内有一像素已知,由此出发利用连通性找到区域内所有像素。
2 取(x,y)为种子点将整个区域填充为新的颜色。
3 进行递归填充。
三、实验结果分析区域填充属性包括填充样式,填充颜色和填充图案的类型。
C语言中定义了某种图形后,即可调用-floodfill函数,对指定区域进行填充. 程序代码#include<graphics.h>#include<conio.h>#include<time.h>void floodfill4(int x,int y,int oldcolor,int newcolor){if(getpixel(x,y)==oldcolor){putpixel(x,y,newcolor);Sleep(1);floodfill4(x,y+1,oldcolor,newcolor);floodfill4(x,y-1,oldcolor,newcolor);floodfill4(x-1,y,oldcolor,newcolor);floodfill4(x+1,y,oldcolor,newcolor);}}main(){int a,b,c,d,i,j;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode,"");cleardevice();setcolor(RED); rectangle(50,50,70,100); for(i=51;i<70;i++)for(j=51;j<100;j++) {putpixel(i,j,4);}a=57;b=70;c=4;d=RGB(0,255,0); floodfill4(a,b,c,d); getch();closegraph();}。
计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验————————————————————————————————作者: ————————————————————————————————日期:ﻩ《计算机图形学实验》报告任课教师:钱文华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);后的结果如下图:实验总结:通过多组数据的测试,知道了上面算法的正确,普适性。
计算机图形学第3讲多边形区域填充算法

40
种子填充算法
栈实现的种子填充算法(四向算法)
void BoundaryFill4(int x, int y, int boundColor, int newColor) { int px = x, py = y; stackPush(px, py); while(!stackEmpty()) { stackPop(&px, &py); SetPixel(x, y, newColor);
扫描转换算法
区域填充算法
34
种子填充算法
区域:点阵表示的图形,像素集合 表示方法
内点表示 区域内的所有像素具有同一颜色,而区域外的所有像素具有另 一种颜色 边界表示 区域边界上的所有像素具有特定的颜色(可以是填充色),在 区域内的所有像素均不能具有这一特定颜色,而且边界外的像 素也不能具有与边界相同的颜色
若低端点y值为ymin,则该边就放在ymin所对应的桶中
桶中的各边:
按下端点的x坐标值排序
27
12 10(2,9) l3 8 6 4 2 l2 l4
(13,11) l5 (13,5) l6
(7,7)
(2,3) (7,1) l1 2 4
9 11 9 3 ∧ ∧
6
8 10 12 14
7 3/2 11
扫描线算法
取整问题
扫描线与多边形边界交点坐标值不为整数 当扫描线与多边形边界交点坐标为小数值时,如果多 边形在此边界右侧,则将该小数值进1作为边界点,否 则舍去小数部分并进行填充,这样可使多边形不扩大
解决方法
16
扫描线算法
水平边问题
计算机图形学-区域填充的扫描线算法

计算机图形学——区域填充的扫描线算法一.实验名称:区域填充的扫描线算法二.实验目的:1、理解区域填充扫描线算法的原理;2、实现区域填充的扫描线算法并测试;三.算法原理:算法基本思想: 首先填充种子点所在扫描线上位于区域内的区段,然后确定与该区段相邻的上下两条扫描线上位于区域内的区段,并依次将各区段的起始位置保存, 这些区段分别被用区域边界色显示的像素点所包围。
随后,逐步取出一开始点并重复上述过程,直到所保存各区段都填充完毕为止。
借助于栈结构,区域填充的扫描线算法之步骤如下:Step 1. 初始化种子点栈:置种子点栈为空栈,并将给定的种子点入栈;Step 2. 出栈:若种子点栈为空,算法结束;否则,取栈顶元素(x,y)为种子点;Step 3. 区段填充:从种子点(x, y) 开始沿纵坐标为y 的当前扫描线向左右两个方向逐像素点进行填色,其颜色值置为newcolor 直至到达区域边界。
分别以xl 和xr 表示该填充区段两端点的横坐标;Step 4. 新种子点入栈: 分别确定当前扫描线上、下相邻的两条扫描线上位于区段[xl, xr] 内的区域内的区段。
若这些区段内的像素点颜色值为newolor ,则转至Step 2;否则以区段的右端点为种子点入种子点栈,再转至Step 2。
四.原程序代码:/*****************************************//*4-ScanLineFill 区域填充的扫描线算法实现*//*****************************************/#include <stdio.h>#include <conio.h>#include <graphics.h>#include <malloc.h>#define Stack_Size 100 //栈的大小常量//定义结构体,记录种子点typedef struct{int x;int y;}Seed;//定义顺序栈(种子点)typedef struct{Seed Point[Stack_Size];int top;}SeqStack;//初始化栈操作void InitStack(SeqStack *&S){S=(SeqStack *)malloc(sizeof(SeqStack));S->top=-1;}//种子点栈置空;void setstackempty (SeqStack *S){S->top==-1;}//种子点栈状态检测函数int isstackempty (SeqStack *S){if(S->top==-1)return true; //空栈返回trueelsereturn false; //非空栈返回false}//种子点入栈;int stackpush (SeqStack *&S,Seed point){if(S->top==Stack_Size-1)//栈已满,返回false return false;S->top++;//栈未满,栈顶元素加1S->Point[S->top]= point;return true;}//取栈顶元素;int stackpop (SeqStack *&S,Seed &point){if(S->top==-1)//栈为空,返回falsereturn false;point=S->Point[S->top];S->top --;//栈未空,top减1return true;}//画圆void CirclePoints (int xc, int yc, int x, int y, int Color) {putpixel (xc + x, yc + y, Color);putpixel (xc + x, yc - y, Color);putpixel (xc - x, yc + y, Color);putpixel (xc - x, yc - y, Color);putpixel (xc + y, yc + x, Color);putpixel (xc + y, yc - x, Color);putpixel (xc - y, yc + x, Color);putpixel (xc - y, yc - x, Color); }//中点画圆算法void MidpointCircle(int radius, int Color) {int x, y;float d;x=0;y=radius;d=5.0/4-radius;CirclePoints(250,250,x,y,Color);while(x<y){if (d<0){d+=x*2.0+3;}else{d+=(x-y)*2.0+5;y--;}x++;CirclePoints(250,250,x,y,Color);}}//四连通扫描线算法void ScanLineFill4(int x, int y, int oldcolor, int newcolor) {int xl, xr, i;bool SpanNeedFill;Seed pt;//种子点SeqStack *S;//定义顺序栈InitStack(S);//定义了栈之后必须把栈先初始化setstackempty(S);//种子点栈置空;pt.x = x;pt.y = y;stackpush (S,pt); // 种子点(x, y)入栈while (!isstackempty(S)){stackpop (S,pt);//取种子点y = pt.y;x = pt.x;while (getpixel (x,y)==oldcolor) {// 从种子点开始向右填充putpixel (x, y, newcolor);x++;}xr = x -1;x = pt.x -1;while (getpixel (x,y)==oldcolor) { // 从种子点开始向左填充putpixel (x, y, newcolor);x--;}xl = x + 1;x = xl;y = y +1; // 处理上面一条扫描线while (x < xr){SpanNeedFill = false;while (getpixel (x, y)==oldcolor){SpanNeedFill = true;x++ ;} // 待填充区段搜索完毕if (SpanNeedFill){// 将右端点作为种子点入栈pt.x = x - 1;pt.y = y;stackpush (S,pt);SpanNeedFill = false;} //继续向右检查以防遗漏while ((getpixel (x, y)!=oldcolor) && (x< xr)) x++;} //上一条扫描线上检查完毕x = xl;y=y-2; // 处理下面一条扫描线while (x < xr){SpanNeedFill = false;while (getpixel (x, y)==oldcolor){SpanNeedFill=true;x++ ;}if (SpanNeedFill){pt.x= x - 1;pt.y = y;stackpush (S,pt);SpanNeedFill=false;}while ((getpixel (x, y)!=oldcolor) && (x < xr))x++;}}}//主函数检测void main(){int radius,color;int x,y;//种子点int oldcolor,newcolor;//原色与填充色//输入参数值printf("input radius and color:\n");//画圆参数scanf("%d,%d",&radius,&color);printf("input x and y:\n"); //读入内点scanf("%d,%d", &x, &y);printf("input oldcolor and newcolor:\n"); //读入原色与填充色scanf("%d,%d", &oldcolor, &newcolor);int gdriver = DETECT,gmode;initgraph(&gdriver, &gmode, "c:\\tc");// 用背景色清空屏幕cleardevice();// 设置绘图色为红色setcolor(RED);MidpointCircle(radius,color);//用中点画圆算法画圆rectangle(150, 150, 350, 350);//再画一个矩形区域ScanLineFill4 (x,y,oldcolor,newcolor);//扫描线区域填充getch();closegraph();}五.运行结果与讨论:测试结果1:测试结果2:六.实验分析与讨论:1.通过借助栈这一数据结构,完成了区域填充的扫描线算法的实现,并利用以前所学的画圆等算法,进行综合运用,在此基础上进行扩充,设计多种图案,进行扫描线填充算法的检测,都得到了理想的结果,体现了算法的有效性;2.栈的数据结构给种子点的操作带来了极大的方便,为算法的实现提供了便利,同时还提高了算法的复用性和可靠性;3.此扫描线填充算法能够对多种图案进行填充,展现了算法的实用性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四区域填充算法的实现
班级 08信计2班学号 20080502088 姓名许延恒分数
一、实验目的和要求:
1、理解区域的表示和类型。
2、能正确区分四连通和八连通的区域
3、了解区域填充的实验原理。
4、利用C++实现区域填充的递归算法。
二、实验内容:
1假设在多边形内有一像素已知,由此出发利用连通性找到区域内所有像素。
2 取(x,y)为种子点将整个区域填充为新的颜色。
3 进行递归填充。
三、实验结果分析
区域填充属性包括填充样式,填充颜色和填充图案的类型。
C语言中定义了某种图形后,即可调用-floodfill函数,对指定区域进行填充
. 程序代码
#include<graphics.h>
#include<conio.h>
#include<time.h>
void floodfill4(int x,int y,int oldcolor,int newcolor)
{
if(getpixel(x,y)==oldcolor)
{
putpixel(x,y,newcolor);
Sleep(1);
floodfill4(x,y+1,oldcolor,newcolor);
floodfill4(x,y-1,oldcolor,newcolor);
floodfill4(x-1,y,oldcolor,newcolor);
floodfill4(x+1,y,oldcolor,newcolor);
}
}
main()
{
int a,b,c,d,i,j;
int graphdriver=DETECT;
int graphmode=0;
initgraph(&graphdriver,&graphmode,"");
cleardevice();
setcolor(RED); rectangle(50,50,70,100); for(i=51;i<70;i++)
for(j=51;j<100;j++) {
putpixel(i,j,4);
}
a=57;
b=70;
c=4;
d=RGB(0,255,0); floodfill4(a,b,c,d); getch();
closegraph();
}。