计算机图形学实验三:多边形裁剪

不含凹多边形裁剪算法

#include <iostream>
#include<GL/glut.h>
#include<vector>
using namespace std;
int window_size = 600;
int wmin = 200, wmax = 400;
int hmin = 200, hmax = 400;
int last_x = -1, last_y = -1;
struct Vertex {
	int x, y;
};
struct Edge {
	Vertex point[2];
};


Edge LEFT, RIGHT, TOP, BOTTOM;

vector<Vertex> inputVertex, outputVertex;


void Output(Vertex& p, int outlength, vector<Vertex>& OutVertexarray) {

}


bool Inside(Vertex& TestPt, Edge& ClipBoundary) {//裁剪边为窗口下边
	//判断点是否在裁剪边的可见侧
	if (ClipBoundary.point[1].x > ClipBoundary.point[0].x) {//裁剪边为窗口下边
		if (TestPt.y >= ClipBoundary.point[0].y) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].x < ClipBoundary.point[0].x) {//裁剪边为窗口上边
		if (TestPt.y <= ClipBoundary.point[0].y) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].y > ClipBoundary.point[0].y) {//裁剪边为窗口右边
		if (TestPt.x <= ClipBoundary.point[0].x) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].y < ClipBoundary.point[0].y) {//裁剪边为窗口左边
		if (TestPt.x >= ClipBoundary.point[0].x) {
			return true;
		}
	}
	return false;

}




void Intersect(Vertex& S, Vertex& P, Edge& ClipBoundary, Vertex& IntersectPt) {
	if (ClipBoundary.point[0].y == ClipBoundary.point[1].y) {//水平裁剪边
		IntersectPt.y = ClipBoundary.point[1].y;
		IntersectPt.x = S.x + (ClipBoundary.point[0].y - S.y) * (P.x - S.x) / (P.y - S.y);
	}
	else {//垂直裁剪边
		IntersectPt.x = ClipBoundary.point[0].x;
		IntersectPt.y = S.y + (ClipBoundary.point[0].x - S.x) * (P.y - S.y) / (P.x - S.x);
	}
}
void SutherlandHogmanClip(vector<Vertex>& InVertexArray, vector<Vertex>& OutVertexArray, Edge ClipBoundary, int Inlength);
void showResult(vector<Vertex>& VertexArray);
void polygonClip() {
	//4把刀
	//1、左侧边
	LEFT.point[0].x = wmin;
	LEFT.point[0].y = hmax;
	LEFT.point[1].x = wmin;
	LEFT.point[1].y = hmin;
	SutherlandHogmanClip(inputVertex, outputVertex, LEFT, inputVertex.size());
	//2、下侧边
	BOTTOM.point[0].x = wmin;
	BOTTOM.point[0].y = hmin;
	BOTTOM.point[1].x = wmax;
	BOTTOM.point[1].y = hmin;
	inputVertex.clear();
	SutherlandHogmanClip(outputVertex, inputVertex, BOTTOM, outputVertex.size());
	//右侧边
	RIGHT.point[0].x = wmax;
	RIGHT.point[0].y = hmin;
	RIGHT.point[1].x = wmax;
	RIGHT.point[1].y = hmax;
	outputVertex.clear();
	SutherlandHogmanClip(inputVertex, outputVertex, RIGHT, inputVertex.size());
	//上侧边
	TOP.point[0].x = wmax;
	TOP.point[0].y = hmax;
	TOP.point[1].x = wmin;
	TOP.point[1].y = hmax;
	inputVertex.clear();
	SutherlandHogmanClip(outputVertex, inputVertex, TOP, outputVertex.size());


	showResult(inputVertex);
}
void showResult(vector<Vertex>& VertexArray) {
	//把裁剪后的结果显示出来
	glColor3f(0, 255, 0);
	int len = VertexArray.size();
	for (int i = 0; i < VertexArray.size(); i++) {
		cout << "裁剪后点的坐标为(" << VertexArray[i].x << "," << VertexArray[i].y << ")" << endl;
		glLineWidth(5);
		glBegin(GL_LINES);

		glVertex2i(VertexArray[i].x, VertexArray[i].y);
		glVertex2i(VertexArray[(i + 1) % len].x, VertexArray[(i + 1) % len].y);
		glEnd();
		glBegin(GL_POINTS);
		glVertex2i(VertexArray[i].x, VertexArray[i].y);
		glVertex2i(VertexArray[(i + 1) % len].x, VertexArray[(i + 1) % len].y);
		glEnd();
		glLineWidth(1);
	}
	glFlush();
}




