当前位置:文档之家› 带孔多边形填充算法

带孔多边形填充算法

带孔多边形填充算法
带孔多边形填充算法

带孔多边形填充算法

带孔多边形填充算法一( 基本原理

用自上而下的每一条水平的扫描线扫描多边形,每一条扫描线被多边形分成几段,每一段要么在多边形内,要么在多边形外。在内的填充,在外的舍弃。见图1 图1

二( 基本算法

1. 水平扫描线与线段求交点

假定当前扫描线y与多边形的某一条边的交点x坐标为x,那么下一条扫描线

y-1与该边的交点不必从头算起,只要加上一个增量即可。设增量为dx,显然dx= -(x1-x0)/(y1-y0)

结果是:若y=y ,x=x,则当y=y-1时,x=x-(x1-x0)/(y1-y0) iiii

(x0,y0)

y 11 y-1 dx (x1,y1)

图2

2. 活性边与活性边表

为了提高效率,在处理一条扫描线时,仅对与它相交的多边形的边进行求交运算。我们把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表。

由于边的连贯性(即当某条边与当前扫描线相交时,它很可能也与下一条扫描

线相交),以及扫描线的连贯性(当前扫描线与各边的交点顺序与下一条扫描线与各边的交点顺序很可能相同或非常类似),在当前扫描线处理完毕之后,我们不必为

下一条扫描线从头开始构造活性边表,而只要对当前扫描线的活性边表稍作修改,即可更新得到下一条扫描线的活性边表。

例如,(见图3)

扫描线6的活性边表如下:PP,PP, PP,PP61 6554 43

扫描线4的活性边表如下:PP,PP 6143

扫描线3的活性边表如下:PP,PP (满足上闭下开的原则)。 6132

扫描线2的活性边表如下:PP,PP (满足上闭下开的原则)。 1223

y

(11,8) 9 P4

(2,7) 8 P6

7

6

5 P(5,5) 5 4

(11,3) 3 P3 P(5,1) 2 2 P(2,2) 11

4 56 78 910 11 1 2 3 0 x

图3

3(Y桶表

为了方便活性边表的建立与更新,我们为每一条扫描线建立一个新边表,存放在

该扫描线第一次出现的边。也就是说,若某边的较高端点为Y,则该边就放在扫描线maxY的新边表中。这样,当我们按扫描线从大到小顺序处理扫描线时,该边在该扫描max

线第一次出现。我们把这样的表称为Y桶表。

例如,图3的多边形可以产生以下的Y桶表。

Ymax

8 PP PP 4543

7 PPP P 6165

3 PP 32

2 PP 12

图4 : Y桶表

三(数据结构

/*多边形边表*/

typedef struct LINE{

int y; /*边所交的最高扫描线号(顶点的最大y值)*/ double x; /*当前扫描线与边的交点x值*/

double dx; /*从当前扫描线到下一扫描线之间的x增量*/ int dy; /*边的两个顶点的y差值>=0*/

struct LINE *next; /*下一条边*/

}LINE;

/*Y桶表*/

typedef struct Y_TUB{

int y; /*该桶最大值*/

struct Y_TUB *next; /*下一桶*/

struct LINE *line; /*该桶的边表*/

}Y_TUB;

/*活性边表*/

typedef struct EXP_LINE{

int y; /*当前扫描线*/

struct LINE *line; /*活性边*/

}EXP_LINE;

四(算法步骤

1( 首先生成如图4的多边形Y桶表

2( 取Y桶的Y值最大的一桶(或第一桶)的边表作为活性边表。取该桶的Y为maxmax

第一条扫描线。

3( 清除活性边表中的水平线(水平边出链)及dy=0的边。 4( 计算出交点序列,并按点列x坐标递增重排点列,由点列中奇数点依次连线到偶数点(如1-2,3-4,5-6 …),即可填充该扫描线所在行。注意在连线填充时,最右边

一点不要填充,以达到左闭右开的结果。

5( 扫描线下移,即y=y-1;

6( 修改当前活性边表,如果下一桶存在并且y值等于下一桶的Y,则在活性边表后加max

入下一桶的边表(下一桶边表入链)。

7( 重复3-6步,直到当前活性边表为空。

(注:该算法由于最后一条扫描线使活性边的dy=0而不处理,这就产生了上闭下开的结果)

多边形区域填充算法

13. 设五边形的五个顶点坐标为(10, 10),(15, 5),(12, 5),(8, 2)和(4, 5),利用多边形区域填充算法,编一程序生成一个实心图。 解:假设以上五个顶点依次对应编号A-B-C-D-E,首先计算得到ET表: 6-10 5 4 3 2 1 该多边形的AET指针的内容为: 1 AET为空 2 3 4 1 2 3 4 5 6 7 8 9 10 01234567891011121314 1516

5 6 7 8 9 10 具体编程实现如下: 第1步:(1) 根据输入的五个顶点坐标找到y 值最小的点(例如点D ,此时y=2),并找到与D 有边关系的两个顶点(此时为E 和C),在y=2处建立ET 边表记录(ymax 、xi 和m 值均可通过顶点坐标间的计算得到,例如DE 边的建立,特别注意:当D 点和E 点y 坐标值相同时,也即是DE 与x 轴平行,该边不能计入ET 边表),之后标记D 点被访问过;(2) 排除访问过的点以及和该点相关联的边,重复(1)直至将ET 表建立完善。 [注]边关系的建立可通过邻接矩阵的数据结构实现,权值可以为该矩阵行编号对应点的y 坐标值,ET 边表采用邻接表的数据结构 第2步:根据ET 表构建AET 表,并逐行完成多边形填充,具体的C++代码如下: (1) 建立头文件base_class.h ,主要是边表结点结构体和ET 边表类的实现 enum ResultCode{Success, Failure}; template struct Enode { Enode() {next=NULL;} Enode(T pymax, float pxi, float pm, Enode *pnext) { ymax=pymax; xi=pxi; m=pm; next=pnext; } T ymax, xi; //ymax 表示最大的y 值,xi 表示最底端点的x 坐标值 float m; //m 表示斜率的倒数 Enode *next; }; //定义了ET 表和AET 表中结点的结构体

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

实验题目:实验二有效边表填充算法 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.h class AET { public: AET(); virtual ~AET(); double x; int yMax; double k;//代替1/k AET *next; }; //AET..cpp AET::AET() {

} AET::~AET() { } 2) //Bucket.h #include "AET.h" class Bucket { public: Bucket(); virtual ~Bucket(); int ScanLine; AET *p;//桶上的边表指针 Bucket *next; }; // Bucket.cpp Bucket::Bucket() { } Bucket::~Bucket() { } 3)//TestView.h #include "AET.h"//包含有效边表类 #include "Bucket.h"//包含桶类 #define Number 7//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中class CTestView : public CView { 。。。。。。。。。 public: void PolygonFill();//上闭下开填充多边形 void CreatBucket();//建立桶结点桶 void Et();//构造边表 void AddEdge(AET *);//将边插入AET表 void EdgeOrder();//对AET表进行排序

《计算机图形学》试卷及答案

一、填空题(每空0.5分,共 1 0 分) 1、 计算机图形学中的图形是指由点、线、面、体等 和明暗、灰度(亮度)、色 彩等 构成的,从现实世界中抽象出来的带有灰度、色彩及形状的图或形。 2、 一个计算机图形系统至少应具有 、 、输入、输出、 等 基本功能。 3、 常用的字符描述方法有:点阵式、 和 。 4、 字符串剪裁的策略包括 、 和笔划/像素精确度 。 5、 所谓齐次坐标就是用 维向量表示一个n 维向量。 6、 投影变换的要素有:投影对象、 、 、投影线和投影。 7、 输入设备在逻辑上分成定位设备、描画设备、定值设备、 、拾取设备 和 。 8、 人机交互是指用户与计算机系统之间的通信,它是人与计算机之间各种符号和动作 的 。 9、 按照光的方向不同,光源分类为: , , 。 10、从视觉的角度看,颜色包含3个要素:即 、 和亮度。 二、单项选择题(每题 2分,共 30 分。请将正确答案的序号填在 题后的括号内) 1、在CRT 显示器系统中,( )是控制电子束在屏幕上的运动轨迹。 A. 阴极 B. 加速系统 C. 聚焦系统 D. 偏转系统 2、分辨率为1024×1024的显示器需要多少字节位平面数为16的帧缓存?( ) A. 512KB B. 1MB C. 2MB D. 3MB 3、计算机图形显示器一般使用什么颜色模型?( ) A. RGB B. CMY C. HSV D. HLS 4、下面哪个不属于图形输入设备?( ) A. 键盘 B. 绘图仪 C. 光笔 D. 数据手套 5、多边形填充算法中,错误的描述是( )。 A. 扫描线算法对每个象素只访问一次,主要缺点是对各种表的维持和排序的耗费较大 B. 边填充算法基本思想是对于每一条扫描线与多边形的交点,将其右方象素取补 C. 边填充算法较适合于帧缓冲存储器的图形系统

区域填充算法的实现

实验四区域填充算法的实现 一、实验目的和要求: 1、掌握区域填充算法基本知识 2、理解区域的表示和类型,能正确区分四连通和八连通的区域 3、了解区域填充的实现原理,利用Microsoft Visual C++ 6.0(及EasyX_2011版) 实现区域种子填充的递归算法。 二、实验内容: 1、编程完成区域填色 2、利用画线函数,在屏幕上定义一个封闭区域。 3、利用以下两种种子填充算法,填充上述步骤中定义的区域 (1)边界表示的四连通区域种子填充的实现 (2)内点表示的四连通区域种子填充的实现 4、将上述算法作部分改动应用于八连通区域,构成八连通区域种子填充算法, 并编程实现。 三、实验结果分析 1、以上各种算法相应代码及运行结果如下: 程序代码: #include #include #include void FloodFill4(int x,int y,int oldcolor,int newcolor) { if(getpixel(x,y)==oldcolor) { putpixel(x,y,newcolor); Sleep(1); FloodFill4(x-1,y,oldcolor,newcolor); FloodFill4(x,y+1,oldcolor,newcolor); FloodFill4(x+1,y,oldcolor,newcolor); FloodFill4(x,y-1,oldcolor,newcolor); } } void main() { int a,b,c,d,i,j; int graphdriver=DETECT; int graphmode=0; initgraph(&graphdriver,&graphmode," "); cleardevice();

计算机图形学课程设计-有效边表填充算法的实现

计算机图形学课程设计设计题目改进的有效边表算法对多边形的填充学院名称信息科学与技术学院 专业名称计算机科学与技术 学生姓名刘柯 学生学号201213030112 任课教师梅占勇 设计(论文)成绩 教务处制 2015年9 月28 日

目录 一、设计内容与要求 (3) 1.1设计题目 (3) 1.2 设计内容 (3) 1.3 设计目标 (3) 二、总体设计 (3) 2.1 多边形的表示 (3) 2.2 x-扫描线算法 (4) 2.3 改进的有效边表算法 (4) 2.3.1 改进的有效边表算法 (4) 2.3.2 有效边表 (5) 2.3.3 边表 (6) 三、详细设计 (8) 3.1 改进的有效边表算法的实现 (8) 3.2 有效边表算法程序流程图 (9) 四、测试结果 (9) 五、总结 (15) 六、源代码 (15) 参考文献 (26)

一、设计内容与要求 1.1设计题目 用改进的有效边表算法实现多边形的填充 1.2 设计内容 使用OpenGL实现用改进的有效边表算法填充多边形 1.3 设计目标 参照课本上改进的有效边表算法的思想,实现该算法的C语言代码,并用该算法搭配OpenGL以像素点的方式绘制出给定顶点坐标的多边形。 二、总体设计 2.1 多边形的表示 在计算机图形学中,多边形有2种重要的表示方法:顶点表示和点阵表示。 顶点表示用多边形的顶点序列来刻画多边形,这种方法直观、几何意义强,占用内存少,应用普遍,但它没有明确指出哪些像素在多边形内,故不能直接用于面着色。 点阵表示用位于多边形内的像素的集合来刻画多边形。这种表示法虽然失去了许多重要的几何信息,但便于运用帧缓存表示图形,是面着色所需要的图形表示形式。 大多数图形应用系统采用顶点序列表示多边形,而顶点表示又不能直接用于显示,那么就必须有从多边形的顶点表示到点阵表示的转换,这种转换称为多边形的扫描转

计算机图形学实验二

太原工业学院

实验拓展:绘制颜色渐变的三角形和四边形。 void CTriangle::Draw(CDC* pDC)//画出来一个三角形 { pDC->MoveTo(point0.x,point0.y); pDC->LineTo(point1.x,point1.y); pDC->LineTo(point2.x,point2.y); pDC->LineTo(point0.x,point0.y); } void CTriangle::GouraudShader(CDC* pDC) { SortVertex();//point0点为y坐标最小的点,point1点为y坐标最大的点,point2点的y坐标位于二者之间。如果y值相同,取x最小的点//定义三角形覆盖的扫描线条数 int nTotalScanLine = point1.y - point0.y + 1; //定义span的起点与终点数组 SpanLeft = new CPoint2[nTotalScanLine];//跨度左边数组 SpanRight = new CPoint2[nTotalScanLine];//跨度右边数组 //判断三角形与P0P1边的位置关系,0-1-2为右手系 int nDeltz = (point1.x - point0.x) * (point2.y - point1.y) - (point1.y - point0.y) * (point2.x - point1.x);//点矢量叉积的z坐标 if(nDeltz > 0)//三角形位于P0P1边的左侧 { nIndex = 0; DDA(point0, point2, TRUE); DDA(point2, point1, TRUE); nIndex = 0; DDA(point0, point1, FALSE); }

画圆与凸多边形填充算法

华北水利水电大学 计算机图形学 实验报告 2017--2018学年 第一学期 2014级 计算机科学与技术 专业 指导老师 曹源昊 班级 2014157 学号 201415717 姓名 李卫朋 实验四、画圆与凸多边形填充算法 1. 实验目的 练习对Bezier 曲线的绘制和Bezier 曲线的de Casteljau 算法。 2. 实验内容和要求 按要求完成以下一个作业。提交纸质实验报告,同时提交实验报告和源代码的电子版。 实现Bezier 曲线的de Casteljau 递推算法,能够对任意介于0和1之间的参数t 计算Bezier 曲线上的点,然后把Bezier 曲线绘制成首尾相连的直线段。 要求: (1). 对[0,1]参数区间进行100等分。 (2). 控制点的数目至少为5个,即Bezier 曲线的次数不低于4次。 (3). 同时绘制控制多边形。 (4). 至少绘制两条Bezier 曲线,具有不同的次数,颜色和曲线宽度。 形如: 3. 算法描述 使用vs2012编译环境,使用OpenGL 进行绘图操作。 4. 源程序代码 // 实验4.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include #include GLfloat ctrlPoints[5][2] = { { -0.8f, 0.1f }, {-0.4f, 0.6f }, { 0.0f, 0.8f }, { 0.5f, 0.2f },{0.9f,0.7f} }; 1P 2P 3P 4 P 5P

计算机图形学 多边形裁剪与填充 计算机图形学课程设计

课程设计报告 课程名称计算机图形学 课题名称多边形裁剪与填充 专业计算机科学与技术 班级计算机0902 学号 姓名 指导教师刘长松曹燚 2012年10 月9 日

湖南工程学院 课程设计任务书 课程名称计算机图形学课题多边形裁剪与填充 专业班级计算机0902 学生姓名 学号 指导老师刘长松曹燚 审批 任务书下达日期2012年9月15 日 任务完成日期2012 年10月9 日

一、设计内容与设计要求 1.设计内容: 交互式地实现多边形的裁剪和填充。。 2.设计要求: 1)窗口功能设计。 2)实现鼠标画多边形与数据存储功能。 3)实现鼠标剪裁窗口选择功能。 4)实现多边形裁剪和填充功能。 3.算法提示: 多边形裁剪算法分析: 基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:可见一侧,不可见一侧。用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。 对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。 多边形填充算法分析: 确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin 和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间填色。 二、进度安排 第 3 周星期一8:00——12:00 星期二8:00——12:00 星期三8:00——12:00 星期四8:00——12:00 星期五8:00——12:00 第 4 周星期一8:00——12:00 附: 课程设计报告装订顺序:封面、任务书、目录、正文、附件(A4大小的图纸及程序清单)、评分。正文的格式:一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。 正文的内容:一、课题的主要功能;二、课题的功能模块的划分(要求画出模块图);三、主要功能的实现(至少要有一个主要模块的流程图);四、程序调试;五、总结;六、附件(所有程序的原代码,要求对程序写出必要的注释)。 正文总字数要求在5000字以上(不含程序原代码)。

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

实验二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);//P0 P1[1]=CP2(MaxX/4+a,MaxY/2+a);//P1 P1[2]=CP2(MaxX/4+a,MaxY/2-a);//P2 P1[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);//P0 P2[1]=CP2(3*MaxX/4+b,MaxY/2);//P1 P2[2]=CP2(3*MaxX/4,MaxY/2-b);//P2 P2[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 here COLORREF FColor; CColorDialog ccd(RGB(255,0,0)); if(ccd.DoModal()==IDOK)//调用调色板选取色 { FColor=ccd.GetColor(); m_Red=GetRValue(FColor);//获得颜色的红色分量

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

实验报告 一、实验目的 1、掌握有序边表算法填充多边形区域; 2、理解多边形填充算法的意义; 3、增强C语言编程能力。 二、算法原理介绍 根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。 判断扫描线上的点是否在多边形之内,对于一条扫描线,多边形的扫描转换过程可以分为四个步骤: (1)求交:计算扫描线与多边形各边的交点; (2)排序:把所有交点按x值递增顺序排序; (3)配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边形的一个相交区间; (4)着色:把相交区间内的象素置成多边形颜色,把相交区间外的象素置成背景色。 p1,p3,p4,p5属于局部极值点,要把他们两次存入交点表中。如扫描线y=7上的交点中,有交点(2,7,13),按常规方法填充不正确,而要把顶点(7,7)两次存入交点表中(2,7,7,13)。p2,p6为非极值点,则不用如上处理。

为了提高效率,在处理一条扫描线时,仅对与它相交的多边形的边进行求交运算。把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。 对每一条扫描线都建立一个与它相交的多边形的活性边表(AET)。每个AET的一个节点代表一条活性边,它包含三项内容 1.x -当前扫描线与这条边交点的x坐标; 2.Δx -该边与当前扫描线交点到下一条扫描线交点的x增量; 3.ymax -该边最高顶点相交的扫描线号。 每条扫描线的活性边表中的活性边节点按照各活性边与扫描线交点的x值递增排序连接在一起。 当扫描线y移动到下一条扫描线y = y+1时,活性边表需要更新,即删去不与新扫描线相交的多边形边,同时增加与新扫描线相交的多边形边,并根据增量法重新计算扫描线与各边的交点x。 当多边形新边表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。 三、程序源代码 #include "graphics.h" #define WINDOW_HEIGHT 480 #define NULL 0 #include "alloc.h" #include "stdio.h" #include "dos.h" #include "conio.h" typedef struct tEdge /*typedef是将结构定义成数据类型*/ { int ymax; /* 边所交的最高扫描线号 */

多边形填充

计算机图形学实验报告 班级: 学号:

姓名:

实验三多边形填充 一实验目的 1)掌握多边形的有效边表填充算法; 2)掌握边界像素处理原则; 3)掌握菱形图形的填充方法。 二实验要求 1)设计实现多边形填充类,可以设置顶点序列,调用填充函 数。 2)多边形填充采用有效边表填充算法进行实现,通过建立多 边形的桶表和边表数据,按照算法步骤依次扫描填充;3)调用设计实现的多边形填充类,对菱形线框进行颜色填充。三实验步骤 第1步:创建MFC应用程序框架 参照第一章的步骤建立空的MFC应用程序框架。 第2步:设计实现直线绘制类 设计实现多边形填充类 1)有效边表填充算法原理 在多边形填充过程中,常采用:“下闭上开”和“左闭右开”的原则对边界像素进行处理。有效边表填充算法通过维护“桶表和边表”数据,节省了有效数据存储空间,避免了扫描线与多

