计算机图形学实验四:扫描线填充多边形

#include<GL/glut.h>
#include<iostream>
#include<iterator>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
const int window_size = 600;
int last_x=-1, last_y=-1;
struct point {
	int x, y;	
};
struct node {
	float x, ymax, delta_x;
	bool operator < (const node &b) const  {
		if (x != b.x) {
			return x < b.x;
		}
		else  if(ymax!=b.ymax){
			return ymax < b.ymax;
		}
		else {
			return delta_x < b.delta_x;
		}
	}
};
set<node> AET, NET[window_size];
vector<node> temp;
vector<point> Vertexs;
int Y_MIN, Y_MAX;
void drawline(int x0,int y0,int x1,int y1) {
	glColor3ub(25,160,95);
	glBegin(GL_LINES);
	glVertex2f(x0, y0);
	glVertex2f(x1, y1);
	glEnd();
	glFlush();
}


void polyfill() {
	//找ymin和ymax
	int len = Vertexs.size();
	for (int i = 0; i < len; i++) {
		if (Vertexs[i].y > Y_MAX) Y_MAX = Vertexs[i].y;
		if (Vertexs[i].y < Y_MIN)Y_MIN = Vertexs[i].y;
	}
	//初始化NET
	for (int i = Y_MIN; i <= Y_MAX; i++) {
		for (int j = 0; j < len; j++) {
			if (Vertexs[j].y == i) {
				cout << "当前的i是" << i << endl;
				if (Vertexs[(j + len - 1) % len].y > Vertexs[j].y) {
					float y_max = Vertexs[(j + len - 1) % len].y;
					float x = Vertexs[j].x;
					float dx = Vertexs[(j + len - 1) % len].x - Vertexs[j].x;
					float dy = Vertexs[(j + len - 1) % len].y - Vertexs[j].y;
					cout << "插入1" << endl;
					NET[i].insert({ x,y_max,dx / dy });
				}
				if (Vertexs[(j + 1) % len].y > Vertexs[j].y) {
					float y_max = Vertexs[(j + 1) % len].y;
					float x = Vertexs[j].x;
					float dx = Vertexs[(j + 1) % len].x - Vertexs[j].x;
					float dy = Vertexs[(j + 1) % len].y - Vertexs[j].y;
					NET[i].insert({ x,y_max,dx / dy });
					cout << "插入2" << endl;
				}
			}
			
		}
	}
	//AET
	for (int i = Y_MIN; i <= Y_MAX; i++) {		
		//将NET[i]中的边结点用插入排序法插入AET,使之按x坐标递增顺序排列。
		set<node>::iterator it = NET[i].begin();
		for (; it != NET[i].end(); it++) {
			AET.insert({it->x,it->ymax,it->delta_x});
			cout << "当前的i是" << i << " ,插入了一次" << endl;
			cout << "现在有" << AET.size() << "条活性边" << endl;
		}	
		//删除ymax==i的节点
		it = AET.begin();
		for (; it != AET.end();) {
			if (it->ymax == i) {
				AET.erase(it++); 
				cout << "当前的i是" << i << " ,删除了一次" << endl;
				cout << "现在有" << AET.size() << "条活性边" << endl;
			}
			else { it++; }
		}
		//匹配画线
		it = AET.begin();
		while (it != AET.end()) {
			float x0 = it->x;
			it++;
			float x1 = it->x;
			drawline(x0, i, x1, i);
			it++;
		}
		//增量
		temp.clear();
		it = AET.begin();
		for (; it != AET.end();) {			
			float x = it->x + it->delta_x;
			float y = it->ymax;
			float delta_x = it->delta_x;
			AET.erase(it++);
			temp.push_back({ x,y,delta_x });
		}
		for (int i = 0; i < temp.size(); i++) {
			AET.insert(temp[i]);
		}
	}
}

void mymouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		Vertexs.push_back({ x,y });
		cout << "顶点的坐标为(" << x << "," << y << ")" << endl;
		glPointSize(5);
		glColor3ub(211, 79, 67);
		glBegin(GL_POINTS);
		glVertex2i(x, y);
		glEnd();
		glFlush();
		if (last_x > 0 && last_y > 0) {
			glColor3ub(75, 140, 255);
			glBegin(GL_LINES);
			glVertex2i(x, y);
			glVertex2i(last_x, last_y);
			glEnd();
			glFlush();
		}
		last_x = x, last_y = y;
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
		polyfill();	
	}
}

void mykeyboard(unsigned char key, int x, int y) {
	if (key == 'f' && Vertexs.size()) {
		glBegin(GL_LINES);
		glVertex2i(last_x, last_y);
		glVertex2i(Vertexs[0].x, Vertexs[0].y);
		glEnd();
		glFlush();
	}
	if (key == 'c') {
		cout << "按下了c键" << endl;
		AET.clear();
		for (int i = 0; i < window_size; i++) {
			NET[i].clear();
		}
		Vertexs.clear();
		temp.clear();
		glClearColor(1, 1, 1, 0);
		glClear(GL_COLOR_BUFFER_BIT);
		last_x = -1, last_y = -1;
		glFlush();
	}
}
void myDisplay() {
	cout << "调用了一次回调函数" << endl;
}
void init() {
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluOrtho2D(0, window_size, window_size, 0);
	Y_MIN = window_size; Y_MAX = 0;
}
int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(300, 100);
	glutInitWindowSize(window_size, window_size);
	glutCreateWindow("扫描线填充多边形");
	init();
	glutMouseFunc(mymouse);
	glutKeyboardFunc(mykeyboard);
	glutDisplayFunc(myDisplay);
	glutMainLoop();
	return 0;
}

含内环的多边形

#include<GL/glut.h>
#include<iostream>
#include<iterator>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
const int window_size = 600,maxhole=255;
int poly_number = -1;
int last_x=-1, last_y=-1;
struct point {
	int x, y;	
};
struct node {
	float x, ymax, delta_x;
	bool operator < (const node &b) const  {
		if (x != b.x) {
			return x < b.x;
		}
		else  if(ymax!=b.ymax){
			return ymax < b.ymax;
		}
		else {
			return delta_x < b.delta_x;
		}
	}
};
set<node> AET, NET[window_size];
vector<node> temp;
vector<point> Vertexs[255];
int Y_MIN, Y_MAX;
void drawline(int x0,int y0,int x1,int y1) {
	glColor3ub(25,160,95);
	glBegin(GL_LINES);
	glVertex2f(x0, y0);
	glVertex2f(x1, y1);
	glEnd();
	glFlush();
}


