Go to the documentation of this file.00001
00002 #ifndef vgl_convex_txx_
00003 #define vgl_convex_txx_
00004
00005
00006 #include "vgl_convex.h"
00007 #include <vcl_limits.h>
00008 #include <vcl_cmath.h>
00009 #include <vcl_list.h>
00010
00011
00012
00013
00014
00015
00016 template <class T>
00017 static T get_nc_angle(const vgl_vector_2d<T> &last_dir,
00018 const vgl_point_2d<T> ¤t,
00019 const vgl_point_2d<T> &next)
00020 {
00021 vgl_vector_2d<T> v = next - current;
00022 double eps = vcl_sqrt(current.x() * current.x() + current.y() * current.y())
00023 * vcl_numeric_limits<T>::epsilon();
00024
00025
00026
00027 if (v.length() <= eps) return (T)2.0;
00028 return T(-cos_angle(last_dir, v));
00029 }
00030
00031 template <class T>
00032 vgl_polygon<T> vgl_convex_hull(vcl_vector<vgl_point_2d<T> > const& points)
00033 {
00034 vgl_polygon<T> hull(1);
00035 if (points.empty()) return hull;
00036
00037 typedef typename vcl_list<vgl_point_2d<T> >::iterator ITER;
00038
00039
00040 vcl_list<vgl_point_2d<T> > pts(points.begin(), points.end());
00041
00042
00043 ITER start = pts.begin();
00044 for (ITER i=pts.begin(); i != pts.end(); ++i)
00045 if (i->x() < start->x()) start=i;
00046
00047 vgl_point_2d<T> first = *start;
00048 vgl_point_2d<T> current = first;
00049 vgl_vector_2d<T> last_dir(0,1);
00050 hull.push_back(first);
00051 pts.erase(start);
00052 bool not_starting = false;
00053
00054 while (true)
00055 {
00056
00057 if (pts.empty()) return hull;
00058
00059
00060 double nc_angle_to_first = get_nc_angle(last_dir, current, first);
00061
00062
00063
00064 if (not_starting && nc_angle_to_first > 1.5) return hull;
00065 not_starting=true;
00066
00067 double best_nc_angle = 1.5;
00068 ITER best;
00069
00070 for (ITER i=pts.begin(); i != pts.end(); ++i)
00071 {
00072 double nc_angle = get_nc_angle(last_dir, current, *i);
00073 if (nc_angle < best_nc_angle)
00074 {
00075 best_nc_angle = nc_angle;
00076 best = i;
00077 }
00078 }
00079
00080
00081 if (nc_angle_to_first <= best_nc_angle) return hull;
00082
00083
00084
00085 hull.push_back(*best);
00086 last_dir=*best - current;
00087 current = * best;
00088 pts.erase(best);
00089 }
00090 }
00091
00092 #undef VGL_CONVEX_INSTANTIATE
00093 #define VGL_CONVEX_INSTANTIATE(T) \
00094 template vgl_polygon<T > vgl_convex_hull(const vcl_vector<vgl_point_2d<T > >&)
00095
00096
00097 #endif // vgl_convex_txx_