zoukankan      html  css  js  c++  java
  • [OpenGL] 绘制并且判断凹凸多边形、自相交多边形。

    #include <iostream>
    #include <ctime>
    #include <GL/glut.h>
    #include <math.h>
    #include <vector>
    
    using namespace std;
    
    struct Pos
    {
    	int x;
    	int y;
    };
    
    struct Edge
    {
    	int x1, x2;
    	int y1, y2;
    	int vx;
    	int vy;
    	int a, b, c;
    };
    
    struct Poly
    {
    	// 点集
    	int xx[100];
    	int yy[100];
    
    	// 边集
    	Edge Edges[100];
    
    	int plotNums = 0; //点数量
    	int edgeNums = 0; //边数量
    
    	// 记录凹点
    	int conv = 0;
    };
    
    Poly poly;
    
    
    // 求交点坐标
    Pos CrossPos(int p1,int p2){
    	Pos res;
    	int A1 = poly.Edges[p1].a;
    	int B1 = poly.Edges[p1].b;
    	int A2 = poly.Edges[p2].a;
    	int B2 = poly.Edges[p2].b;
    	int C1 = poly.Edges[p1].c;
    	int C2 = poly.Edges[p2].c;
    
    	int m = A1 * B2 - A2 * B1;
    	if (m == 0)
    		cout <<"第"<<p1<<"边和第"<<p2<<"边"<< "无交点" << endl;
    	else
    	{
    		res.x = (C2*B1 - C1 * B2) / m;
    		res.y = (C1*A2 - C2 * A1) / m;
    	}
    	return res;
    
    }
    
    // 判断点是否在线段内
    bool JudgeInLine(Pos pos,Edge edge)
    {
    	int maxX = edge.x1 >= edge.x2 ? edge.x1 : edge.x2;
    	int minX = edge.x1 <= edge.x2 ? edge.x1 : edge.x2;
    	int maxY = edge.y1 >= edge.y2 ? edge.y1 : edge.y2;
    	int minY = edge.y1 <= edge.y2 ? edge.y1 : edge.y2;
    	if (pos.x<=maxX && pos.x>=minX && pos.y<=maxY && pos.y>=minY)
    	{
    		return true;
    	}
    	return false;
    }
    
    // 求叉积 返回正负值
    int CrossProduct(int n)
    {
    	n = n % poly.edgeNums;
    	int np = (n + 1) % poly.edgeNums;
    	return (poly.Edges[n].vx*poly.Edges[np].vy - poly.Edges[np].vx*poly.Edges[n].vy) >= 0 ? 1 : -1;
    }
    
    // 切割凹多边形
    void ChangePoly() {
    	int convP = poly.conv; //凹点的下一个点
    	Pos interPos;
    
    
    	for (int i = 0; i < poly.edgeNums; i++)
    	{
    		if (i<convP-1 || i>convP+1)
    		{
    			interPos = CrossPos(convP, i);
    		}
    	}
    
    	glClearColor(0.0, 0.0, 0.0, 0.0);
    	glClear(GL_COLOR_BUFFER_BIT);
    	glBegin(GL_POLYGON);
    	glColor3f(1.0f, 0.0f, 0.0f);
    	for (int i = 0; i <= convP; i++)
    	{
    		glVertex2f(poly.xx[i], poly.yy[i]);
    	}
    	glVertex2f(interPos.x, interPos.y);
    	glEnd();
    
    	glBegin(GL_POLYGON);
    	glColor3f(0.0f, 1.0f, 1.0f);
    	glVertex2f(interPos.x, interPos.y);
    	for (int i=convP+1;i<poly.plotNums;i++)
    	{
    		glVertex2f(poly.xx[i], poly.yy[i]);
    	}
    	glEnd();
    
    	glFlush();
    }
    
    // 判断是什么多边形
    bool Judge()
    {
    	/*输出边信息*/
    	for (int i = 0; i < poly.edgeNums; i++)
    	{
    		cout << "Vx:" << poly.Edges[i].vx << "  " << "Vy:" << poly.Edges[i].vy << "  " << "A:" << poly.Edges[i].a<< "  " << "B:" << poly.Edges[i].b << "  " << "C:" << poly.Edges[i].c <<endl;
    	}
    
    	/*判断自交*/
    	Pos interPos;
    	if (poly.edgeNums > 3)
    		for (int i = 0; i < poly.edgeNums; i++)
    		{
    			interPos = CrossPos(i, (i + 2) % poly.edgeNums);
    			if (JudgeInLine(interPos, poly.Edges[i]) && JudgeInLine(interPos, poly.Edges[(i + 2) % poly.edgeNums]))
    			{
    				cout << "该多边形为自相交多边形" << endl;
    				return false;
    			}
    		}
    
    	/*判断凹凸*/
    	// 判断向量叉积 是否为同一正负
    	int judge;
    	if (CrossProduct(0) >= 0)
    		judge = 1;
    	else
    		judge = -1;
    	//判断每一个角,两边向量乘积是否同符号
    	for (int i = 1; i <= poly.edgeNums; i++)
    	{
    		if (judge*CrossProduct(i) < 0)
    		{
    			poly.conv = i;
    			ChangePoly();
    			cout << "该多边形为凹多边形" << endl;
    			return false;
    		}
    	}
    	cout << "该多边形为凸多边形" << endl;
    	return true;
    }
    
    void init(void)
    {
    	glClearColor(0.0, 0.0, 0.0, 0.0);
    
    	glMatrixMode(GL_PROJECTION);//设置投影矩阵
    	gluOrtho2D(0.0, 400.0, 0.0, 300.0);//二维视景区域
    
    	glColor3f(1.0, 0.0, 0.0);
    	glPointSize(3.0);//点的大小
    }
    
    void plotpoint(GLint x, GLint y)
    {
    	glBegin(GL_POINTS);
    	glVertex2i(x, y);
    	glEnd();
    }
    
    void displayFcn(void)
    {
    	glClearColor(0.0, 0.0, 0.0, 0.0);
    	glClear(GL_COLOR_BUFFER_BIT);
    	for (int i = 0; i < poly.plotNums; i++)
    	{
    		plotpoint(poly.xx[i], poly.yy[i]);
    	}
    	glBegin(GL_POLYGON);
    	for (int i = 0; i < poly.edgeNums; i++)
    	{
    		glVertex2f(poly.xx[i], poly.yy[i]);
    	}
    	glEnd();
    
    	glFlush();
    }
    
    void mouse(GLint button, GLint action, GLint x, GLint y)
    {
    	if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN)
    	{
    		poly.xx[poly.plotNums] = x;
    		poly.yy[poly.plotNums] = 300 - y;
    		cout << "x:" << x << "  " << "y:" << 300 - y << endl;
    		poly.plotNums++;
    		glutPostRedisplay();//重绘窗口
    	}
    	if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN)
    	{
    		poly.edgeNums = poly.plotNums;
    		if (poly.plotNums > 2)
    		{
    			for (int i = 1; i <= poly.plotNums; i++)
    			{
    				poly.Edges[i - 1].x1 = poly.xx[i - 1];
    				poly.Edges[i - 1].y1 = poly.yy[i - 1];
    				poly.Edges[i - 1].x2 = poly.xx[i%poly.plotNums];
    				poly.Edges[i - 1].y2 = poly.yy[i%poly.plotNums];
    				poly.Edges[i - 1].vx = poly.Edges[i - 1].x2 - poly.Edges[i - 1].x1;
    				poly.Edges[i - 1].vy = poly.Edges[i - 1].y2 - poly.Edges[i - 1].y1;
    				poly.Edges[i - 1].a = poly.Edges[i - 1].vy;
    				poly.Edges[i - 1].b = -poly.Edges[i - 1].vx;
    				poly.Edges[i - 1].c = poly.Edges[i - 1].x2 * poly.Edges[i - 1].y1 - poly.Edges[i - 1].x1 * poly.Edges[i - 1].y2;
    			}
    			if (Judge())
    				glutPostRedisplay();//重绘窗口
    		}
    	}
    }
    
    int main(int argc, char** argv)
    {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    	glutInitWindowPosition(50, 100);
    	glutInitWindowSize(400, 300);
    	glutCreateWindow("mouse");
    
    	init();
    	glutDisplayFunc(displayFcn);
    
    	glutMouseFunc(mouse);
    
    	glutMainLoop();
    
    }
    
    
  • 相关阅读:
    FastJson---高性能JSON开发包
    mybatis中大于等于小于等于的写法
    MarkDown 使用说明示例
    Get和Post的参数传值
    规则引擎 资料收集
    ORA-01033错误解决方案
    mybatis 参数为String,用_parameter 取值
    php中实现记住密码下次自动登录的例子
    php 应用 bootstrap-fileinput 上传文件 插件 操作的方法
    AJAX 跨域请求
  • 原文地址:https://www.cnblogs.com/ruoh3kou/p/9893427.html
Copyright © 2011-2022 走看看