边形所有边求交的运算耗时。 图1 边表结点数据结构 有效边表填充算法实现步骤为: a)根据多边形的顶点序列,建立其“桶表和边表”数据。b)按照扫描线从小到大的移动顺序,取出当前扫描线对应桶的边表数据。 c)如果“桶表”数据已经取完,则填充结束;否则,继续后续填充操作。 d)将当前桶里的边表数据加入到有效边表,根据“下闭上开”的原则,删除已经到y max的无效边。 e)对当前扫描线的有效边表按x值递增的顺序进行排序、配对,以确定填充区间;根据“左闭右开”的原则,对两两配对的填充空间进行像素填充。 f)继续回到步骤b。 1)新建多边形填充类CFillPoly头文件

首先声明二维点类“CP2”、边表类“CAET”和桶表类“CBucket”,用于存储和传递多边形“桶表和边表”数据。多边形填充类中主要包括存放多边形顶点数据、有效边表结点指针和桶表结点指针的成员变量,以及创建桶表、边表、有效边表排序和填充多边形等成员函数。“FillPoly.h”头文件中具体类型声明代码如下: #pragma once class CP2 { public: CP2 (); virtual~CP2 (); CP2 (double,int);

多边形的有效边表填充算法-

实验三多边形的有效边表填充算法 一、实验目的与要求 1、理解多边形的扫描转换原理、方法; 2、掌握有效边表填充算法; 3、掌握链表的建立、添加结点、删除节点的基本方法; 3、掌握基于链表的排序操作。 二、实验内容 在实验二所实现工程的基础上,实现以下内容并把实现函数封装在类 CMyGL 中。 1、C++实现有效边表算法进行多边形扫描转换 2、利用1进行多边形扫描转换和区域填充的实现; 三、实验原理 请同学们根据教材及上课的PPT独立完成。 四、实验步骤(程序实现)。 1、建立并选择工程项目。打开VC6.0->菜单File 的New 项,在projects 属性页选择MFC AppWizard(exe)项,在Project name 中输入一个工程名,如“Sample”。单文档。 2、新建一个图形类。选择菜单Insert New class,Class type 选择“Generic Class”,Name 输入类名,如“CMyCG。 3、向新建的图形类中添加成员函数(实际就是加入实验要求实现的图形生成算法的实现代码)。在工作区中直接鼠标右键单击,选择“Add Member Function…”项,添加绘制圆的成员函数。 void PolygonFill(int number, CPoint *p, COLORREF color, CDC* pDC) 添加其他成员函数: CreatBucket(); CreatET(); AddEdge(); EdgeOrder(); 4、成员函数的实现。实现有效边表填充算法。这一部分需要同学们去实现。 参考实现: 多边形的有效边表填充算法的基本过程为: 1、定义多边形: 2、初始化桶 3、建立边表 4、多边形填充 1)对每一条扫描线,将该扫描线上的边结点插入到临时AET表中,HeadE. 2)对临时AET表排序,按照x递增的顺序存放。 3)根据AET表中边表结点的ymax抛弃扫描完的边结点,即ymax>=scanline 4)扫描AET表,填充扫描线和多边形相交的区间。