void SutherlandHogmanClip(vector<Vertex>& InVertexArray, vector<Vertex>& OutVertexArray, Edge ClipBoundary, int Inlength) {
	Vertex S, P, ip;
	S = InVertexArray[Inlength - 1];
	for (int j = 0; j < Inlength; j++) {
		P = InVertexArray[j];
		if (Inside(P, ClipBoundary)) {
			if (Inside(S, ClipBoundary)) {
				cout << "情况1" << endl;
				//SP在窗口内,情况(1)
				OutVertexArray.push_back(P);
				//Output(P, Outlength, OutVertexArray);
			}
			else {//S在窗口外,情况(4)
				cout << "情况4" << endl;
				Intersect(S, P, ClipBoundary, ip);
				OutVertexArray.push_back(ip);
				OutVertexArray.push_back(P);
				//Output(ip, Outlength, OutVertexArray);
				//Output(P, Outlength, OutVertexArray);
			}
		}
		else if (Inside(S, ClipBoundary)) {
			cout << "情况3" << endl;
			//S在窗口内,P在窗口外,情况(3)
			Intersect(S, P, ClipBoundary, ip);
			OutVertexArray.push_back(ip);
			cout << "ip的坐标为" << ip.x << " , " << ip.y << endl;
			cout << "刚才入数组的点的坐标为" << OutVertexArray.back().x << " , " << outputVertex.back().y << endl;
			//Output(ip, Outlength, OutVertexArray);
		}
		else {
			cout << "情况2" << endl;
		}
		S = P;
	}
}

void drawpoint(int x, int y) {
	glColor3f(1, 0, 0);
	glBegin(GL_POINTS);
	glVertex2f(x, y);
	glEnd();
	glFlush();
}
void mykeyboard(unsigned char key, int x, int y) {
	if (key == 'f' && inputVertex.size()) {
		glColor3f(0, 0, 255);
		glBegin(GL_LINES);
		glVertex2d(last_x, last_y);
		glVertex2d(inputVertex[0].x, inputVertex[0].y);
		glEnd();
		glFlush();
	}
	if (key == 'c') {
		polygonClip();
	}
}
void myDisplay();
void mymouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		inputVertex.push_back({ x,y });
		drawpoint(x, y);
		if (last_x >= 0 && last_y >= 0) {
			cout << "可以画线" << endl;
			glColor3f(0, 0, 255);
			glBegin(GL_LINES);
			glVertex2i(last_x, last_y);
			glVertex2i(x, y);
			glEnd();
			glFlush();
		}
		cout << "刚才加入的坐标是" << x << "," << y << endl;
		last_x = x; last_y = y;
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
		cout << "点击了鼠标右键" << endl;
		myDisplay();
		inputVertex.clear(); outputVertex.clear();
		last_x = -1; last_y = -1;
	}
}


void myDisplay() {
	cout << "调用了一次回调函数" << endl;
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	//绘制裁剪区域
	glColor3f(0, 1, 1);
	glBegin(GL_LINES);
	//1、L
	glVertex2i(wmin, hmin);
	glVertex2i(wmin, hmax);
	//2、B
	glVertex2i(wmin, hmin);
	glVertex2i(wmax, hmin);
	//3、R
	glVertex2i(wmax, hmin);
	glVertex2i(wmax, hmax);
	//4、T
	glVertex2i(wmin, hmax);
	glVertex2i(wmax, hmax);
	glEnd();
	glFlush();
}
void init() {
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(7);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluOrtho2D(0, window_size, window_size, 0);
	myDisplay();
}
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);
	//glutMotionFunc(dragMouse);
	glutMainLoop();
	return 0;
}

含有凹多边形裁剪算法

#include <iostream>
#include<GL/glut.h>
#include<vector>
#include<cstring>
using namespace std;
const int window_size = 600;
int wmin = 200, wmax = 400;
int hmin = 200, hmax = 400;
int last_x = -1, last_y = -1;
struct Vertex {
	int x, y;
};
struct Edge {
	Vertex point[2];
};
int vis[window_size][window_size];

Edge LEFT, RIGHT, TOP, BOTTOM;

vector<Vertex> inputVertex, outputVertex;



