乘胜追击再写一个点云凸包怎么找的代码好了,毕竟下一次更新也不知道是什么时候,太懒了,太懒了,不适合搞学术
啥是凸包呢,在网上随便找了一个图哈,大概意思就是每个转角的地方都是凸出去的,这个代码师兄也跟我说很简单很简单,行吧,反正我是想了好久才想出来的,可能师兄的简单==和我的简单不是一个量级吧
//叉乘
double multi(CCVector3 p1,CCVector3 p2,CCVector3 p0)
{
return ((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x));
}
//p1,p2的距离
double distance2(CCVector3 p1,CCVector3 p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
//找到点集的凸包
int convex_hull(QVector<CCVector3> *input,QVector<CCVector3> *output)
{
long npt=input->size();
if (npt< 0) return 0;
int i,j,k,top;
k=0; //找到最下且偏左的那个点
for(i=1;i<npt;i++)
if(input->at(i).y<input->at(k).y||(input->at(i).y==input->at(k).y&&(input->at(i).x<input->at(k).x)))
k=i;
CCVector3 tempts=input->data()[(0)];
CCVector3 firstpts=input->data()[(k)];
input->data()[(k)]=tempts;
input->data()[(0)]=firstpts;
//按极角从小到大,距离偏短进行排序
for(i=1;i<npt;i++)
{
k=i;
for(j=i+1;j<npt;j++)
if(multi(input->at(j),input->at(k),input->at(0))>0||(fabs(multi(input->at(j),input->at(k),input->at(0)))<=eps&&
(distance2(input->at(0),input->at(j))<distance2(input->at(0),input->at(k)))))
{
k=j; //k保存极角最小的那个点,或者相同距离原点最近
}
tempts=input->data()[(i)];
input->data()[(i)]=input->data()[(k)];
input->data()[(k)]=tempts;
}
//第三个点先入栈
double *stack=new double[npt+1];
stack[0]=0;
stack[1]=1;
stack[2]=2;
top=2; //判断与其余所有点的关系
for(i=3;i<npt;i++)
{
//不满足向左转角度大于45°的关系,栈顶元素出栈
while((multi(input->at(i),input->at(stack[top]),input->at(stack[top-1]))/(distance2(input->at(i),input->at(stack[top]))*distance2(input->at(stack[top]),input->at(stack[top-1])))>-0.1 ||fabs(multi(input->at(i),input->at(stack[top]),input->at(stack[top-1])))<=eps))
{
top--;
if(top==0)
break;
}
//当前点与栈内所有点满足向左关系,因此入栈
top++;
stack[top]=i;
}
/*//计算凸包的面积
area = 0;
for (i = 1; i < top; i++)
area += fabs(multi(input->at(stack[0]), input->at(stack[i]), input->at(stack[i+1]))); */
if(top==0)
return 0;
else
{
for(int i=0;i<top;i++)
{
CCVector3 pt_=input->at(stack[i]);
output->push_back(pt_);
}
return top;
}
delete[]stack;
}