void polyfill() {
	//找ymin和ymax
	for (int k = 0; k <= poly_number; k++) {
		int len = Vertexs[k].size();
		for (int i = 0; i < len; i++) {
			if (Vertexs[k][i].y > Y_MAX) Y_MAX = Vertexs[k][i].y;
			if (Vertexs[k][i].y < Y_MIN)Y_MIN = Vertexs[k][i].y;
		}
	}
	
	//初始化NET
	for (int i = Y_MIN; i <= Y_MAX; i++) {
		for (int k = 0; k <= poly_number; k++) {
			int len = Vertexs[k].size();
			for (int j = 0; j < len; j++) {
				if (Vertexs[k][j].y == i) {
					cout << "当前的i是" << i << endl;
					if (Vertexs[k][(j + len - 1) % len].y > Vertexs[k][j].y) {
						float y_max = Vertexs[k][(j + len - 1) % len].y;
						float x = Vertexs[k][j].x;
						float dx = Vertexs[k][(j + len - 1) % len].x - Vertexs[k][j].x;
						float dy = Vertexs[k][(j + len - 1) % len].y - Vertexs[k][j].y;
						cout << "插入1" << endl;
						NET[i].insert({ x,y_max,dx / dy });
					}
					if (Vertexs[k][(j + 1) % len].y > Vertexs[k][j].y) {
						float y_max = Vertexs[k][(j + 1) % len].y;
						float x = Vertexs[k][j].x;
						float dx = Vertexs[k][(j + 1) % len].x - Vertexs[k][j].x;
						float dy = Vertexs[k][(j + 1) % len].y - Vertexs[k][j].y;
						NET[i].insert({ x,y_max,dx / dy });
						cout << "插入2" << endl;
					}
				}

			}
		}

		
	}
	//AET
	for (int i = Y_MIN; i <= Y_MAX; i++) {		
		//将NET[i]中的边结点用插入排序法插入AET,使之按x坐标递增顺序排列。
		set<node>::iterator it = NET[i].begin();
		for (; it != NET[i].end(); it++) {
			AET.insert({it->x,it->ymax,it->delta_x});
			cout << "当前的i是" << i << " ,插入了一次" << endl;
			cout << "现在有" << AET.size() << "条活性边" << endl;
		}	
		//删除ymax==i的节点
		it = AET.begin();
		for (; it != AET.end();) {
			if (it->ymax == i) {
				AET.erase(it++); 
				cout << "当前的i是" << i << " ,删除了一次" << endl;
				cout << "现在有" << AET.size() << "条活性边" << endl;
			}
			else { it++; }
		}
		//匹配画线
		it = AET.begin();
		while (it != AET.end()) {
			float x0 = it->x;
			it++;
			float x1 = it->x;
			drawline(x0, i, x1, i);
			it++;
		}
		//增量
		temp.clear();
		it = AET.begin();
		for (; it != AET.end();) {			
			float x = it->x + it->delta_x;
			float y = it->ymax;
			float delta_x = it->delta_x;
			AET.erase(it++);
			temp.push_back({ x,y,delta_x });
		}
		for (int i = 0; i < temp.size(); i++) {
			AET.insert(temp[i]);
		}
	}
}

void mymouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		if (last_x == -1 && last_y == -1) {
			poly_number++;
		}
		Vertexs[poly_number].push_back({ x,y });
		cout << "顶点的坐标为(" << x << "," << y << ")" << endl;
		glPointSize(5);
		glColor3ub(211, 79, 67);
		glBegin(GL_POINTS);
		glVertex2i(x, y);
		glEnd();
		glFlush();
		if (last_x > 0 && last_y > 0) {
			glColor3ub(75, 140, 255);
			glBegin(GL_LINES);
			glVertex2i(x, y);
			glVertex2i(last_x, last_y);
			glEnd();
			glFlush();
		}
		last_x = x, last_y = y;
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
		polyfill();	
	}
}

void mykeyboard(unsigned char key, int x, int y) {
	if (key == 'f' && Vertexs[poly_number].size()) {
		glBegin(GL_LINES);
		glVertex2i(last_x, last_y);
		glVertex2i(Vertexs[poly_number][0].x, Vertexs[poly_number][0].y);
		glEnd();
		glFlush();
		last_x = -1, last_y = -1;
	}
	if (key == 'c') {
		cout << "按下了c键" << endl;
		AET.clear();
		for (int i = 0; i < window_size; i++) {
			NET[i].clear();
		}
		for (int i = 0; i <= poly_number; i++) {
			Vertexs[i].clear();
		}		
		temp.clear();
		glClearColor(1, 1, 1, 0);
		glClear(GL_COLOR_BUFFER_BIT);
		last_x = -1, last_y = -1;
		glFlush();
	}
}
void myDisplay() {
	cout << "调用了一次回调函数" << endl;
}
void init() {
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluOrtho2D(0, window_size, window_size, 0);
	Y_MIN = window_size; Y_MAX = 0;
}
int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(300, 100);
	glutInitWindowSize(window_size, window_size);
	glutCreateWindow("扫描线填充多边形");
	init();
	glutMouseFunc(mymouse);
	glutKeyboardFunc(mykeyboard);
	glutDisplayFunc(myDisplay);
	glutMainLoop();
	return 0;

}

不足与改进:

set在插入边的时候,需要删除再插,复杂度过高。
解决方法:node里面再加一个值x’,非键值,y++的时候更新x’.等到了关键高度的时候再用x’去更新x.
也在一个关键节点时,将set的值先存到数组中,y++的时候对数组进行操作,等到了下一个关键节点的时候再将数组的值变成set

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值