02824523wanglili.cpp

来自「数据结构实验课中的所有实验程序」· C++ 代码 · 共 353 行

CPP
353
字号
// 02824523Wanglili.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream.h>
#include <windows.h>
#include <gl/gl.h>
#include <gl/glaux.h>
#include <gl/glu.h>

#define SCREEN_WIDTH   500


inline void DrawPoint(int x, int y)         //画点函数
{
	::glBegin(GL_POINTS);
		::glVertex2d(x, y);
	::glEnd();
}

void CALLBACK Reshape(GLsizei w, GLsizei h)
{
	::glViewport(0, 0, w, h);
	::glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
    if (w <= h) 
		gluOrtho2D (0.0, SCREEN_WIDTH, 0.0, SCREEN_WIDTH*(GLfloat)h/(GLfloat)w);
    else 
		gluOrtho2D (0.0, (GLfloat)SCREEN_WIDTH*(GLfloat)w/(GLfloat)h, 0.0, SCREEN_WIDTH);
    
	glMatrixMode(GL_MODELVIEW);
	return;
}


void Init()
{
	::auxInitDisplayMode(AUX_RGBA|AUX_SINGLE);     //RGB单缓存模式
	::auxInitPosition(0, 0, 500, 500);//窗口的左上角位置(x,y)及窗口大小
	::auxInitWindow("Scan algithmic");

	::glShadeModel(GL_FLAT);
	::glClearColor(0.0, 0.0, 0.0, 0.0);
}

//-----------------------------------
//Here, please define your own data structure for edge Table, Active Edge Table, Edge

//struct Original_Edge:Define to receive Original Edge information
struct Original_Edge                  //初始边信息
{
	int x1,y1;
	int x2,y2;
};


//*************接收初始边信息并存入初始边数组******************
void BuildArea(const int n,Original_Edge o_edge[])
{
	
	for(int i=0;i<n;i++)
	{
		cout<<"please input vertex"<<i<<"'s coordinate"<<endl<<"x: ";
		if(i==0)                            
		{
			cin>>o_edge[i].x1;
			o_edge[n-1].x2=o_edge[i].x1;
			cout<<"y: ";
			cin>>o_edge[i].y1;
			o_edge[n-1].y2=o_edge[i].y1;
		}
		else
		{
			cin>>o_edge[i-1].x2;
			o_edge[i].x1=o_edge[i-1].x2;
			cout<<"y: ";
			cin>>o_edge[i-1].y2;
			o_edge[i].y1=o_edge[i-1].y2;
		}
	}
}

//struct Edge:Define to store edge information prepared for scan_conversion
struct Edge
{
	float x_current;
	int y_max;
	float x_incrs;//Inverse of the edge slope
	Edge *next;
};

//////////////////////////////////////////
Edge *edge[SCREEN_WIDTH];//store information of edges sorted by their top y_value
int n;//number of totle edges of polygon
Original_Edge o_edge[15];//store polygon edges,but it's edges should less then 15.
/////////////////////////////////////////

//function Insert_Edge: Define to Insert primary-worked Edges(from Original_edge o_edge[] to
// Edge_table *edge[] via Edge p[])
void Insert_Edge(int q,int index[],Edge p[],Edge *edge[])  //q处理后的(非水平边)数目,index边序号,边数组,边表
{
	while(q>0)
	{
		int id=index[q-1];
		Edge *p1;
		Edge *p2;
		p1=p2=edge[id];
		if(p1==NULL) edge[id]=&p[q-1];
		else
		{
			while(p1!=NULL)
			{
				p2=p1;
				p1=p1->next;
			}
		p2->next=&p[q-1];
		}
		q--;
	}//end of while
}