多边形填充算法运行代码

private void scanLineFillingToolStripMenuItem_Click(object sender, EventArgs e) { slf.ScanLinePolygonFill(P,g,XiangSu); } private void label2_Click(object sender, EventArgs e) { } private void四联通填充ToolStripMenuItem_Click(object sender, EventArgs e) { tempp.X = tempP[3].X + XiangSu;//选取第4个点内侧(随机猜测) tempp.Y = tempP[3].Y + XiangSu; checkBox.Enabled = false;//让绘制过程中不能改变选择 do_check();//也要检查一遍,不然会出现错误 FloodSeedFill(tempp); checkBox.Enabled = true;//恢复 } ///

///下拉框选择像素回调函数 /// /// /// private void PortList_SelectedIndexChanged(object sender, EventArgs e) { XiangSu = 2 * PortList.SelectedIndex + 2;//根据下拉框选择绘制像素 } /// ///洪泛填充[注入填充] ///将所有联通区域内某种指定颜色的点都替换成另一种颜色 ///边界填充:只要是边界内的点无论是什么颜色,都替换成指定的颜色 /// /// /// private void floodFillAlgorithmToolStripMenuItem_Click(object sender, EventArgs e) {

实验二 有效边表填充算法

实验二有效边表填充算法 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.算法设计: 4.源程序: 1)//AET.h和AET..cpp class AET { } 2)//Bucket.h和Bucket.cpp class Bucket { } 3) // TestView.h #include "AET.h"//包含有效边表类 #include "Bucket.h"//包含桶类 #define Number 7//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中class CTestView : public CView { 。。。。。。。。。 public: void PolygonFill();//上闭下开填充多边形 void CreatBucket();//建立桶结点桶 void Et();//构造边表 void AddEdge(AET *);//将边插入AET表 void EdgeOrder();//对AET表进行排序

