Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ApproxMVBB/ConvexHull2D.hpp"
00014 namespace ApproxMVBB{
00015 void ConvexHull2D::compute() {
00016 using namespace PointFunctions;
00017 using namespace ContainerFunctions;
00018
00019 m_indicesCH.clear();
00020
00021
00022 if(m_p.cols()==0) {
00023 return;
00024 }
00025
00026
00027 unsigned int position = minPointYX(m_p);
00028
00029 Vector2 base = m_p.col(position);
00030
00031
00032
00033 using PointData = std::pair<unsigned int, bool>;
00034 std::vector< PointData > indices; indices.reserve(m_p.cols());
00035
00036
00037 indices.emplace_back(position,false);
00038
00039 for(unsigned int i = 0; i<m_p.cols(); ++i) {
00040 if( (i != position) && !almostEqualUlp(base,m_p.col(i))) {
00041 indices.emplace_back(i,false);
00042 }
00043 }
00044
00045
00046 if(indices.size() <= 2 ) {
00047 for(auto & pa : indices){ m_indicesCH.emplace_back(pa.first);} return;
00048 }
00049
00050
00051 unsigned int deletedPoints = 0;
00052 CompareByAngle comp(m_p,base,position,deletedPoints);
00053 std::sort( indices.begin()+1, indices.end(), comp );
00054
00055 std::vector<unsigned int> indicesT(indices.size()-deletedPoints);
00056 unsigned int k=0;
00057 for(auto & p: indices){ if(!p.second){indicesT[k++]=p.first;} }
00058
00059
00060
00061
00062 auto ifFunc = [&](const unsigned int & p1, const unsigned int & p2){
00063 return !almostEqualUlp(this->m_p.col(p1),this->m_p.col(p2));
00064 };
00065
00066 auto d2 = ContainerFunctions::moveConsecutiveToFrontIf(indicesT.begin(),indicesT.end(), ifFunc);
00067 indicesT.resize( std::distance(indicesT.begin(),d2) );
00068
00069
00070 if(indicesT.size() <= 2 ) {
00071 for(auto & pa : indicesT){ m_indicesCH.emplace_back(pa);} return;
00072 }
00073
00074
00075
00076
00077
00078 unsigned int nPoints = indicesT.size();
00079 m_indicesCH.reserve(nPoints);
00080 unsigned int lastIdx = indicesT[0];
00081 unsigned int firstIdx = indicesT[1];
00082 m_indicesCH.push_back( lastIdx );
00083 m_indicesCH.push_back( firstIdx );
00084
00085 unsigned int lPtIdx = lastIdx;
00086 unsigned int mPtIdx = firstIdx;
00087 unsigned int currIdx ;
00088 unsigned int i = 2;
00089
00090
00091
00092
00093
00094 while( i<nPoints){
00095 currIdx = indicesT[i];
00096 if(leftTurn(m_p.col(lastIdx), m_p.col(firstIdx), m_p.col(currIdx))){
00097 break;
00098 }
00099 ++i;
00100 };
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 if ( i < nPoints )
00111 {
00112 m_indicesCH.push_back( currIdx );
00113 decltype(m_indicesCH.rbegin()) revIter;
00114 lPtIdx = mPtIdx;
00115 mPtIdx = currIdx;
00116
00117 for (++i ; i < nPoints; ++i )
00118 {
00119 currIdx = indicesT[i];
00120
00121 if ( leftTurn(m_p.col(mPtIdx), m_p.col(currIdx), m_p.col(lastIdx)) )
00122 {
00123 while ( !leftTurn(m_p.col(lPtIdx), m_p.col(mPtIdx), m_p.col(currIdx)) )
00124 {
00125
00126 ApproxMVBB_ASSERTMSG(m_indicesCH.size()>2,"");
00127 m_indicesCH.pop_back();
00128
00129 if( m_indicesCH.size() <= 1) {
00130 mPtIdx = lPtIdx;
00131 break;
00132 }else{
00133 mPtIdx = lPtIdx;
00134 revIter = m_indicesCH.rbegin();
00135 lPtIdx = *(++revIter);
00136 }
00137 }
00138
00139 m_indicesCH.push_back( currIdx );
00140 lPtIdx = mPtIdx;
00141 mPtIdx = currIdx;
00142 }
00143
00144
00145 }
00146
00147 }
00148
00149 }
00150
00151
00152 bool ConvexHull2D::verifyHull() {
00153 using namespace PointFunctions;
00154 if(m_indicesCH.size()>2) {
00155 unsigned int i = 2;
00156 while( i<m_indicesCH.size()) {
00157 if( ! (orient2d( m_p.col(m_indicesCH[i-2]), m_p.col(m_indicesCH[i-1]), m_p.col(m_indicesCH[i])) >= 0) ) {
00158 return false;
00159 }
00160 ++i;
00161 }
00162 }
00163 return true;
00164 }
00165
00166 }