思路:通过鼠标响应函数输入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值
本文介绍了一种通过用户交互绘制多边形并判断其为凸多边形还是凹多边形的方法。利用OpenGL和GLUT库实现图形界面,用户可通过鼠标左键添加顶点,鼠标右键完成多边形绘制。程序通过计算各边向量的叉积来判断多边形类型。
2244

被折叠的 条评论
为什么被折叠?