多边形的偏移填充算法

多边形的偏移填充算法 多边形偏移(polygon offset)算法可能我们印象不深,不过用过autoCAD的同学也印象autoCAD 上面也还是有这个功能的。我们可以用autoCAD上的“正多边形”功能画一个多边形,然后用修改工具中“偏移”按钮,对多边形进行偏移,见图1,从外面的一个大的5边形按照边偏移至里面小的5边形,其中相应边偏移的距离定义为offset值。 图1 AutoCAD中的多边形偏移效果图 当然,这只是简单的情况,复杂的情况可能是有多个多边形,其中1个outer多边形,多个inner 多边形,然后offset的时候应该是outer多边形向内offset,inner多边形向外offset。当一个多边形(特别是凹多边形)初步offset时,可能会发生自交;然后多边形之间也可能会发生相交。大概思路:这里就需要首先将自交的多边形分裂出来,并选择正确的多边形;然后将选择出来的多边形进行求交计算,再一次将有相交的多边形合并分裂出来,并且选择正确的多边形,这个时候得到的全部多边形就是一次offset出来的结果。 1、为了保证outer多边形能向内offset,inner多边形能向外offset,这里需要保证outer多边形是逆时针方向旋转的,inner多边形是顺时针方向旋转的。 1.1 这里就稍稍讲下多边形的顺逆判断。

