原作者:张林
#include <iostream>
#include <time.h>
#include <vector>
#include <iomanip>
#include <stdlib.h>
#include <math.h>
using namespace std;
int main()
{
int i,
j,
n , //行数
m = 2;//列数
cout << "How many dots do you want:";
cin>>n;
srand( (unsigned)time( NULL ) );
//用vector建立n*2维数组,存储随机产生的点的横纵坐标值
//注意下面这一行:vector<int后两个">"之间要有空格!否则会被认为是重载">>"。
vector<vector<int> > vecInt(n, vector<int>(m));
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
{
vecInt[i][j] = rand() % 20;
}
for (i = 0; i < n; i++)
{
cout<<"Point"<<i+1<<":"<<setw(2)<<"("<<vecInt[i][0]<<","<<vecInt[i][1]<<")"<<endl;
}
//找横坐标最小的点
int min = vecInt[0][0];
int count = 0;
for(i=1; i<n; i++ )
{
if( vecInt[i][0] < min)
{ min = vecInt[i][0];
count = i+1 ;
}
}
cout<<"The convex closure of these dots are:"<<endl;
//按向量夹角最小,依次找凸包点
//min为当前寻找到的满足向量夹角最小的点,last为在min前一个找到的点
int min1,min2,nn;
nn=n;
int p3x,p3y;
min1=vecInt[count-1][0];
min2=vecInt[count-1][1];
int last1=min1; //last的初始值自定
int last2=21;
p3x=min1;
p3y=min2;
//从数组中去掉横坐标最小点
// cout<<min1<<","<<min2<<endl;
int t;
for (t=count-1; t<n-1; t++)
{
vecInt[t][0] = vecInt[t+1][0];
vecInt[t][1] = vecInt[t+1][1];
}
n=n-1;
int v,x1,y1,x2,y2,count2,t1,t2;
t2=1;
double cosx,z,maxcos;
//依次寻找点
for(t1=0; t1<nn; t1++)
{
maxcos=-2;
for(v=0;v<n;v++)
{
x1=min1-last1;
y1=min2-last2;
x2=vecInt[v][0]-min1;
y2=vecInt[v][1]-min2;
z=sqrt((x1*x1+y1*y1)*(x2*x2+y2*y2));
cosx = (x1*x2+y1*y2)/z;//计算夹角余弦
if (cosx>maxcos)
{
maxcos=cosx;
count2=v;
}
}
cout<<setw(2)<<"("<<vecInt[count2][0]<<","<<vecInt[count2][1]<<")"<<endl; //输出符合要求的点
//将之前去掉的、横坐标最小的点添加回数组
while (t2==1)
{
vecInt[n][0]=p3x;
vecInt[n][1]=p3y;
t2=t2-1;
n=n+1;
}
//当找回到横坐标最小点时,退出循环,不再寻找
if ((vecInt[count2][0]==p3x)&&(vecInt[count2][1])==p3y) break;
//更新min和last值
last1 = min1;
last2 = min2;
min1 = vecInt[count2][0];
min2 = vecInt[count2][1];
//将输出的点从数组中删除
for (t=count2; t<n-1; t++)
{
vecInt[t][0]=vecInt[t+1][0];
vecInt[t][1]=vecInt[t+1][1];
}
n=n-1;
}
return 0;
}
—————————————————————–
稍微改改
// 从点vecInt中返回闭包点
vector< vector<double> > convHull(vector< vector<double> > &vecInt)
{
vector< vector<double> > ret;
int i, j;
int n = vecInt.size(); //行数
int m = 2; //列数
//找横坐标最小的点
double min = vecInt[0][0];
int count = 0;
for(i=1; i<n; i++ )
{
if( vecInt[i][0] < min)
{
min = vecInt[i][0];
count = i ;
}
}
//按向量夹角最小,依次找凸包点
//min为当前寻找到的满足向量夹角最小的点,last为在min前一个找到的点
int nn = n;
double min1 = vecInt[count][0];
double min2 = vecInt[count][1];
double last1 = min1; //last的初始值自定
double last2 = 21;
double p3x = min1;
double p3y = min2;
//从数组中去掉横坐标最小点
for (int t=count; t<n-1; t++)
{
vecInt[t][0] = vecInt[t+1][0];
vecInt[t][1] = vecInt[t+1][1];
}
n = n-1;
double v, x1, y1, x2, y2;
int count2 = 0, t2 = 1;
double cosx, z, maxcos;
int tn = n;
//依次寻找点
for(int t1=0; t1<nn; t1++)
{
maxcos = -2;
for(v=0; v<n; v++)
{
x1 = min1 - last1;
y1 = min2 - last2;
x2 = vecInt[v][0] - min1;
y2 = vecInt[v][1] - min2;
z = sqrt( (double)(x1*x1 + y1*y1) * (x2*x2 + y2*y2) );
cosx = (x1*x2 + y1*y2) / z;//计算夹角余弦
if (cosx > maxcos)
{
maxcos = cosx;
count2 = v;
}
}
vector<double> tmp;
tmp.push_back(vecInt[count2][0]);
tmp.push_back(vecInt[count2][1]);
ret.push_back(tmp);
//将之前去掉的、横坐标最小的点添加回数组
while (t2 == 1)
{
vecInt[n][0] = p3x;
vecInt[n][1] = p3y;
t2 -= 1;
n += 1;
}
//当找回到横坐标最小点时,退出循环,不再寻找
if ((vecInt[count2][0] == p3x) && (vecInt[count2][1]) == p3y)
{
break;
}
//更新min和last值
last1 = min1;
last2 = min2;
min1 = vecInt[count2][0];
min2 = vecInt[count2][1];
//将输出的点从数组中删除
for (int t=count2; t<n-1; t++)
{
vecInt[t][0] = vecInt[t+1][0];
vecInt[t][1] = vecInt[t+1][1];
}
n -= 1;
}
return ret;
}
void testConvHull()
{
vector< vector<double> > vecInt(4, vector<double>(2));
double x[] = {144.5, 146, 369, 370};
double y[] = {185.5, 375.5, 181.5, 363};
for(int i=0; i<4; i++)
{
vecInt[i][0] = x[i];
vecInt[i][1] = y[i];
}
vector< vector<double> > K = convHull(vecInt);
for(int i=0; i<K.size(); i++)
cout << K[i][0] << ", " << K[i][1] << endl;
}