凸包求取

来源:互联网 发布:一个二次元软件 有后山 编辑:程序博客网 时间:2024/06/05 09:36

参加了一场在线笔试,有点匆匆忙忙,下线后重写了一下:

#include"Graham.h"void Swap(SPoint **m_Point,int i,int j){    SPoint temp;    temp.x=(*m_Point)[i].x;    temp.y=(*m_Point)[i].y;    temp.angle=(*m_Point)[i].angle;    (*m_Point)[i].x=(*m_Point)[j].x;    (*m_Point)[i].y=(*m_Point)[j].y;    (*m_Point)[i].angle=(*m_Point)[j].angle;    (*m_Point)[j].x=temp.x;    (*m_Point)[j].y=temp.y;    (*m_Point)[j].angle=temp.angle;}int _Partition(SPoint* TPoint,int left,int right){    int pivot=left;    int i=left+1;    int j=right;    while(1)    {        while(TPoint[i].angle<TPoint[pivot].angle&&i<=right) {i=i+1;}        while(TPoint[j].angle>TPoint[pivot].angle&&j>left) {j=j-1;}        if(i<j) { Swap(&TPoint,i,j); }        else break;    }    Swap(&TPoint,pivot,j);    return j;}void Quick_Sort(SPoint* TPoint,int left,int right){    if(left<right)    {       int Partition=_Partition(TPoint,left,right);       Quick_Sort(TPoint,left,Partition-1);       Quick_Sort(TPoint,Partition+1,right);    } }int Find_Minumy_Point(SPoint *m_Point,int nLen){    int mid=(nLen-1)/2;    float minumy=(float)MINUM;    int res=-1;    for(int i=0;i<=mid;i++)    {      if(m_Point[i].y<m_Point[nLen-1-i].y)      {        if(m_Point[i].y<minumy)         {          minumy=m_Point[i].y;          res=i;        }        else        {        if(m_Point[i].y==minumy&&res!=-1)         {          if(m_Point[i].x<=m_Point[res].x)          {              minumy=m_Point[i].y;              res=i;          }        }        }      }      else      {        if(m_Point[nLen-i-1].y<minumy)           {            minumy=m_Point[nLen-1-i].y;            res=nLen-1-i;          }        else        {        if(m_Point[nLen-i-1].y==minumy&&res!=-1)           {            if(m_Point[nLen-1-i].x<=m_Point[res].x)            {            minumy=m_Point[nLen-1-i].y;            res=nLen-1-i;            }          }        }      }    }    return res;}void Compute_Angles(SPoint *m_Point,SPoint *T_Point,int nLen,int index){    float m_tan,x,y;    Swap(&m_Point,0,index);    for(int i=1;i<nLen;i++)    {       x=m_Point[i].x-m_Point[0].x;       y=m_Point[i].y-m_Point[0].y;       if(x>0&&y>0) m_tan=atan(y/x);       if(x>=0&&y==0)m_tan=0;       if(x>0&&y<0) m_tan=2*val-atan((-y)/x);       if(x<0&&y==0)m_tan=-val;       if(x<0&&y>0) m_tan=val-atan(y/(-x));       if(x<0&&y<0) m_tan=val+atan((-y)/x);       if(x==0&&y>0)m_tan=0.5*val;       if(x==0&&y<0)m_tan=1.5*val;       //m_Tan=atan2f(y,x);       T_Point[i-1].x=m_Point[i].x;       T_Point[i-1].y=m_Point[i].y;       T_Point[i-1].angle=m_tan;    }     for(int i=0;i<nLen-1;i++)     printf("%f,%f,%f\n",T_Point[i].x,T_Point[i].y,T_Point[i].angle);     printf("\n\n\n");    Quick_Sort(T_Point,0,nLen-2);}float distance(SPoint *T_Point,SPoint pt,int flag){      float dis=(T_Point[flag].x-pt.x)*(T_Point[flag].x-pt.x)+(T_Point[flag].y-pt.y)*(T_Point[flag].y-pt.y);      dis=sqrtf(dis);      return dis;}void sort_by_distance(SPoint *T_Point,SPoint pt,int start,int end){     float dis1,dis2;     for(int m=start;m<end;m++)     {       for(int n=m+1;n<end;n++)       {         dis1=distance(T_Point,pt,m);         dis2=distance(T_Point,pt,n);         if(dis1>dis2) Swap(&T_Point,m,n);       }     }}void Adjustment(SPoint *T_Point,SPoint pt,int nLen){     int p=0,q;     int dis1,dis2;     while(p<nLen)     {       q=p+1;       if(q>=nLen) break;       else       {           while(T_Point[p].angle==T_Point[q].angle&&q<nLen)           {              q=q+1;           }           if(p+1==q)           {             p=p+1;           }           else           {               sort_by_distance(T_Point,pt,p,q-1);           }       }     }}int GraHam(SPoint *m_Point,SPoint *T_Point,p2d* CS,int nLen){     int index=Find_Minumy_Point(m_Point,nLen);     printf("The point x=%f,y=%f has minumy\n",m_Point[index].x,m_Point[index].y);          Compute_Angles(m_Point,T_Point,nLen,index);     Adjustment(T_Point,m_Point[0],nLen-1);          for(int i=0;i<nLen-1;i++)     printf("%f,%f,%f\n",T_Point[i].x,T_Point[i].y,T_Point[i].angle);     CS[0].x=T_Point[nLen-2].x;     CS[0].y=T_Point[nLen-2].y;     CS[1].x=m_Point[0].x;     CS[1].y=m_Point[0].y;     int sp=1;     int k=0;     float D;     while(k<nLen-1)     {       //栈顶两点以及扫描线上一点所构成的三角区符号       //D=CS[sp-1].x*CS[sp].y+CS[sp].x*T_Point[k].y+T_Point[k].x*CS[sp-1].y       //-CS[sp-1].y*CS[sp].x-CS[sp].y*T_Point[k].x-T_Point[k].y*CS[sp-1].x;              D=(T_Point[k].x-CS[sp].x)*(CS[sp-1].y-CS[sp].y)-(CS[sp-1].x-CS[sp].x)*(T_Point[k].y-CS[sp].y);       if(D>=0)       {         sp=sp+1;         CS[sp].x=T_Point[k].x;         CS[sp].y=T_Point[k].y;         k=k+1;       }       else       {         sp=sp-1;         /*if(sp==0)          {          CS[sp].x=T_Point[k].x;          CS[sp].y=T_Point[k].y;         }*/       }                          }     return (sp+1);}