在多边形是简单多边形的前提下,其实还是挺简单的,只要找出多边形左下角的一个顶点,然后判断与这个顶点相连的两条边的叉积是否大于0就行了;如果多边形不是简单多边形,比如有自相交,有顶点夹角为0的情况等等,这个时候多边形就不应该有顺逆这种属性吧 2、对单个多边形,根据角平分线初步偏移得到角点 对于一个角点,可以设这个顶点为curPoint,相连的前一个点为prePoint,下一个点为nexPoint,于是可以得到两个向量a = prePoint – curPoint,b=nexPoint – curPoint。将向量a和b设置为单位向量之后,相加就能得到角平分线的方向向量c。然后对单位向量a和b做点乘和叉乘,就能得到这个角度的cos和sin值了,我们假设这个角度的一般为Θ,则cos=cos2Θ,sin=sin2Θ。根据三角函数,就能得到sinΘ值,之后将就能得到该顶点的角平分线方向的偏移向量d=c/|c|×offset÷sinΘ。 3、考虑到有些边在偏移的过程中会消失,即一些边有退化的offset值,见图3。如果初步偏移的值大于它的退化offset值,则该边就会反向出现,见图3中的边【4,5】,会给后面的程序带来很大的麻烦。 图2

多边形有效边表填充算法

