Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_GRAHAM_SCAN_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_GRAHAM_SCAN_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <algorithm>
00013 #include <cmath>
00014 #include <iostream>
00015
00016 namespace OpenTissue
00017 {
00018 namespace geometry
00019 {
00020
00021 template<typename vector3_iterator,typename vector3_container, typename vector3_type>
00022 void graham_scan(vector3_iterator begin,vector3_iterator end, vector3_container & hull, vector3_type const & n)
00023 {
00024 typedef typename vector3_type::value_type real_type;
00025
00026 assert(begin!=end || !"graham_scan(...) Empty range of points");
00027
00028 hull.clear();
00029 unsigned int count = std::distance(begin,end);
00030 std::vector<vector3_type *> points(count);
00031 {
00032 unsigned int idx = 0;
00033 for(vector3_iterator v = begin;v!=end;++v,++idx)
00034 {
00035 points[idx] = &(*v);
00036 }
00037 }
00038
00039
00040 for (unsigned int u = 0; u<count-1; ++u)
00041 {
00042 for(unsigned int i=u+1; i<count; ++i)
00043 {
00044 if( *(points[i]) == *(points[u]) )
00045 {
00046 count--;
00047 std::swap(points[i],points[count]);
00048 }
00049 }
00050 }
00051
00052
00053 unsigned int used = 0;
00054 unsigned int j=0;
00055 for(unsigned int i=1; i<count; ++i)
00056 {
00057 if( *(points[i]) < *(points[j]) )
00058 j = i;
00059 }
00060 std::swap(points[j],points[0]);
00061 ++used;
00062
00063 vector3_type a,b,c;
00064 unsigned int last = 0;
00065 unsigned int best = 0;
00066 do
00067 {
00068 best = used%count;
00069 a = *(points[best]) - *(points[last]);
00070
00071 for(unsigned int i=(used+1); i<(count+1); ++i)
00072 {
00073 unsigned int k = ((i)%count);
00074 if(is_zero(a))
00075 {
00076 best = k;
00077 a = *(points[best]) - *(points[last]);
00078 continue;
00079 }
00080
00081 b = *(points[k]) - *(points[last]);
00082 c = (a % b);
00083 real_type dot = n * c;
00084 if((dot < 0 && b*b>a*a) || dot < -0.001)
00085 {
00086 best = k;
00087 a = *(points[best]) - *(points[last]);
00088 }
00089
00090 else if( (dot==0) && (a*b>0) && (b*b>a*a) )
00091 {
00092 best = k;
00093 a = *(points[best]) - *(points[last]);
00094 }
00095 }
00096 if(best==0)
00097 break;
00098
00099 std::swap(points[used],points[best]);
00100 last = used;++used;
00101
00102 }while(best!=0);
00103
00104
00105 for(unsigned int idx = 0;idx<used;++idx)
00106 hull.push_back( *(points[idx]) );
00107 }
00108
00109 template<typename vector3_iterator,typename vector3_container>
00110 void graham_scan(vector3_iterator begin,vector3_iterator end, vector3_container & hull)
00111 {
00112 typedef typename vector3_container::value_type vector3_type;
00113 graham_scan(begin,end,hull,vector3_type(0,0,1));
00114 }
00115
00116 }
00117 }
00118
00119
00120 #endif