Go to the documentation of this file.00001 #ifndef vgl_convex_hull_2d_txx_
00002 #define vgl_convex_hull_2d_txx_
00003 #include "vgl_convex_hull_2d.h"
00004
00005 #include <vcl_cstdlib.h>
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #if 0
00035 static void print_hull(double **P, int m)
00036 {
00037 for (int i=0; i<m; i++)
00038 vcl_cout << (P[i]-points[0])/2) << ' ';
00039 vcl_cout << vcl_endl;
00040 }
00041 #endif // 0
00042
00043 static int ccw(double **P, int i, int j, int k)
00044 {
00045 double a = P[i][0] - P[j][0],
00046 b = P[i][1] - P[j][1],
00047 c = P[k][0] - P[j][0],
00048 d = P[k][1] - P[j][1];
00049 return a*d - b*c <= 0;
00050 }
00051
00052
00053 #define CMPM(c,A,B) \
00054 v = (*(double*const*)A)[c] - (*(double*const*)B)[c];\
00055 if (v>0) return 1;\
00056 if (v<0) return -1
00057
00058 static int cmpl(const void *a, const void *b)
00059 {
00060 double v;
00061 CMPM(0,a,b);
00062 CMPM(1,b,a);
00063 return 0;
00064 }
00065 #undef CMPM
00066
00067 static int cmph(const void *a, const void *b) {return cmpl(b,a);}
00068
00069
00070 static int make_chain(double** V, int n, int (*cmp)(const void*, const void*))
00071 {
00072 vcl_qsort(V, n, sizeof(double*), cmp);
00073 int s = 1;
00074 for (int i=2; i<n; i++) {
00075 while (s>=1 && ccw(V, i, s, s-1)) --s;
00076 ++s;
00077 double* t = V[s]; V[s] = V[i]; V[i] = t;
00078 }
00079 return s;
00080 }
00081
00082 static int ch2d(double **P, int n)
00083 {
00084 int u = make_chain(P, n, cmpl);
00085 if (!n) return 0;
00086 P[n] = P[0];
00087 return u+make_chain(P+u, n-u+1, cmph);
00088 }
00089
00090 template <class T>
00091 vgl_convex_hull_2d<T>::
00092 vgl_convex_hull_2d (vcl_vector<vgl_point_2d<T> > const& points)
00093 {
00094 hull_valid_ = false;
00095 points_ = points;
00096 }
00097
00098 template <class T>
00099 void vgl_convex_hull_2d<T>::compute_hull()
00100 {
00101
00102 int N = points_.size();
00103 double * array = new double[2*N];
00104 double** points = new double*[N];
00105 double** P = new double*[N+1];
00106 for (int i = 0; i<N; i++)
00107 points[i]=&array[2*i];
00108
00109 for (int n = 0; n<N; n++)
00110 {
00111 points[n][0]=(double)points_[n].x();
00112 points[n][1]=(double)points_[n].y();
00113 P[n] = &points[n][0];
00114 }
00115
00116 int n_hull = ch2d(P, N);
00117
00118
00119 vcl_vector<vgl_point_2d<T> > temp;
00120 for (int i = 0; i<n_hull; i++)
00121 {
00122 vgl_point_2d<T> p((T)P[i][0], (T)P[i][1]);
00123 temp.push_back(p);
00124 }
00125
00126 if (P[0][0] != P[n_hull][0] || P[0][1] != P[n_hull][1])
00127 temp.push_back(vgl_point_2d<T>((T)P[n_hull][0], (T)P[n_hull][1]));
00128
00129
00130 hull_ = vgl_polygon<T>(temp);
00131
00132 delete [] array;
00133 delete [] points;
00134 delete [] P;
00135 hull_valid_ = true;
00136 }
00137
00138 template <class T>
00139 vgl_polygon<T> vgl_convex_hull_2d<T>::hull()
00140 {
00141 if (!hull_valid_)
00142 this->compute_hull();
00143 return hull_;
00144 }
00145
00146
00147 #undef VGL_CONVEX_HULL_2D_INSTANTIATE
00148 #define VGL_CONVEX_HULL_2D_INSTANTIATE(T) \
00149 \
00150 \
00151 template class vgl_convex_hull_2d<T >
00152
00153 #endif // vgl_convex_hull_2d_txx_