多边形有效边表填充算法案例效果如下: 具体实现: (1)新建MFC项目: (2)分别添加类:AET 和Bucket

在AET.h 中定义#pragma once class AET { public: AET(void); ~AET(void); double x; int yMax; double k; AET * next; }; 在Bucket.h中定义#pragma once #include"AET.h" class Bucket {

public: Bucket(void); ~Bucket(void); int Scanline; AET *p; Bucket * next; }; (3)定义菜单 (4)添加菜单处理程序 (5)定义视图头文件 // scanfillView.h : CscanfillView 类的接口// #pragma once #include"AET.h" #include"Bucket.h" # define Number 7 class CscanfillView : public CView {

protected: // 仅从序列化创建 CscanfillView(); DECLARE_DYNCREATE(CscanfillView) // 属性 public: CscanfillDoc* GetDocument() const; // 操作 public: void PolygonFill(); //上闭下开填充多边形 void CreatBucket(); //建立桶节点 void Et(); //构造边表 void AddEdge(AET *); //将边插入AET表 void EdgeOrder(); //对AET表进行排序 // 重写 public: virtual void OnDraw(CDC* pDC); // 重写以绘制该视图 virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); // 实现 public: virtual ~CscanfillView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: COLORREF GetColor; //调色板 CPoint Point[7]; //定义多边形 Bucket * HeadB,*CurrentB; //桶的头结点和当前节点 AET E[Number],*HeadE,*CurrentE,*T1,*T2; //有效边表的节点 // 生成的消息映射函数 protected: DECLARE_MESSAGE_MAP() public: afx_msg void OnMenuAET(); };

