凸包求解

做了一下在线测试,在匆忙中没把凸包代码很好的完善,下面给出源码和效果。

#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 65536
const 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

#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);
}

/**************************************************************
***Mail:zhjkobe2013@live.com
***Author: zhang jie
***Function: Graham algorithms
***cpp:main.cpp
***Create time:2015-04-10 12:26
***Last Modify Time: 2015-04-10
***************************************************************/
#include "Graham.h"
//凸壳问题的格雷厄姆
#define WIDTH 640
#define HEIGHT 480
#define N 10
const 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;
     }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值