//Function Build_Edge:Define to build edge table
//Including dealing with the odd points(if is not extremum point Its y_max-1)
void Build_Edge(const int n,Original_Edge o_edge[],Edge *edge[])
{
	Edge *p=new Edge[n];
	int q=0;
	int *id=new int[n];//id:use to decide the location of the edge in Edge_table
	for(int k=0;k<n;k++)
	{
		if(o_edge[k].y1==o_edge[k].y2) continue;//Horizon edges should not insert into edge_table
		else 
		{ 
		//x_incrs:refer to the x_value on current edge increase when y_value add 1(scan upper line)
			p[q].x_incrs=((float)o_edge[k].x2-o_edge[k].x1)/(o_edge[k].y2-o_edge[k].y1);
			p[q].next=NULL;//initialization pointer next
		}
		if(k==0)
		{
			if((o_edge[k].y1-o_edge[k].y2)*(o_edge[k].y1-o_edge[n-1].y2)<0)//非奇点
			{
				p[q].y_max=(o_edge[k].y1>o_edge[k].y2?o_edge[k].y1:o_edge[k].y2)-1;
				p[q].x_current=float(o_edge[k].y1<o_edge[k].y2?o_edge[k].x1:o_edge[k].x2);
				id[q]=o_edge[k].y1<o_edge[k].y2?o_edge[k].y1:o_edge[k].y2;
			}
			else
			{
				p[q].y_max=(o_edge[k].y1>o_edge[k].y2?o_edge[k].y1:o_edge[k].y2);
				p[q].x_current=float(o_edge[k].y1<o_edge[k].y2?o_edge[k].x1:o_edge[k].x2);
				id[q]=o_edge[k].y1<o_edge[k].y2?o_edge[k].y1:o_edge[k].y2;
			}
		}
		else
		{
			if((o_edge[k].y1-o_edge[k-1].y1)*(o_edge[k].y1-o_edge[k].y2)<0)//非奇点
			{
				if(o_edge[k].y1>o_edge[k].y2)//current edge ymax-1
				{
					p[q].y_max=(o_edge[k].y1>o_edge[k].y2?o_edge[k].y1:o_edge[k].y2)-1;//将高点的Y值减1
					p[q].x_current=float(o_edge[k].y1<o_edge[k].y2?o_edge[k].x1:o_edge[k].x2);//记录低点的x值
					id[q]=o_edge[k].y1<o_edge[k].y2?o_edge[k].y1:o_edge[k].y2;//将该边信息记录到该边最低点经过扫描线的Y桶 
				}
				else//last edge ymax-1
				{
					p[q-1].y_max=p[q-1].y_max-1;
					p[q].y_max=(o_edge[k].y1>o_edge[k].y2?o_edge[k].y1:o_edge[k].y2);
					p[q].x_current=float(o_edge[k].y1<o_edge[k].y2?o_edge[k].x1:o_edge[k].x2);
					id[q]=o_edge[k].y1<o_edge[k].y2?o_edge[k].y1:o_edge[k].y2;
				}
			}
			else//对奇点的处理,坐标值不做改变
			{
				p[q].y_max=(o_edge[k].y1>o_edge[k].y2?o_edge[k].y1:o_edge[k].y2);
				p[q].x_current=float(o_edge[k].y1<o_edge[k].y2?o_edge[k].x1:o_edge[k].x2);
				id[q]=o_edge[k].y1<o_edge[k].y2?o_edge[k].y1:o_edge[k].y2;
			}
		}
	q++;
	}
	Insert_Edge(q,id,p,edge);
}
void Scan_Fill(Edge *edge[])
{
	Edge *ael=NULL;//初始化活化边表指针;
	for(int scan=0;scan<SCREEN_WIDTH;scan++)//scan from bottom to top
	{
		Edge *po,*pl;//point to Old Active edge list for sorting,*po2
		Edge *pn1,*pn2;//point to New Active edge list for sorting
		Edge *pe=edge[scan];//point to edge to get information

		if(pe!=NULL)
		{
			pl=po=ael;
			while(po!=NULL)
			{
				pl=po;
				po=po->next;
			};
			if(pl==NULL)     //如果原来活化边表为空,就将边表中值直接赋给当前活化边
				ael=pe;
			else
				pl->next=pe;//将新边加到活化边表尾
		}

		//以下为更新活化边表,对表中边进行排序
		Edge *newlist=new Edge;
		newlist=NULL;
		po=ael;
		while(po!=NULL)
		{
			Edge *listNode=new Edge;
			listNode->next=NULL;
			listNode->x_current=po->x_current;
			listNode->x_incrs=po->x_incrs;
			listNode->y_max=po->y_max;
			if(newlist==NULL)
				newlist=listNode;
			else                      //begin
			{
				pn1=pn2=newlist;
				while(pn1!=NULL)
				{
					if(pn1->x_current<listNode->x_current)
					{
						pn2=pn1;
						pn1=pn1->next;
					}
					else break;
				}
				if(pn1==NULL)//插入到表尾
				{
					pn2->next=listNode;
				}
				else if(pn1!=newlist)//不是活化边表头的情况
				{
						listNode->next=pn1;
						pn2->next=listNode;
				}
				else                 //插入到表头部
				{
						listNode->next=pn1;
						newlist=listNode;
				}
			}                  //end 
			po=po->next;
		};                    //结束更新活化边表
		ael=newlist;

		// 开始扫描填充
		pn1=pn2=ael;
		if(pn1!=NULL)
		while(pn2->next!=NULL)
		{
			pn2=pn2->next;
			int x1,x2;
			x1=int(pn1->x_current+0.5);
			x2=int(pn2->x_current+0.5);
			for(int pix=x1;pix<x2;pix++)
			{
				DrawPoint(pix,scan);
			}
			pn1->x_current=pn1->x_current+pn1->x_incrs;
			pn2->x_current=pn2->x_current+pn2->x_incrs;
			if(pn2->next!=NULL)
			{
				pn1=pn2->next;   //指向紧跟的两条边
				pn2=pn1;
			}
		};

		//如果该边最高端点小于当前扫描线 将之删除
		pn1=pn2=ael;
		while(pn1!=NULL)
		{
			Edge *temp;
			if(pn1->y_max==scan)
			{
				if(pn1==ael) {temp=ael; ael=pn1->next; }       //删除活化边表头
				else {temp=pn1;pn2->next=pn1->next;}           //删除中间的边
				pn1=pn1->next;
				delete temp;
			}
			else
			{
				pn2=pn1;
				pn1=pn1->next;
			}
		};//删除操作结束
	}//end of active__for
}


