OpenGL学习之求凸包

#include <iostream>
#include <math.h>
#include <gl/glut.h>

using namespace std;
typedef struct{double x,y;} Point;
void qsortpoint(Point s[],Point base,int start,int end);
void sortstartedge(Point s[],int nums);

void init()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glClearColor(0.0,0.0,0.0,1.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(-5.0,10,-5.0,10.0);
}
//向量(x1,y1),(x2,y2)的叉积
double CrossMul(double x1,double y1,double x2,double y2)
{
	return x1*y2-x2*y1;
}
//向量(x1,y1),(x2,y2)的点积
double DotMul(double x1,double y1,double x2,double y2)
{
	return x1*x2+y1*y2;
}
//跨立判断
//判断点c是在向量ab的逆时针方向还是顺时针方向,大于零逆时针,等于0则共线
double CrossMul(Point a,Point b,Point c)
{
	return CrossMul(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
//计算向量ab和ac点积
double DotMul(Point a,Point b,Point c)
{
	return DotMul(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
//判断浮点数符号
int doublecmp(double d)
{
	if(fabs(d)<10e-6)
		return 0;
	return d>0?1:-1;
}
//判断同一直线上的三个点位置,点c是否在点ab之间
bool betweenCmp(Point a,Point b,Point c)
{
	if(doublecmp(DotMul(c,a,b))<=0)
		return true;
	return false;
}
//判断j是否在base->i向量的左边或当共线时j是否位于它们的线段之间
bool isLeftorNearer(Point base,Point i,Point j)
{
	if(CrossMul(base,i,j)>0)
		return true;
	if(CrossMul(base,i,j)==0 && betweenCmp(base,i,j))
		return true;
	return false;
}
void swap(Point& a,Point& b)
{
	Point temp = b;
	b=a;
	a=temp;
}
//以s中的最低点为参考点,对其他所有点进行极角排序(逆时针)
//共线时离参考点较远的点排在前面,凸包的起始边共线点从近到远排列
void sortpoint(Point s[],int nums)
{
	//找最低点
	for(int i=1;i<nums;i++)
	{
		if(s[i].y<s[0].y || (s[i].y==s[0].y && s[i].x<s[0].x))
			swap(s[0],s[i]);
	}
	qsortpoint(s,s[0],1,nums);
	//将起始边上的共线点重新排列
	sortstartedge(s,nums);
}
void sortstartedge(Point s[],int nums)
{
	int i,j;
	for(i=2;i<nums;i++)
	{
		if(CrossMul(s[0],s[1],s[i])!=0)
			break;
	}
	for(j=1;j<(i+1)/2;j++)
		swap(s[j],s[i-j]);
}

//将点按极角逆时针排序
void qsortpoint(Point s[],Point base,int start,int end)
{
	if(start>=end)
		return;
	Point partition = s[end-1];
	int i=start-1,j=start-1;
	while(++j<end-1)
	{
		if(isLeftorNearer(base,s[j],partition))
		{
			swap(s[++i],s[j]);
		}
	}
	swap(s[++i],s[end-1]);
	qsortpoint(s,base,start,i);
	qsortpoint(s,base,i+1,end);
}
void ConvexHull(Point s[],int nums,Point result[],int& resultnums)
{
	sortpoint(s,nums);

	resultnums = 0;
	if(nums<=3)
	{
		for(int i=0;i<nums;i++)
			result[resultnums++] = s[i];
		return;
	}
	int top=0;
	int i;
	for(i=0;i<2;i++)
		result[top++] = s[i];
	while(i<nums)
	{
		//用<号判断则包含凸包边上的共线点,<=号判断则只包含凸包顶点
		if(CrossMul(result[top-2],result[top-1],s[i])<=0)
		{
			top--;
		}
		else
		{
			result[top++] = s[i++];
		}
	}
	//最后加入起点形成闭包
	while(CrossMul(result[top-2],result[top-1],s[0])<=0)
	{
		top--;
	}
	result[top++]=s[0];
	resultnums = top;
}

Point pa[] = {{1,2},{0,0},{5,5},{3,0},{4,0},
{4,1},{4,2},{4,3},{4,4},
{3,4},{2,4},{1,4},{0,5},
{8,3},{0,2},{0,1},{2,2},{1,1}};

bool flag = true;
//static int convex_points = 0;
void draw_line()
{
	cout<<"convex hull is:"<<endl;
	Point  result[18];
	for (int i=0;i<18;i++)
	{
		result[i].x = -10;
		result[i].y = -10;
	}
	int nums;
	ConvexHull(pa,18,result,nums);
	cout<<"nums is adsadas:"<<nums<<endl;
	for(int i=0;i<nums;i++)
	{
		cout<<result[i].x <<"," <<result[i].y<<endl;
	}
	int j=0;
	int temp = 0;
	while(1)
	{
		if ((result[nums-1].y == pa[j].y) && (pa[j].x > result[nums-1].x))
		{
			temp = pa[j].x;
		}
		j++;
		if (j == 18)
		{
			break;
		}

	}
	cout<<"the temp is : "<<temp<<endl;
	result[nums].x = temp;
	result[nums].y = result[nums-1].y;
	//return result;
	cout<<"the result is :"<<endl;
	for (int i=0;i<nums+1;i++)
	{
		cout<<"result is: "<<result[i].x<<","<<result[i].y<<endl;
	}
	glBegin(GL_LINE_LOOP);
		for (int i=0;i<nums+1;i++)
		{
			glVertex2f(result[i].x,result[i].y);
		}
	glEnd();
	glFlush();
}

void draw_line();

void display()
{
	if (flag == true)
	{
		glColor3f(1.0,0.0,0.0);
		glPointSize(5);
		//Point *p = number_point();
		glBegin(GL_POINTS);
			for (int i=0;i<18;i++)
			{
				glVertex2f(pa[i].x,pa[i].y);
			}
		glEnd();
		draw_line();
		glFlush();
	}
	else
	{
		flag = false;
	}
}



///
/*
以上是把网上的凸包程序用opengl显示出来了而已,但是有很多的问题,这个程序只是找到了凸包中的最大点,但是连接起来还是有很多的问题
需要=做的就是找到最后到第一个点的中间点
*/

int main(int argc,char **argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(200,200);
	glutInitWindowSize(500,500);
	glutCreateWindow("hello");
	init();
	glutDisplayFunc(display);
	glutMainLoop();
	return 0;
}

凸包问题是很经典的数学问题,我之前自己写了一个quick hull的程序,最后发现迭代的时候出现问题,这里线给出别人的程序内核,我在外面加了一个显示的壳

凸包,什么是凸包??

凸包是一个图形学的概念,不严谨的说就是给一个点集,求出能够包围这个点集的最小的一个凸多边形,有很多这种方面的算法,主要的方法直接看wiki和百科比我说的全多了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值