有效边表填充算法

实验二有效边表填充算法 实验题目:有效边表填充算法学号: 姓名:班级: 指导老师:完成日期: 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.算法设计: 多边形的有效边表填充算法的基本原理是按照扫描线从小到大的移动顺序,计算当前扫描线与多边形各边的交点,然后把这些交点按x值递增的顺序进行排序、配对,以确定填充区间,然后用指定颜色点亮填充区间的所有像素,即完成填充工作。有效边表填充算法通过访问多边形覆盖区间内的每个像素,可以填充凸、凹多边形和环,已成为目前最为有效的多边形填充算法。 4.源程序: 1)//AET.h和AET..cpp class AET { public: AET(); virtual ~AET(); double x; int yMax; double k; //代替1/k AET *next; } 2)//Bucket.h和Bucket.cpp class Bucket

{ public: Bucket(); virtual ~Bucket(); int ScanLine; AET *p;//桶上的边表指针 Bucket *next; } 3) // TestView.h #include "AET.h"//包含有效边表类 #include "Bucket.h"//包含桶类 #define Number 7//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中class CTestView : public CView { 。。。。。。。。。 public: void PolygonFill();//上闭下开填充多边形 void CreatBucket();//建立桶结点桶 void Et();//构造边表 void AddEdge(AET *);//将边插入AET表 void EdgeOrder();//对AET表进行排序 。。。。。。。。。。 protected: COLORREF GetColor;//调色板 CPoint Point[7];//定义多边形 Bucket *HeadB,*CurrentB;//桶的头结点和当前结点 AET E[Number],*HeadE,*CurrentE,*T1,*T2;//有效边表的结点 4)// TestView.cpp CTestView::CTestView() { //设置多边形的7个顶点 Point[0]=CPoint(550,400);//P0 Point[1]=CPoint(350,600);//P1 Point[2]=CPoint(250,350);//P2 Point[3]=CPoint(350,50);//P3 Point[4]=CPoint(500,250);//P4 Point[5]=CPoint(600,50);//P5 Point[6]=CPoint(800,450);//P6 } void CTestView::OnDraw(CDC* pDC) {

算法系列之十二:多边形区域填充算法--递归种子填充算法

算法系列之十二:多边形区域填充算法--递归种子填充算 法 平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充)。区域填充中最常用的是多边形填色,本文中我们就讨论几种多边形区域填充算法。一、种子填充算法(Seed Filling)如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法(Seed Filling)进行区域填充。种子填充算法需要给出图像数据的区域,以及区域内的一个点,这种算法比较适合人机交互方式进行的图像填充操作,不适合计算机自动处理和判断填色。根据对图像区域边界定义方式以及对点的颜色修改方式,种子填充又可细分为几类,比如注入填充算法(Flood Fill Algorithm)、边界填充算法(Boundary Fill Algorithm)以及为减少递归和压栈次数而改进的扫描线种子填充算法等等。所有种子填充算法的核心其实就是一个递归算法,都是从指定的种子点开始,向各个方向上搜索,逐个像素进行处理,直到遇到边界,各种种子填充算法只是在处理颜色和边界的方式上有所不同。在开始介绍种子填充算法之前,首先也介绍两个概念,就是“4-联通算法”

