实验六 扫描线填充算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验六扫描线填充算法
一、实验目的
编写多边形的扫描线填充算法程序,加深对扫描线算法的理解,验证算法的正确性。
二、实验任务(2学时)
编写多边形的扫描线填充算法程序,利用数组实现AET,考虑与链表实现程序的不同。
三、实验内容
1、算法
对一条扫描线的填充一般分为以下4个步骤:
(1)求交:计算扫描线与多边形各边的交点;
(2)排序:把扫描线上所有交点按递增顺序进行排序;
(3)配对:将第一个交点与第二个交点,第三个交点与第四个交点等等进行配对,每对交点代表扫描线与多边形的一个相交区间。
(4)着色:把区间内的像素置为填充色。
2、成员函数的关系
主程序名为fill_area(count, x, y),其中参数x, y是两个一维数组,存放多边形顶点(共c ount个)的x和y坐标。它调用8个子程序,彼此之间的调用关系图1所示为:
图1 fill_area的程序结构
3、算法的程序设计
步骤1:创建“S_L_Fill”工程文件;
步骤2:创建类class:“EACH_ENTRY”。
在工作区“S_L_Fill classes”单击右键-→“new class”-→选择类型“Generic Class”名称为“EACH_ENTRY”,添加成员变量(添加至“class EACH_ENTRY { public:”之内):int y_top;
float x_int;
int delta_y;
float x_change_per_scan;
步骤3:包含头文件,同时初始化定义多边形顶点数目。在“class CS_L_FillView : public Cview……”之前添加代码“#include EACH_ENTRY.h”及“#define MAX_POINT 9”。
#define MAX_POINT 9
#include "EACH_ENTRY.h"
步骤4:在类“class CS_L_FillView”中添加成员变量(鼠标双击工作区“CS_L_FillView”,代码添加至“class CS_L_FillView : public Cview {protected: ……public:之后”):EACH_ENTRY sides[MAX_POINT];
int x[MAX_POINT],y[MAX_POINT];
int side_count,first_s,last_s,scan,bottomscan,x_int_count;
步骤5:利用构造函数“CS_L_FillView::CS_L_FillView()”初始化顶点坐标(鼠标双击工作区“CS_L_FillView”,代码添加至“CS_L_FillView()之内”):
x[0]=200;y[0]=100;
x[1]=240;y[1]=160;
x[2]=220;y[2]=340;
x[3]=330;y[3]=100;
x[4]=400;y[4]=180;
x[5]=300;y[5]=400;
x[6]=170;y[6]=380;
x[7]=120;y[7]=440;
x[8]=100;y[8]=220;
步骤6:在“class CS_L_FillView”下添加实现不同功能的成员函数。在工作区“CS_L_FillView”上单击鼠标右键,选择“Add Member Function”,分别完成以下成员函数的添加:
(1)void put_in_sides_list(int entry,int x1,int y1,int x2,int y2,int next_y)
函数说明:put_in_sides_list子程序的主要功能是将一条边存入活性边表之内。操作步骤是:对该边判别是否左顶点或右顶点,如果将入边之终点删去,按照y_top的大小在活性边表中找到该点的合适位置,y值较大者,排在活性边表的靠前位置。
void put_in_sides_list(int entry,int x1,int y1,int x2,int y2,int next_y)// entry为剔除水平边之后的第entry条边,x1, y1,为起点,x2, y2为终点,next_y为终点相邻的下一个顶点y坐标{
int maxy;
float x2_temp,x_change_temp;
x_change_temp=(float)(x2-x1)/(float)(y2-y1);//计算1/k
x2_temp=float(x2);
if((y2>y1)&&(y2 { y2--; x2_temp-=x_change_temp; } else { if((y2 { y2++; x2_temp+=x_change_temp; } } maxy=(y1>y2)?y1:y2; while((entry>1)&&(maxy>sides[entry-2].y_top)) { sides[entry-1]=sides[entry-2]; entry--; }// sides[]为边数组,边的y_top值越小,在数组中越靠后 sides[entry-1].y_top=maxy; sides[entry-1].delta_y=abs(y2-y1)+1; if(y1>y2)// x2,y2为右顶点,扫描线与起点先求交 sides[entry-1].x_int=float(x1); else// x2,y2左顶点,扫描线与终点先求交 sides[entry-1].x_int=x2_temp; sides[entry-1].x_change_per_scan=x_change_temp; } (2)void sort_on_bigger_y(int n,CDC* pDC) 函数说明:sort_on_bigger_y子程序的主要功能是按照输入的多边形,建立起活性边表。操作步骤是:对每条边加以判断:如非水平边则调用put_in_side_list子程序放入活性边来;如是水平边则直接画出。 void sort_on_bigger_y(int n,CDC* pDC)//按照输入的多边形建立活性链表 { int k,x1,y1; side_count=0;//全局变量,记录所有非水平边数目 y1=y[n-1]; x1=x[n-1];//(Pn-1,P0)为第一条边,开始建表 bottomscan=y[n-1]; for(k=0;k { if(y1!=y[k]&&(k+1)<=(n-1)) { side_count++; put_in_sides_list(side_count,x1,y1,x[k],y[k],y[k+1]);