#ifndef _GRAHAM_H_#define _GRAHAM_H_#include <cstdlib>#include <iostream>#include <cv.h>#include <cxcore.h>#include <highgui.h>#include<Math.h>using namespace std;#define MINUM 65536const float val=3.1415926;typedef float FPoint;typedef struct{  FPoint x;  FPoint y;}p2d;typedef struct{   float x;   float y;   float angle;}SPoint;void Swap(SPoint **m_Point,int i,int j);int _Partition(SPoint* TPoint,int left,int right);void Quick_Sort(SPoint* TPoint,int left,int right);int Find_Minumy_Point(SPoint *m_Point,int nLen);void Compute_Angles(SPoint *m_Point,SPoint *T_Point,int nLen,int index);float distance(SPoint *T_Point,SPoint pt,int flag);void sort_by_distance(SPoint *T_Point,SPoint pt,int start,int end);void Adjustment(SPoint *T_Point,SPoint pt,int nLen);int GraHam(SPoint *m_Point,SPoint *T_Point,p2d* CS,int nLen);#endif

/*****************************************************************Mail:zhjkobe2013@live.com***Author: zhang jie***Function: Graham algorithms***cpp:main.cpp***Create time:2014-12-26 12:26***Last Modify Time: 2014-12-26***************************************************************/#include "Graham.h"//凸壳问题的格雷厄姆#define WIDTH 640#define HEIGHT 480#define N 10const char* win_name="GraHam";int nCount=0;int re=0;void Record_Point_CallBack(int event,int x,int y,int flags,void* param);CvPoint pt;int main(int argc, char *argv[]){   IplImage* Img=cvCreateImage(cvSize(WIDTH,HEIGHT),IPL_DEPTH_8U,3);   cvZero(Img);   cvNamedWindow(win_name);   CvPoint* m_Point=new CvPoint[N];   char c;   cvSetMouseCallback(win_name,Record_Point_CallBack,(void*)Img);loop:   while(1)   {      if(nCount>=1&&nCount<=N)      {      m_Point[nCount-1].x=pt.x;      m_Point[nCount-1].y=pt.y;      }      //printf("nCount=%d\n",nCount);      cvShowImage(win_name,Img);      c=cvWaitKey(100);      if(c=='r') { nCount=0; cvZero(Img); }       if(nCount==N+1) break;     }      SPoint *p_Point=new SPoint[N];   SPoint *T_Point=new SPoint[N-1];   p2d* CS=new p2d[N+1];   for(int i=0;i<N;i++)   {      p_Point[i].x=(float)m_Point[i].x;      p_Point[i].y=(float)m_Point[i].y;      p_Point[i].angle=0.0;      printf("x=%d,y=%d\n",m_Point[i].x,m_Point[i].y);   }   printf("start\n");   int nIndex=GraHam(p_Point,T_Point,CS,N);   printf("nIndex=%d\n",nIndex);   CvPoint pt1,pt2;   for(int i=0;i<nIndex;i++)     {     pt1.x=(int)CS[i%nIndex].x;     pt1.y=(int)CS[i%nIndex].y;     pt2.x=(int)CS[(i+1)%nIndex].x;     pt2.y=(int)CS[(i+1)%nIndex].y;     printf("cs[%d].x=%f,cs[%d].y=%f\n",i,CS[i].x,i,CS[i].y);     cvLine(Img,pt1,pt2,cvScalar(0,0,255),1,8,0);     }       printf("Finish\n");   cvShowImage(win_name,Img);   re=re+1;   if(re==3)   cvSaveImage("res.bmp",Img);   nCount=0;   printf("nCount=%d,re=%d\n",nCount,re);goto loop;   cvWaitKey(0);   cvDestroyAllWindows();   cvReleaseImage(&Img);   if(p_Point) delete[] p_Point;   if(m_Point) delete[] m_Point;   if(CS) delete[] CS;   system("PAUSE");   return EXIT_SUCCESS;}void Record_Point_CallBack(int event,int x,int y,int flags,void* param){     IplImage* pImg=(IplImage*)param;     switch(event)     {       case CV_EVENT_LBUTTONDOWN:            {               pt.x=x;               pt.y=y;               if(nCount<N) cvCircle(pImg,cvPoint(pt.x,pt.y),1,cvScalar(255,0,0),1,8,0);               nCount+=1;            }       break;       case CV_EVENT_RBUTTONDOWN:            {                nCount=-1;                cvZero(pImg);            }       break;       default: break;     }}

效果如下:


0 0
原创粉丝点击