凸包问题(1)-----步进法

  讲解ppt 

#include
#include
#include
#include
using namespace std;

vector> findNodes(vector>& arr);
bool isOrigin(vector& a, vector& b);
bool isOnLeft(vector curNode, vector topMinuOne, vector top);
double distance(vector &a, vector &b);
void test1();
void test2();

int main() {
	test1();   //当坐标数组为空时候,测试1
	test2();  //当扫描时候有多个坐标在一条直线上时,测试2
}

void test1() {
	cout << "test1()输入为空数组:" << endl;
	vector> temp;
	if (findNodes(temp).size() == 0) {
		cout << "test1()输出为空数组,正确" << endl << endl << "-------------" << endl;
	}
	else {
		cout << "test1()输出不为空数组,错误:" << endl << endl << "--------------" << endl;
	}
}

void test2() {
	vector> temp = { { 1,1 },{ 2,2 },{ 2,0 },{ 2,4 },{ 3,3 },{ 4,2 } };
	//vector>     temp = { {1,1},{2,1},{3,1},{2,2},{3,3},{2,3},{1,3} };
	//vector>     temp = { {1,1},{1,1},{1,1},{1,1},{1,1},{1,1} };
	cout << "test2()输入是:     " << "{
    {1,1},{2,2},{2,0},{2,4},{3,3},{4,2}}" << endl;
	vector> ans = findNodes(temp);
	cout << "test2()输出结果是:{";
	for (int i = 0; i < ans.size(); i++) {
		cout << '{' << ans[i][0] << "," << ans[i][1] << "},";
	}
	cout << '}' << endl;
	cout << "test2()正确结果是:" << "{
    {2,0},{4,2},{2,4},{1,1}}";
}

//Description: 找出凸包上的坐标点,会先找到一个极点然后进行逆时针扫描
vector> findNodes(vector>& arr) {

	sort(arr.begin(), arr.end(), isOrigin); //排序目的有两个,一是用于查找第一个节点(左下角)
	int nodeNum = arr.size();				//二是为了给坐标点去重
	for (int i = 0; i < nodeNum - 1; i++) {
		if ((arr[i][0] == arr[i + 1][0]) && (arr[i][1] == arr[i + 1][1])) {
			arr.erase(arr.begin() + i);
			nodeNum = arr.size();
			i--;
		}
	}

	nodeNum = arr.size(); //计算去重后剩下的坐标点的个数
	if (nodeNum <= 2) { //数组为空或者坐标点为1,2这些简单情况就直接返回
		return arr;
	}

	int originPoint = 0;
	vector> ans;
	ans.push_back(arr[0]);	//把极点先存入

	int curPoint = originPoint;
	do {
		int nextPoint = -1;  //表示随便选一个点就可以
		for (int i = 0; i < arr.size(); i++) {
			if (i != curPoint && i != nextPoint && (nextPoint == -1 || !isOnLeft(arr[i], arr[curPoint], arr[nextPoint]))) {
				nextPoint = i;  
			}
		}
	ans.push_back(arr[nextPoint]);
	curPoint = nextPoint;
	} while (originPoint != curPoint);
	ans.pop_back();
	return ans;
}

//Description: 判断三点构成的连线的相对位置
bool isOnLeft(vector cur, vector topMinuOne, vector top) {
	int cross = (cur[0] - topMinuOne[0])*(top[1] - topMinuOne[1]) - (top[0] - topMinuOne[0])*(cur[1] - topMinuOne[1]); //x1y2-x2y1 计算叉积
	if (cross > 0) {
		return false;
	}
	else if (cross < 0) {
		return true;
	}
	else { //叉积等于0的时候,说明点共线,要进行判断一下
		if (distance(cur, topMinuOne) > distance(top, topMinuOne)) {
			return false;
		}
		return true;
	}
}

bool isOrigin(vector& a, vector& b) {
	if (a[1] == b[1]) { //纵坐标相等的时候,横坐标小的在前
		return a[0] < b[0];
	}
	return a[1] < b[1];
}

double distance(vector &a, vector &b) {
	return (pow((a[0] - b[0]), 2) + pow((a[1] - b[1]), 2));
}

 

你可能感兴趣的:(凸包问题(1)-----步进法)