和“8-联通算法”。既然是搜索就涉及到搜索的方向问题,从区域内任意一点出发,如果只是通过上、下、左、右四个方向搜索到达区域内的任意像素,则用这种方法填充的区域就称为四连通域,这种填充方法就称为“4-联通算法”。如果从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下全部八个方向到达区域内的任意像素,则这种方法填充的区域就称为八连通域,这种填充方法就称为“8-联通算法”。如图1(a)所示,假设中心的蓝色点是当前处理的点,如果是“4-联通算法”,则只搜索处理周围蓝色标识的四个点,如果是“8-联通算法”则除了处理上、下、左、右四个蓝色标识的点,还搜索处理四个红色标识的点。两种搜索算法的填充效果分别如如图1(b)和图1(c)所示,假如都是从黄色点开始填充,则“4-联通算法”如图1(b)所示只搜索填充左下角的区域,而“8-联通算法”则如图1(c)所示,将左下角和右上角的区域都填充了。图(1)“4-联通”和“8-联通”填充效果并不能仅仅因为图1 的填充效果就认为“8-联通算法”一定比“4-联通算法”好,应该根据应用环境和实际的需求选择联通搜索方式,在很多情况下,只有“4-联通算法”才能得到正确的结果。1.1 注入填充算法(Flood Fill Algorithm)注入填充算法不特别强调区域的边界,它只是从指定位置开始,将所有联通区域内某种指定颜色的点都替换成另一种颜色,从而实现填

相关主题
文本预览
相关文档 最新文档