bool Inside(Vertex& TestPt, Edge& ClipBoundary) {//裁剪边为窗口下边
	//判断点是否在裁剪边的可见侧
	if (ClipBoundary.point[1].x > ClipBoundary.point[0].x) {//裁剪边为窗口下边
		if (TestPt.y >= ClipBoundary.point[0].y) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].x < ClipBoundary.point[0].x) {//裁剪边为窗口上边
		if (TestPt.y <= ClipBoundary.point[0].y) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].y > ClipBoundary.point[0].y) {//裁剪边为窗口右边
		if (TestPt.x <= ClipBoundary.point[0].x) {
			return true;
		}
	}
	else if (ClipBoundary.point[1].y < ClipBoundary.point[0].y) {//裁剪边为窗口左边
		if (TestPt.x >= ClipBoundary.point[0].x) {
			return true;
		}
	}
	return false;

}

void Intersect(Vertex& S, Vertex& P, Edge& ClipBoundary, Vertex& IntersectPt) {
	if (ClipBoundary.point[0].y == ClipBoundary.point[1].y) {//水平裁剪边
		IntersectPt.y = ClipBoundary.point[1].y;
		IntersectPt.x = S.x + (ClipBoundary.point[0].y - S.y) * (P.x - S.x) / (P.y - S.y);
	}
	else {//垂直裁剪边
		IntersectPt.x = ClipBoundary.point[0].x;
		IntersectPt.y = S.y + (ClipBoundary.point[0].x - S.x) * (P.y - S.y) / (P.x - S.x);
	}
}
void SutherlandHogmanClip(vector<Vertex>& InVertexArray, vector<Vertex>& OutVertexArray, Edge ClipBoundary, int Inlength);
void showResult(vector<Vertex>& VertexArray);
void polygonClip() {
	//4把刀
	//1、左侧边
	LEFT.point[0].x = wmin;
	LEFT.point[0].y = hmax;
	LEFT.point[1].x = wmin;
	LEFT.point[1].y = hmin;
	SutherlandHogmanClip(inputVertex, outputVertex, LEFT, inputVertex.size());
	//2、下侧边
	BOTTOM.point[0].x = wmin;
	BOTTOM.point[0].y = hmin;
	BOTTOM.point[1].x = wmax;
	BOTTOM.point[1].y = hmin;
	inputVertex.clear();
	SutherlandHogmanClip(outputVertex, inputVertex, BOTTOM, outputVertex.size());
	//右侧边
	RIGHT.point[0].x = wmax;
	RIGHT.point[0].y = hmin;
	RIGHT.point[1].x = wmax;
	RIGHT.point[1].y = hmax;
	outputVertex.clear();
	SutherlandHogmanClip(inputVertex, outputVertex, RIGHT, inputVertex.size());
	//上侧边
	TOP.point[0].x = wmax;
	TOP.point[0].y = hmax;
	TOP.point[1].x = wmin;
	TOP.point[1].y = hmax;
	inputVertex.clear();
	SutherlandHogmanClip(outputVertex, inputVertex, TOP, outputVertex.size());


	showResult(inputVertex);
}
void drawpixel(int x, int y) {
	glPointSize(2);
	vis[x][y]++;
	if (vis[x][y] % 2 == 1) {//奇数次 显示
		glColor3ub(20, 160, 93);
		glBegin(GL_POINTS);
		glVertex2i(x, y);
		glEnd();
		glFlush();
	}
	else {//偶数次 不显示
		glColor3ub(255, 205, 68);
		glBegin(GL_POINTS);
		glVertex2i(x, y);
		glEnd();
		glFlush();

	}

}
void Bresenham(int x0, int y0, int x1, int y1) {
	cout << "B" << endl;
	if (x0 > x1)swap(x0, x1), swap(y0, y1);//(x0,y0)->(x1,y1);
	bool negk = y1 < y0;//负斜率,沿x轴对称,画点时用-y
	if (negk) y0 = -y0, y1 = -y1;
	bool steepk = y1 - y0 > x1 - x0;// 斜率 |k|>1,交换x和y的位置
	if (steepk) swap(x0, y0), swap(x1, y1);
	int x = x0, y = y0, dx = x1 - x0, dy = y1 - y0;
	int e = -dx;
	for (int i = 0; i <= dx; i ++) {
		drawpixel(steepk ? y : x, negk ? (steepk ? -x : -y) : (steepk ? x : y));
		x += 1; e += 2 * dy ;
		if (e >= 0) y += 1, e -= 2  * dx;
	}
}


