ConvexHull2D.cpp
Go to the documentation of this file.
1 // ========================================================================================
2 // ApproxMVBB
3 // Copyright (C) 2014 by Gabriel Nützi <nuetzig (at) imes (d0t) mavt (d0t) ethz (døt) ch>
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 // ========================================================================================
9 //#include <iterator> // for ostream_iterator
10 //#include "TestFunctions.hpp"
11 
12 
14 namespace ApproxMVBB{
16  using namespace PointFunctions;
17  using namespace ContainerFunctions;
18 
19  m_indicesCH.clear();
20 
21  // Need at least 1 point! m_p.col(0)
22  if(m_p.cols()==0) {
23  return;
24  }
25 
26  // Compute min point p0
27  unsigned int position = minPointYX(m_p);
28  // std::cout << "min:" << position << std::endl;
29  Vector2 base = m_p.col(position);
30 
31  // Indices into m_p
32  // first = index into m_p, second = delete flag!
33  using PointData = std::pair<unsigned int, bool>;
34  std::vector< PointData > indices; indices.reserve(m_p.cols());
35 
36  //Save p0 as first point in indices list (temporary)
37  indices.emplace_back(position,false);
38  //Add all indices of points not almostEqual to position
39  for(unsigned int i = 0; i<m_p.cols(); ++i) {
40  if( (i != position) && !almostEqualUlp(base,m_p.col(i))) {
41  indices.emplace_back(i,false);
42  }
43  }
44 
45  // Convex hull consists of only 1 or 2 points!
46  if(indices.size() <= 2 ) {
47  for(auto & pa : indices){ m_indicesCH.emplace_back(pa.first);} return;
48  }
49 
50  // Sort by angle
51  unsigned int deletedPoints = 0;
52  CompareByAngle comp(m_p,base,position,deletedPoints);
53  std::sort( indices.begin()+1, indices.end(), comp );
54 
55  std::vector<unsigned int> indicesT(indices.size()-deletedPoints);
56  unsigned int k=0;
57  for(auto & p: indices){ if(!p.second){indicesT[k++]=p.first;} }
58 
59  // Remove almost equal elements
60  // move to front if not almost equal to first point
61  // skip all deleted points
62  auto ifFunc = [&](const unsigned int & p1, const unsigned int & p2){
63  return !almostEqualUlp(this->m_p.col(p1),this->m_p.col(p2));
64  };
65 // auto skipFunc = [](const unsigned int & p1){ return false; };
66  auto d2 = ContainerFunctions::moveConsecutiveToFrontIf(indicesT.begin(),indicesT.end(), ifFunc);
67  indicesT.resize( std::distance(indicesT.begin(),d2) );
68 
69  // Convex hull consists of only 1 or 2 points!
70  if(indicesT.size() <= 2 ) {
71  for(auto & pa : indicesT){ m_indicesCH.emplace_back(pa);} return;
72  }
73 
74  //for(auto a: indicesT){
75  // std::cout << a.first<<",";
76  //}
77  //std::cout << "Graham Scan points: " << indicesT.size() << std::endl;
78  unsigned int nPoints = indicesT.size();
79  m_indicesCH.reserve(nPoints);
80  unsigned int lastIdx = indicesT[0];
81  unsigned int firstIdx = indicesT[1];
82  m_indicesCH.push_back( lastIdx );
83  m_indicesCH.push_back( firstIdx );
84 
85  unsigned int lPtIdx = lastIdx;
86  unsigned int mPtIdx = firstIdx;
87  unsigned int currIdx ;
88  unsigned int i = 2; // current point;
89 
90  // skip the first non left turns in the sequence!
91  // std::cout << "lastIdx point: " <<lastIdx << ","<< m_p.col(lastIdx).transpose() << std::endl;
92  // std::cout << "firstIdx point: " <<firstIdx << ","<< m_p.col(firstIdx).transpose() << std::endl;
93 
94  while( i<nPoints){
95  currIdx = indicesT[i];
96  if(leftTurn(m_p.col(lastIdx), m_p.col(firstIdx), m_p.col(currIdx))){
97  break;
98  }
99  ++i;
100  };
101 
102 
103  // std::cout << "i:"<< i << std::endl;
104  // std::cout << "currIdx point: " <<currIdx << std::endl;
105  // std::cout << ","<< m_p.col(currIdx).transpose() << std::endl << "===="<<std::endl;
106  // std::cout << "0,5,8: :" << orient2d(m_p.col(0), m_p.col(5), m_p.col(8)) << std::endl;
107  // std::cout << "1,5,8: :" << orient2d(m_p.col(1), m_p.col(5), m_p.col(8)) << std::endl;
108  // std::cout << "5,8,0: :" << orient2d(m_p.col(5), m_p.col(8), m_p.col(0)) << std::endl;
109 
110  if ( i < nPoints )
111  {
112  m_indicesCH.push_back( currIdx );
113  decltype(m_indicesCH.rbegin()) revIter;
114  lPtIdx = mPtIdx;
115  mPtIdx = currIdx;
116 
117  for (++i ; i < nPoints; ++i )
118  {
119  currIdx = indicesT[i];
120 
121  if ( leftTurn(m_p.col(mPtIdx), m_p.col(currIdx), m_p.col(lastIdx)) )
122  {
123  while ( !leftTurn(m_p.col(lPtIdx), m_p.col(mPtIdx), m_p.col(currIdx)) )
124  {
125  //std::cout << "right turn: " <<lPtIdx << ","<< mPtIdx << "," << currIdx << std::endl;
126  ApproxMVBB_ASSERTMSG(m_indicesCH.size()>2,"");
127  m_indicesCH.pop_back();
128 
129  if( m_indicesCH.size() <= 1) { // Degenerate Case if we come back to the beginning
130  mPtIdx = lPtIdx; // such that lPtIdx stays the same , mPtIdx becomes currIdx and we go to next point!
131  break;
132  }else{
133  mPtIdx = lPtIdx; // middle point becomes last
134  revIter = m_indicesCH.rbegin();
135  lPtIdx = *(++revIter); // previous of .back();
136  }
137  }
138  //std::cout << "left turn: " <<lPtIdx << ","<< mPtIdx << "," << currIdx << std::endl;
139  m_indicesCH.push_back( currIdx );
140  lPtIdx = mPtIdx; // last becomes middle
141  mPtIdx = currIdx; // middle becomes currIdx
142  }/*else{
143  std::cout << "skip point: " << currIdx << std::endl;
144  }*/
145  }
146 
147  }
148 
149 }
150 
151 
153  using namespace PointFunctions;
154  if(m_indicesCH.size()>2) {
155  unsigned int i = 2;
156  while( i<m_indicesCH.size()) {
157  if( ! (orient2d( m_p.col(m_indicesCH[i-2]), m_p.col(m_indicesCH[i-1]), m_p.col(m_indicesCH[i])) >= 0) ) { // if this is not a left turn
158  return false;
159  }
160  ++i;
161  }
162  }
163  return true;
164 }
165 
166 }
#define ApproxMVBB_ASSERTMSG(condition, message)
An Assert Macro to use within C++ code.
std::vector< unsigned int > m_indicesCH
unsigned int minPointYX(const MatrixBase< Derived > &points)
These are some container definitions.
bool almostEqualUlp(const VecT1 &a, const VecT2 &b)
Iterator moveConsecutiveToFrontIf(Iterator b, Iterator e, Comp c)
REAL orient2d(REAL *pa, REAL *pb, REAL *pc)
Definition: Predicates.cpp:907
const MatrixRef< const Matrix2Dyn > m_p
bool leftTurn(const VecT1 &a, const VecT2 &b, const VecT3 &c)
Eigen::Matrix< Scalar, 2, 1 > Vector2


asr_approx_mvbb
Author(s): Gassner Nikolai
autogenerated on Mon Jun 10 2019 12:38:08