轮廓的凸包寻找

本文轮廓凸包寻找主要是基于graham算法来实现的,具体的理论知识大家可以网上搜索下一大堆,这里盗用下他人的一张比较好描述该算法的图片安静


下面直接上代码:

struct ptInfo
{
	point_t* pt;
	int size;
};


//符号函数
int signPoint(float x);


//计算叉积
int crossPoint(const point_t a, const point_t b, const point_t c);


//比较两点的位置
int cmpPoint(const point_t a, const point_t b);


//通过两点的叉积来判别两者的相对位置
int compare(const point_t a, const point_t b, const point_t c);


//获取轮廓凸包
void get_convex_hull(point_t* p, point_t* pt, const int num, int* n);
#include "convxhull.h"


static int size = 0;


//计算两点之间的距离
int disPoint(const point_t a, const point_t b)
{
	return common_sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}


//符号函数
int signPoint(int x)
{
	return x == 0 ? 0 : (x > 0 ? 1 : -1);
}


//计算叉积
int crossPoint(const point_t a, const point_t b, const point_t c)
{
	//int temo = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);


	return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y));
}


//比较两点的位置
int cmpPoint(const point_t a, const point_t b)
{
	return (a.x < b.x || (signPoint(a.x - b.x) == 0 && a.y < b.y));
}


//通过两点的叉积来判别两者的相对位置
int compare(const point_t a, const point_t b, const point_t c)
{
	int sg = signPoint(crossPoint(a, b, c));
	if (sg != 0)
		return sg > 0; //左转;
	else     //共线;
		return disPoint(a, b) < disPoint(a, c);
}


//入栈
void push(point_t* S, point_t pt)
{
	S[size++] = pt;
}


//出栈
void pop(point_t* S)
{
	S[--size];
}


//交换两点
void swap(point_t* p, int x, int y)
{
	point_t pt = p[x];
	p[x] = p[y];
	p[y] = pt;
}


void quicksort(point_t *p,int n)
{
	int i, j, k = 0;
	point_t temp;


	for (i = 1; i < n - 1;++i){
		k = i;
		for (j = i + 1; j < n - 1; ++j){
			if (compare(p[0], p[j], p[i])){
				temp = p[i];
				p[i] = p[j];
				p[j] = temp;
			}
		}
	}
}


//获取轮廓凸包
void get_convex_hull(point_t* p, point_t* pt, const int num, int* n)
{
	size = 0;//因为是全局变量,所以每次进来要记得清零,不然会导致错误


	//寻找x坐标最小的点
	int min = -1;
	for (int j = 0; j < num; j++)
	{
		if (min == -1 || cmpPoint(p[j], p[min]))
			min = j;
	}


	//将x最小的点存储在第一个位置
	if (min != 0)
		swap(p,0,min);


	
	//极角快排
	//sort(1,num - 1,p);
	quicksort(p,num - 1);


	push(pt, p[0]);
	push(pt, p[1]);
	push(pt, p[2]);


	//边缘点寻找
	for (int i = 3; i < num; i++)
	{
		//剔除非左转的点
		if (crossPoint(pt[size - 2],pt[size - 1], p[i]) < 0)
			pop(pt);
		push(pt, p[i]);
	}




	*n = size;
}


代码运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值