void showResult(vector<Vertex>& VertexArray) {
	//把裁剪后的结果显示出来
	glColor3ub(20, 160, 93);
	int len = VertexArray.size();
	for (int i = 0; i < VertexArray.size(); i++) {
		cout << "裁剪后点的坐标为(" << VertexArray[i].x << "," << VertexArray[i].y << ")" << endl;
		Bresenham(VertexArray[i].x, VertexArray[i].y,VertexArray[(i + 1) % len].x, VertexArray[(i + 1) % len].y);		
		glColor3ub(20, 160, 93);
		glPointSize(7);
		glBegin(GL_POINTS);
		glVertex2i(VertexArray[i].x, VertexArray[i].y);
		glVertex2i(VertexArray[(i + 1) % len].x, VertexArray[(i + 1) % len].y);
		glEnd();
		glLineWidth(1);
	}
	glFlush();
}




void SutherlandHogmanClip(vector<Vertex>& InVertexArray, vector<Vertex>& OutVertexArray, Edge ClipBoundary, int Inlength) {
	Vertex S, P, ip;
	S = InVertexArray[Inlength - 1];
	for (int j = 0; j < Inlength; j++) {
		P = InVertexArray[j];
		if (Inside(P, ClipBoundary)) {
			if (Inside(S, ClipBoundary)) {
				cout << "情况1" << endl;
				//SP在窗口内,情况(1)
				OutVertexArray.push_back(P);
				//Output(P, Outlength, OutVertexArray);
			}
			else {//S在窗口外,情况(4)
				cout << "情况4" << endl;
				Intersect(S, P, ClipBoundary, ip);
				OutVertexArray.push_back(ip);
				OutVertexArray.push_back(P);
				//Output(ip, Outlength, OutVertexArray);
				//Output(P, Outlength, OutVertexArray);
			}
		}
		else if (Inside(S, ClipBoundary)) {
			cout << "情况3" << endl;
			//S在窗口内,P在窗口外,情况(3)
			Intersect(S, P, ClipBoundary, ip);
			OutVertexArray.push_back(ip);
			cout << "ip的坐标为" << ip.x << " , " << ip.y << endl;
			cout << "刚才入数组的点的坐标为" << OutVertexArray.back().x << " , " << outputVertex.back().y << endl;
			//Output(ip, Outlength, OutVertexArray);
		}
		else {
			cout << "情况2" << endl;
		}
		S = P;
	}
}

void drawpoint(int x, int y) {
	glColor3ub(211, 82, 70);
	glBegin(GL_POINTS);
	glVertex2f(x, y);
	glEnd();
	glFlush();
}
void mykeyboard(unsigned char key, int x, int y) {
	if (key == 'f' && inputVertex.size()) {
		glColor3ub(75, 140, 255);
		glBegin(GL_LINES);
		glVertex2d(last_x, last_y);
		glVertex2d(inputVertex[0].x, inputVertex[0].y);
		glEnd();
		glFlush();
	}
	if (key == 'c') {
		polygonClip();
	}
}
void myDisplay();
void mymouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		inputVertex.push_back({ x,y });
		drawpoint(x, y);
		if (last_x >= 0 && last_y >= 0) {
			cout << "可以画线" << endl;
			glColor3ub(75, 140, 255);
			glBegin(GL_LINES);
			glVertex2i(last_x, last_y);
			glVertex2i(x, y);
			glEnd();
			glFlush();
		}
		cout << "刚才加入的坐标是" << x << "," << y << endl;
		last_x = x; last_y = y;
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
		cout << "点击了鼠标右键" << endl;
		myDisplay();
		inputVertex.clear(); outputVertex.clear();
		memset(vis, 0, sizeof vis);
		last_x = -1; last_y = -1;
	}
}


void myDisplay() {
	cout << "调用了一次回调函数" << endl;
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	//绘制裁剪区域
	glColor3ub(255, 205, 68);
	glLineWidth(2);
	glBegin(GL_LINES);
	//1、L
	glVertex2i(wmin, hmin);
	glVertex2i(wmin, hmax);
	//2、B
	glVertex2i(wmin, hmin);
	glVertex2i(wmax, hmin);
	//3、R
	glVertex2i(wmax, hmin);
	glVertex2i(wmax, hmax);
	//4、T
	glVertex2i(wmin, hmax);
	glVertex2i(wmax, hmax);
	glEnd();
	glFlush();
}
void init() {
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT);
	glPointSize(7);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluOrtho2D(0, window_size, window_size, 0);
	myDisplay();
}
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);
	//glutMotionFunc(dragMouse);
	glutMainLoop();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值