//-----------------------------------


void CALLBACK Display()
{
	::glColor3f(1.0, 0.0, 0.0);
//-----------------------------------
// use the function "DrawPoint"defined above to display
// your scan conversion result here
////draw polygon
	glColor3f(1.0f,0.0f,0.0f);
	Scan_Fill(edge);
	
/*	glLineWidth(3.0f);
	glColor3f(0.0f,1.0f,0.0f);
	glBegin(GL_LINE_LOOP);
	for(int i=0;i<n;i++)
	{
		glVertex2i(o_edge[i].x1,o_edge[i].y1);
	}
	glEnd();*/
//-----------------------------------
	::glFlush();
	return;
}


void main(int argc, char **argv)
{
	//-------------------------------------------
	// implement your scan conversion algorithm here!
	cout<<"======welcome to test lily's programe========="<<endl;
	cout<<"please input the amount of your edges:";
	cin>>n;
	while(n<3) { cerr<<endl<<"the edges are not enough to build a polygon,please reput:"; cin>>n;}
	BuildArea(n,o_edge);
	/*for(int j=0;j<n;j++)
		cout<<"p: "<<o_edge[j].x1<<o_edge[j].y1<<o_edge[j].x2<<o_edge[j].y2<<endl;*/
	for(int i=0;i<SCREEN_WIDTH;i++)
		edge[i]=NULL;
	Build_Edge(n,o_edge,edge);
	/*for(int k=0;k<SCREEN_WIDTH;k++)
	{
		Edge *p=edge[k];
		while(p!=NULL)
		{
			cout<<"e:"<<p->x_current<<' '<<p->y_max<<' '<<p->x_incrs<<endl;
			p=p->next;
		}
	}
	*/
	Scan_Fill(edge);
//-------------------------------------------
	Init();
	::auxReshapeFunc(Reshape);
	::auxMainLoop(Display);
	return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?