Open gl判斷任意多邊形的凹凸性

思路:通過鼠標響應函數輸入n個頂點(n>=3)顯示多邊形,鼠標左擊加一個頂點,鼠標右擊顯示順序相連的多邊形。需要建立多邊形數據結構(保存頂點表、邊信息,及其他信息)

判斷方法:爲多邊形每一個邊建立一個向量,凸多邊形所有相鄰的2邊的向量的差積的z分量均爲同號。如果出現某些爲正,某些爲負,則爲凹多邊形。

 

/*  數學知識補充:
將向量用座標表示(三維向量), 
若向量a=(a1,b1,c1),向量b=(a2,b2,c2), 
則 
向量a·向量b=a1a2+b1b2+c1c2    ------------向量點乘 
向量a×向量b=                  ------------向量叉乘
| i j k| 
|a1 b1 c1| 
|a2 b2 c2| 
=(b1c2-b2c1,c1a2-a1c2,a1b2-a2b1) 
(i、j、k分別爲空間中相互垂直的三條座標軸的單位向量)。
*/
#include <iostream>
#include <vector>
#include <iterator>
#include "glut.h"
using namespace std;
struct vertex 
{
	vertex(GLint _x,GLint _y):x(_x),y(_y)
	{
	}
	GLint x;
    GLint y;
};

class side    
{
public:
    side(vertex _begin,vertex _end):begin(_begin),end(_end)
	{
		x=end.x-begin.x;
		y=end.y-begin.y;
		z=0;
	}

public:
	vertex begin;
	vertex end;

	GLint x;
	GLint y;
	GLint z;
};

// 一個全局函數,求2個邊的差積
GLint getchajiZ(const side& left,const side& right)
{
	// (a1,b1,c1) (a2,b2,c2)
	// z=a1b2-a2b1
	return left.x * right.y - right.x * left.y;
}

vector<vertex> vecVertex;    // 因爲頂點的數量不固定,由用戶左擊次數決定,所以採用vector向量容器
vector<side>   vecSide;
vector<int>    vecZ;
 
void init(void)
{
    
	glClearColor(0.0,0.0, 1.0, 1.0);

	glMatrixMode(GL_PROJECTION);//設置投影矩陣
	gluOrtho2D(0.0, 400.0, 0.0, 300.0);//二維視景區域

	glColor3f(1.0,0.0,0.0);
	glPointSize(13.0);//點的大小
}

void displayFcn(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_POLYGON);                     // 繪製模式
	glColor3f(200.0f,270.0f,0.0f);

	vector<vertex>::iterator it=vecVertex.begin();
	int i=0;
	for(;it!=vecVertex.end();it++,i++)
	{
		
		if (it!=vecVertex.begin())     // 先取得每個邊的向量保存到容器vecSide
		{
			side aSide(vecVertex[i-1],vecVertex[i]);
			vecSide.push_back(  aSide );                     
		}
		glVertex3i((*it).x,(*it).y,0);       // 畫出一個頂點
		
		if (i == vecVertex.size() -1 )  
		{
			side aSide(vecVertex[i],vecVertex[0]);   // 還有一個首尾相連的邊
			vecSide.push_back(  aSide ); 
		}
	}
	
	// 現在想辦法得到chajiZ  ---差積的z
	int size=vecSide.size();
	for (i=0;i<size;i++)
	{
		int chajiZ;
		chajiZ=getchajiZ(vecSide[i],vecSide[(i+1)%size]);
		
		vecZ.push_back(chajiZ);
		cout<<chajiZ<<endl;                    // 打印出每個差積的z值
	}
	for (i=0;i<vecZ.size();i++)
	{
		if (vecZ[i]*vecZ[ (i+1) % vecZ.size() ] <0  )  // 有異號
		{
			cout<<"凹多邊形!!!!!!!"<<endl;
			break;
		}
		
		if(i==vecZ.size()-1)
		{
			cout<<"凸多邊形!!!"<<endl;
			break;
		}
	}

	glEnd();
    glFlush();
}

void plotpoint(GLint x, GLint y)
{
	// 畫出臨時的一個點
	glBegin(GL_POINTS);
	glVertex2i(x,y);
	glEnd();
	
	vecVertex.push_back(vertex(x,y));    // 不用new,全局vector容器保存局部對象可以的
}

void mouse(GLint button, GLint action, GLint x,GLint y)
{
	if (button==GLUT_LEFT_BUTTON && action==GLUT_DOWN)
	{
		plotpoint(x,300-y);
	}
	glFlush();

	if (button==GLUT_RIGHT_BUTTON && action==GLUT_DOWN)
	{
		glutPostRedisplay();//重繪窗口  
	//	vecVertex.clear();     // 發現一旦清除,就不能顯示了
	//  這邊順便判斷下是否爲凸多邊形(所有向量差積的z都同號)		
	}	
}

void 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();
	
}

 

運行:

                                                                                    凸多邊形

 

                                                                        一個凹點對應一個和別的周圍異號的叉積的z值


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章