aimstil  5.0.5
mesh_decimation.h
Go to the documentation of this file.
1 #ifndef TIL_MESH_DECIMATION
2 #define TIL_MESH_DECIMATION
3 
4 // includes from STL
5 
6 // includes from TIL
7 #include "graph.h"
8 #include "mesh_conversion.h"
9 #include "meshUtils.h"
10 
11 namespace til
12 {
13 
14  template < typename TVertexXsr, typename TNeighborhoodXsr, typename TPrec >
16  {
17  public: // typedefs
18 
19  typedef typename TVertexXsr::index_type index_type;
20  typedef typename TVertexXsr::value_type Vertex;
21  typedef typename TNeighborhoodXsr::value_type Neighborhood;
22  typedef typename TNeighborhoodXsr::reference NeighborhoodRef;
23 
24  public: // constructors
25  MeshWaveletEnergy2(const TVertexXsr & vertexXsr, const TNeighborhoodXsr & neighXsr)
26  : m_neighXsr(neighXsr)
27  , m_vertexXsr(vertexXsr)
28  , m_mc(vertexXsr, neighXsr)
29  {}
30 
31  public: // functions
32 
33  TPrec operator()(index_type i)
34  {
35  m_mc.process(i);
36  Vertex c;
37  NeighborhoodRef neigh = m_neighXsr(i);
38  for (typename Neighborhood::const_iterator j = neigh.begin(); j != neigh.end(); ++j)
39  //for (std::size_t j = 0; j < m_neighc[i].size(); ++j)
40  {
41  //std::cout << m_vertices[m_neighc[i][j]] << " ";
42  c += m_vertexXsr(*j);
43  //c += m_vertices[m_neighc[i][j]];
44  }
45  //std::cout << std::endl;
46  c *= TPrec(1.0) / neigh.size();
47  //std::cout << "mean: " << c << std::endl;
48  //centroid(m_neighc[i], c);
49  //return dist<TPrec>(m_vertices[i], centroid<Vertex>(m_neighc[i])) / m_mc.voronoiArea();
50  //m_error = m_vertices[i] - c
51  return dist(m_vertexXsr(i), c, prec<TPrec>()) / m_mc.voronoiArea();
52  }
53 
54  private: // data, input
55 
56  TNeighborhoodXsr m_neighXsr;
57  TVertexXsr m_vertexXsr;
58 
59  private: // data, internals
60 
62  };
63 
64  //---------------------------------------------------------------------------
65 
66 
69  template < typename TVertexCollection, typename TNeighborhoods, typename TPrec >
71  {
72  public: // typedefs
73  typedef typename TVertexCollection::value_type Vertex;
74  public: // constructors
76  (
77  TVertexCollection const & vertices
78  , TNeighborhoods const & neighc
79  )
80  : m_vertices(vertices)
81  , m_neighc(neighc)
82  , m_mc(vertices, neighc)
83  {}
84 
85  public: // functions
86 
87  TPrec operator()(std::size_t i)
88  {
89  m_mc.process(i);
90  Vertex c;
91  for (std::size_t j = 0; j < m_neighc[i].size(); ++j)
92  {
93  c += m_vertices[m_neighc[i][j]];
94  }
95  c *= TPrec(1.0) / m_neighc[i].size();
96  //centroid(m_neighc[i], c);
97  //return dist<TPrec>(m_vertices[i], centroid<Vertex>(m_neighc[i])) / m_mc.voronoiArea();
98  //m_error = m_vertices[i] - c
99  return dist(m_vertices[i], c, prec<TPrec>()) / m_mc.voronoiArea();
100  }
101 
102  private: // data, input
103  const TVertexCollection & m_vertices;
104  const TNeighborhoods & m_neighc;
105  private: // data, internal
107  };
108 
109  //---------------------------------------------------------------------------
110 
111  namespace
112  {
113 
114 
116  /*
117  template < typename TIterator >
118  struct ItComp
119  {
120  bool operator()
121  (
122  //const TIterator & i,
123  //const TIterator & j
124  TIterator i,
125  TIterator j
126  )
127  {
128  return &*i < &*j;
129  }
130  };
131  */
132 
133  template < typename T >
134  struct GroComp
135  {
136  //typedef std::list<MeshVertexNode>::iterator T;
137 
138  GroComp(T a, T b, T c)
139  : m_a(a)
140  , m_b(b)
141  , m_c(c)
142  {}
143 
145  helper(T a, T b, T c)
146  {
147  boost::array<T,3> tmp;
148  tmp[0] = a;
149  tmp[1] = b;
150  tmp[2] = c;
151  return tmp;
152  }
153 
154  template < typename TFace >
155  bool operator()(const TFace & f)
156  {
157  return
158  f->face == helper(m_a, m_b, m_c) ||
159  f->face == helper(m_c, m_a, m_b) ||
160  f->face == helper(m_b, m_c, m_a) ||
161  f->face == helper(m_b, m_a, m_c) ||
162  f->face == helper(m_c, m_b, m_a) ||
163  f->face == helper(m_a, m_c, m_b)
164  ;
165  }
166 
167  T m_a;
168  T m_b;
169  T m_c;
170  };
171 
172  }
173 
174  //---------------------------------------------------------------------------
175 
176  namespace
177  {
178  struct Temp
179  {
180  double angle;
181  std::size_t index;
182  friend bool operator<(const Temp & x, const Temp & y) { return x.angle < y.angle; }
183  };
184  struct TempComp
185  {
186  bool operator()(const Temp & x, const Temp & y) { return x.angle < y.angle; }
187  };
188  }
189 
190  //---------------------------------------------------------------------------
191 
194  // TODO: move to geo
195  template < typename TPointIterator, typename TOutIterator >
196  TOutIterator
197  bounding_triangle(TPointIterator pbegin, TPointIterator pend, TOutIterator out)
198  {
199  float miny, k1, k2;
200  k1 = k2 = -std::numeric_limits<float>::max();
202  for (; pbegin != pend; ++pbegin)
203  {
204  miny = min(miny, (*pbegin)[1]);
205  max_helper(k1, (*pbegin)[1] - std::sqrt(3.0f) * (*pbegin)[0]);
206  max_helper(k2, (*pbegin)[1] + std::sqrt(3.0f) * (*pbegin)[0]);
207  }
208 
210  M[0] = (k2 - k1) / (2*std::sqrt(3.0f));
211  M[1] = 2*miny/3 + (k1+k2)/6;
212 
214  A[0] = (miny - k1) * (1/std::sqrt(3.0f));
215  A[1] = miny;
217  B[0] = (k2 - miny) * (1/std::sqrt(3.0f));
218  B[1] = miny;
220  C[0] = (k2 - k1) / (2*std::sqrt(3.0f));
221  C[1] = (k1+k2)/2;
222 
223  A += 2.0f*(A-M);
224  B += 2.0f*(B-M);
225  C += 2.0f*(C-M);
226 
227  *(out++) = A;
228  *(out++) = B;
229  *(out++) = C;
230  return out;
231  }
232 
233  //---------------------------------------------------------------------------
234 
235 
236  //-------------------------------//
237  // SimpleDelaunayTriangulation //
238  //-------------------------------//
239 
240  /*
241  template < typename TFace >
242  class SimpleDelaunayTriangulation
243  {
244  public: // operators
245  std::list<boost::array<std::size_t,3> >
246  operator()(std::vector<numeric_array<float, 2> > points);
247  };
248  */
249 
250  std::list<boost::array<std::size_t,3> >
252  {
253  typedef boost::array<std::size_t,3> Face;
254  typedef std::list<Face> FaceList;
255 
256  // Get size now before points are added
257  std::size_t n = points.size();
258 
259  // Don't waste time calling this for less than 4 points.
260  assert(points.size() >= 4);
261 
262  FaceList faces;
263 
264  // compute bounding triangle
265  //bounding_triangle(points.begin(), points.end(), std::back_inserter(points));
266 
267  {
268  float miny, k1, k2;
269  k1 = k2 = -std::numeric_limits<float>::max();
271  for (std::size_t i = 0; i < points.size(); ++i)
272  {
273  miny = min(miny, points[i][1]);
274  k1 = max(k1, points[i][1] - std::sqrt(3.0f)*points[i][0]);
275  k2 = max(k2, points[i][1] + std::sqrt(3.0f)*points[i][0]);
276  }
277 
279  M[0] = (k2 - k1) / (2*std::sqrt(3.0f));
280  M[1] = 2*miny/3 + (k1+k2)/6;
281 
283  A[0] = (miny - k1) * (1/std::sqrt(3.0f));
284  A[1] = miny;
286  B[0] = (k2 - miny) * (1/std::sqrt(3.0f));
287  B[1] = miny;
289  C[0] = (k2 - k1) / (2*std::sqrt(3.0f));
290  C[1] = (k1+k2)/2;
291 
292  A += 2.0f*(A-M);
293  B += 2.0f*(B-M);
294  C += 2.0f*(C-M);
295 
296  points.push_back(A);
297  points.push_back(B);
298  points.push_back(C);
299 
300  boost::array<std::size_t,3> face = { { points.size()-1, points.size()-2, points.size()-3 } };
301  faces.push_back(face);
302  }
303 
304 
305  //Face face = {0,1,2};
306  //faces.push_back(face);
307  //for (std::size_t i = 3; i < size(points); ++i)
308  for (std::size_t i = 0; i < n; ++i)
309  {
310  //std::cout << "another point :" << points[i] << std::endl;
311 
312  // Remove triangles if we lie in their circumcircle, and collect their vertex.
313  std::set<std::size_t> neighbors;
314  //e.insert(0);
315  //e.insert(i-1);
316  {
317  FaceList::iterator f = faces.begin();
318  while (f != faces.end())
319  {
320  //std::cout << "face " << points[(*f)[0]] << " " << points[(*f)[1]] << " " << points[(*f)[2]] << ":";
321  if (geo::is_in_circumcircle<double>(points[i], points[(*f)[0]], points[(*f)[1]], points[(*f)[2]]))
322  {
323  //std::cout << "inside" << std::endl;
324  neighbors.insert((*f)[0]);
325  neighbors.insert((*f)[1]);
326  neighbors.insert((*f)[2]);
327  f = faces.erase(f);
328  }
329  else
330  {
331  //std::cout << "outside circle" << std::endl;
332  ++f;
333  }
334  }
335  }
336 
337  assert(neighbors.size() >= 3);
338 
339  // order neighbors according to the angle they make with the current point
340 
341  std::vector<Temp> tmp;
342  tmp.reserve(neighbors.size());
343  for (std::set<std::size_t>::iterator iNeighbor = neighbors.begin(); iNeighbor != neighbors.end(); ++iNeighbor)
344  {
345  Temp t;
346  t.index = *iNeighbor;
347  numeric_array<float,2> v = points[*iNeighbor]-points[i];
348  t.angle = geo::angle(v[0], v[1]);
349  tmp.push_back(t);
350  }
351  //std::sort(tmp.begin(), tmp.end(), TempComp());
352  std::sort(tmp.begin(), tmp.end());
353 
354  // Form new faces
355  for (std::size_t it = 0; it < tmp.size(); ++it)
356  {
357  //std::cout << "Adding face " << i << " " << tmp[it].index << " " << tmp[ (it+1) % size(tmp) ].index << std::endl;
358  Face face = { {i, tmp[it].index, tmp[ (it+1) % tmp.size() ].index } };
359  faces.push_back(face);
360  }
361  }
362  /*
363  {
364  std::cout << "faces" << std::endl;
365  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
366  {
367  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
368  }
369  std::cout << "endfaces" << std::endl;
370  }
371  */
372 
373  // Remove extra faces
374  {
375  FaceList::iterator f = faces.begin();
376  while (f != faces.end())
377  {
378  // Remove faces with supertriangle vertex
379  if ((*f)[0] >= n ||
380  (*f)[1] >= n ||
381  (*f)[2] >= n)
382  {
383  f = faces.erase(f);
384  }
385  else
386  {
387  ++f;
388  }
389  }
390  }
391  /*
392  {
393  FaceList::iterator f = faces.begin();
394  std::cout << "cross2D: " << cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) << std::endl;
395  }
396  */
397 
398  // Check that normals are ok
399  {
400  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
401  {
402  if (cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) < 0)
403  {
404  std::cout << "wS!";
405  }
406  }
407  }
408 
409 
410  // Check if we have to resort to normal testing to remove faces
411  if (faces.size() != n-2)
412  {
413  /*
414  std::cout << "NI!" << faces.size() << "-" << n << std::endl;
415  {
416  std::cout << "faces2" << std::endl;
417  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
418  {
419  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
420  }
421  std::cout << "endfaces" << std::endl;
422  }
423  */
424 
425  // Remove faces with bad normal
426  /*
427  {
428  FaceList::iterator f = faces.begin();
429  while (f != faces.end())
430  {
431  if (cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) < 0)
432  {
433  f = faces.erase(f);
434  }
435  else
436  {
437  ++f;
438  }
439  }
440  }
441  */
442 
443  {
444  FaceList::iterator f = faces.begin();
445  while (f != faces.end())
446  {
447  bool flagdel = false;
448  int count = 0;
449  for (int i = 0; i < 3; ++i)
450  {
451  if ((*f)[i] > (*f)[(i+1)%3])
452  {
453  if (++count > 1)
454  {
455  flagdel = true;
456  //f = faces.erase(f);
457  break;
458  }
459  }
460  }
461  if (flagdel) f = faces.erase(f);
462  else ++f;
463  }
464  }
465 
466  // Check again that we have the expected number of faces
467  if (faces.size() != n-2)
468  {
469  std::cout << "NI2!" << faces.size() << "-" << n << std::endl;
470  {
471  std::cout << "faces2" << std::endl;
472  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
473  {
474  std::cout << (*f)[0] << " " << (*f)[1] << " " << (*f)[2] << std::endl;
475  }
476  std::cout << "endfaces" << std::endl;
477  std::cout << "points" << std::endl;
478  for (std::size_t i = 0; i < n; ++i) std::cout << points[i] << std::endl;
479  std::cout << "end points" << std::endl;
480  }
481  }
482  }
483 
484  // check that all outer edges is missing
485  {
486  std::set<boost::array<std::size_t,2> > outer_edges;
487  for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
488  {
489  for (std::size_t i = 0; i < 3; ++i)
490  {
491  std::size_t delta = std::abs(int((*f)[i]) - int((*f)[(i+1)%3]));
492  if (delta == 1 || delta == (n-1))
493  {
494  boost::array<std::size_t,2> tmp = { {min((*f)[i], (*f)[(i+1)%3]), max((*f)[i], (*f)[(i+1)%3])} };
495  outer_edges.insert(tmp);
496  }
497  }
498  }
499  if (outer_edges.size() != n)
500  {
501  std::cout << "wU!";
502  }
503  }
504 
505  //exit(0);
506 
507  /*
508  std::cout << "nfaces: " << faces.size() << std::endl;
509  for (FaceList::const_iterator i = faces.begin(); i != faces.end(); ++i)
510  {
511  std::cout << (*i)[0] << " " << (*i)[1] << " " << (*i)[2] << std::endl;
512  }
513  */
514  return faces;
515  }
516 
517  //---------------------------------------------------------------------------
518 
519 
525  template < typename TVertexNode, typename TFaceNode >
526  typename std::list<TVertexNode>::iterator
528  (
529  typename std::list<TVertexNode>::iterator i,
530  std::list<TVertexNode> & graph_vertices,
531  std::list<TFaceNode> & graph_faces
532  )
533  {
534  // remove faces point belongs to
535  for (typename TVertexNode::FaceIndexCollection::iterator j = i->faces().begin(); j != i->faces().end(); ++j)
536  {
537  // Remove index to this face
538  for (std::size_t k = 0; k < 3; ++k)
539  {
540  // don't remove face from facelist of point i itself -- because j is iterating on this very list,
541  // plus, it will be deleted with i anyway.
542  if ((*j)->face[k] == i) continue;
543  #ifndef NDEBUG
544  std::size_t tmp = (*j)->face[k]->faces().size();
545  #endif
546  (*j)->face[k]->faces().remove(*j);
547  assert((*j)->face[k]->faces().size() == tmp-1);
548  }
549  // remove face itself
550  #ifndef NDEBUG
551  std::size_t tmp = graph_faces.size();
552  #endif
553  graph_faces.erase(*j);
554  assert(graph_faces.size() == tmp-1);
555  }
556 
557  // remove point in neighbor's list
558  for (typename TVertexNode::VertexIndexCollection::iterator j = i->neighbors().begin(); j != i->neighbors().end(); ++j)
559  {
560  (*j)->neighbors().remove(i);
561  }
562  // remove point
563  return graph_vertices.erase(i);
564  }
565 
566 
567  //---------------------------------------------------------------------------
568 
569  // NB: neighbors should be a std::vector so far
570  template < typename TNeighbors >
571  std::vector<numeric_array<float,2> >
573  (
574  const numeric_array<float,3> & point,
575  // Point<float,3> point,
576  const TNeighbors & neighbors
577  )
578  {
579  //std::cout << "nneighbors " << neighbors.size() << std::endl;
580  //std::cout << "point " << point << std::endl;
581  //std::cout << "neighbors " << std::endl;
582  //for (std::size_t i = 0; i < neighbors.size(); ++i) std::cout << neighbors[i]->pos() << std::endl;
583 
584 
585  std::vector<double> angles;
586  std::vector<double> norms;
587  angles.reserve(neighbors.size());
588  norms.reserve(neighbors.size());
589 
590  typename TNeighbors::const_iterator n = neighbors.begin();
591  const_cyclic_iterator<TNeighbors> n2(neighbors, ++neighbors.begin());
592  //std::cout << "point: " << point << std::endl;
593  for (; n != neighbors.end(); ++n, ++n2)
594  {
595  //std::cout << (*n2)->pos() << " " << (*n)->pos() << std::endl;
596  //std::cout << (*n2)->pos()-point<< " " << (*n)->pos()-point << std::endl;
597  norms.push_back(norm((*n)->pos()-point, prec<double>()));
598  /*
599  double tmp4 = norm<double>((*n2)->pos()-point);
600  double tmp3 = norm<double>((*n)->pos()-point);
601  double tmp1 = tmp4 * tmp3;
602  double tmp2 = dot((*n2)->pos() - point, (*n)->pos() - point);
603  double tmp5 = std::acos( tmp2 / tmp1);
604  angles.push_back(tmp5);
605  */
606  angles.push_back(std::acos(dot((*n2)->pos()-point, (*n)->pos()-point) / (norm((*n2)->pos()-point, prec<double>()) * norm((*n)->pos()-point, prec<double>()))));
607 
608  //std::cout << angles.size() << " " << angles.capacity() << std::endl;
609  }
610 
611  /*
612  std::cout << "norms: ";
613  std::copy(norms.begin(), norms.end(), std::ostream_iterator<double>(std::cout, " "));
614  std::cout << std::endl;
615 
616  std::cout << "angles: ";
617  std::copy(angles.begin(), angles.end(), std::ostream_iterator<double>(std::cout, " "));
618  std::cout << std::endl;
619  */
620 
621  std::partial_sum(angles.begin(), angles.end(), angles.begin());
622 
623  /*
624  std::cout << "angles summed: ";
625  std::copy(angles.begin(), angles.end(), std::ostream_iterator<double>(std::cout, " "));
626  std::cout << std::endl;
627  */
628 
629  //double totalAngle = std::accumulate(angles.begin(), angles.end(), 0.0);
630  std::transform(angles.begin(), angles.end(), angles.begin(), std::bind2nd(std::multiplies<double>(), 2*M_PI/angles.back()));
631 
632  /*
633  std::cout << "angles normalized: ";
634  std::copy(angles.begin(), angles.end(), std::ostream_iterator<double>(std::cout, " "));
635  std::cout << std::endl;
636  */
637 
638  std::vector<numeric_array<float, 2> > res(neighbors.size());
639  for (std::size_t i = 0; i < size(res); ++i)
640  {
641  res[i][0] = std::cos(angles[i]) * norms[i];
642  res[i][1] = std::sin(angles[i]) * norms[i];
643  //res[i][0] = std::cos(angles[i]);
644  //res[i][1] = std::sin(angles[i]);
645  }
646  /*
647  std::cout << "newpoints" << std::endl;
648  for (std::size_t i = 0; i < res.size(); ++i)
649  {
650  std::cout << res[i] << std::endl;
651  }
652  std::cout << "end newpoints" << std::endl;
653  */
654 
655  return res;
656  }
657 
658 
659  //---------------------------------------------------------------------------
660 
661 
662  namespace
663  {
664  template < typename T >
665  struct ValueFinder
666  {
667  ValueFinder(T value) : m_value(value) {}
668  bool operator()(const SimpleOrientedGraphNode<T> & i) { return i.value == m_value; }
669  T m_value;
670  };
671 
672  template < typename T >
673  ValueFinder<T> valueFinder(T value) { return ValueFinder<T>(value); }
674  }
675 
680  template < typename TVertexNode, typename TFaceNode >
682  {
683  public: // enum
684 
685  enum Error {
686  none = 0,
689  };
690 
691  private: // typedefs
692 
694  typedef std::list<NeighborGraphNode> NeighborGraph;
695  typedef typename TVertexNode::VertexIndexCollection::value_type VertexPointer;
696 
697  public: // constructors
698 
699  Vertex_remover(std::list<TVertexNode> & graph_vertices, std::list<TFaceNode> & graph_faces)
700  : m_graph_vertices(graph_vertices)
701  , m_graph_faces(graph_faces)
702  , m_error(none)
703  {}
704 
705  public: // set & get
706 
707  std::vector<VertexPointer> & neighbors() { return m_neighbors; }
708  Error error() const { return m_error; }
709 
710 
711  private: // functions
712 
715  bool neighborTriangulation(VertexPointer i)
716  {
717  // get delaunay faces for more than 4 neighbors
718  std::size_t nneigh = m_neighbors.size();
719  // NB: I don't know why we need this, but we do -- it crashes otherwise
720  m_tri.clear();
721  if (nneigh >= 4)
722  {
723  m_tri = simple_delaunay_triangulation(simple_neighborhood_flattening(i->pos(), m_neighbors));
724  }
725  // For three neighbors, simply add the only triangle possible
726  else if (nneigh == 3)
727  {
728  boost::array<std::size_t,3> tmp = { {0,1,2} };
729  m_tri.push_back(tmp);
730  }
731  // For two points or less, do not add any face. Note that if this happens, it means that the mesh
732  // is in really bad shape -- actually the following might crash.
733  else
734  {
735  m_error = invalid_neighborhood;
736  std::cout << "w2!";
737  return false;
738  }
739  // Check consistency between number of points and number of faces
740  if (m_tri.size() != nneigh - 2)
741  {
742  m_error = triangulation_failure;
743  std::cout << "wK!" << m_tri.size() << "-" << nneigh-2;
744  return false;
745  }
746  return true;
747  }
748 
749 
752  void initializeOrientedEdges(VertexPointer i)
753  {
754  std::size_t nneigh = m_neighbors.size();
755  m_convmap.resize(nneigh);
756  for (std::size_t j = 0; j < nneigh; ++j)
757  {
758  // first pass: vertices
759  {
760  for (typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin(); k != m_neighbors[j]->neighbors().end(); ++k)
761  {
762  if (*k == i) continue;
763  NeighborGraphNode node(*k);
764  m_convmap[j][*k] = m_neighborGraph[j].insert(m_neighborGraph[j].end(), node);
765  }
766  }
767  // second pass: edges
768  {
769  typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin();
770  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k2(m_neighbors[j]->neighbors(), m_neighbors[j]->neighbors().begin());
771  ++k2;
772  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k3(m_neighbors[j]->neighbors(), m_neighbors[j]->neighbors().begin());
773  ++k3;
774  ++k3;
775  for (; k != m_neighbors[j]->neighbors().end(); ++k, ++k2, ++k3)
776  {
777  if (*k2 == i) continue;
778  if (*k != i) m_convmap[j][*k2]->from.push_back(m_convmap[j][*k]);
779  if (*k3 != i) m_convmap[j][*k2]->to.push_back(m_convmap[j][*k3]);
780  }
781  }
782  }
783  }
784 
787  void updateNeighborGraph()
788  {
789  for (std::list<boost::array<std::size_t,3> >::iterator newf = m_tri.begin(); newf != m_tri.end(); ++newf)
790  {
791  for (std::size_t n = 0; n < 3; ++n)
792  {
793  typename NeighborGraph::iterator p2, p3;
794 
795  p2 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+1)%3]]));
796  p3 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+2)%3]]));
797  if (p2 == m_neighborGraph[(*newf)[n]].end()) p2 = m_neighborGraph[(*newf)[n]].insert(p2, NeighborGraphNode(m_neighbors[(*newf)[(n+1)%3]]));
798  if (p3 == m_neighborGraph[(*newf)[n]].end()) p3 = m_neighborGraph[(*newf)[n]].insert(p3, NeighborGraphNode(m_neighbors[(*newf)[(n+2)%3]]));
799 
800  p2->to.push_back(p3);
801  p3->from.push_back(p2);
802  }
803  }
804  }
805 
806 
808  bool checkNeighborsHaveThreeNeighbors()
809  {
810  for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
811  {
812  if (m_neighborGraph[k].size() < 3)
813  {
814  //std::cout << "WREJECT!(small-neighborhood)";
815  return false;
816  }
817  }
818  return true;
819  }
820 
822  bool checkCorrectNeighborhood()
823  {
824  for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
825  {
826  //std::cout << k << "/" << m_neighborGraph.size() << std::endl;
827  typename NeighborGraph::iterator p = m_neighborGraph[k].begin();
828  typename NeighborGraph::iterator p0 = p;
829  bool flag = false;
830  for (;;)
831  {
832  //std::cout << ":" << &*p << " " << std::flush;
833  if (flag)
834  {
835  //std::cout << "R" << std::flush;
836  if (p == p0) break;
837  //std::cout << "T" << std::flush;
838  }
839  else
840  {
841  //std::cout << "S" << std::flush;
842  flag = true;
843  }
844  //std::cout << "P" << std::flush;
845  if (p->to.size() != 1 || p->from.size() != 1)
846  {
847  //std::cout << "WREJECT!(incorrect-neighborhood)";
848  return false;
849  }
850  //std::cout << "%" << std::flush;
851  p = p->to.front();
852  //std::cout << "*" << std::flush;
853  }
854  }
855  return true;
856  }
857 
858 
859  void addFaces(VertexPointer i)
860  {
861  for (std::list<boost::array<std::size_t,3> >::iterator newf = m_tri.begin(); newf != m_tri.end(); ++newf)
862  {
863  // convert into graph faces
864  TFaceNode f;
865  for (std::size_t n = 0; n < 3; ++n)
866  {
867  f.face[n] = m_neighbors[(*newf)[n]];
868  }
869  // add face to graph
870  typename std::list<TFaceNode>::iterator gf = m_graph_faces.insert(m_graph_faces.end(), f);
871  numeric_array<float,3> normal = cross(
872  i->faces().front()->face[0]->pos() - i->faces().front()->face[1]->pos(),
873  i->faces().front()->face[0]->pos() - i->faces().front()->face[2]->pos()
874  );
875  // add face index to face points
876  for (std::size_t n = 0; n < 3; ++n)
877  {
878  GroComp<VertexPointer> grocomp(f.face[0], f.face[1], f.face[2]);
879  typename TVertexNode::FaceIndexCollection::iterator p = find_if(f.face[n]->faces().begin(), f.face[n]->faces().end(), grocomp);
880  if (p != f.face[n]->faces().end())
881  {
882  std::cout << "FATAL: face already there: " << std::endl;
883  std::cout << &*f.face[0] << " " << &*f.face[1] << " " << &*f.face[2] << std::endl;
884  std::cout << &*(*p)->face[0] << " " << &*(*p)->face[1] << " " << &*(*p)->face[2] << std::endl;
885  std::cout << "I'll continue as if nothing happened, but this is a bug and your algorithm is likely to go bananas :)" << std::endl;
886  }
887 
888  // checking normal consistency
889  // I removed this test because normality consistency is broken very often, and yet this is legal.
890  // Actually, I know it is legal -- it is just surprising that this happens so often (like 1/10th of the
891  // cases!).
892  /*
893  {
894  Vector<float,3> mynormal = cross(
895  f.face[0]->pos() - f.face[1]->pos(),
896  f.face[0]->pos() - f.face[2]->pos());
897  if (dot(normal, mynormal) < 0) std::cout << "wY!";
898  }
899  */
900  f.face[n]->faces().push_back(gf);
901  }
902  }
903  }
904 
905  void addNeighbors(VertexPointer i)
906  {
907  for (std::size_t j = 0; j < i->neighbors().size(); ++j)
908  {
909  typename TVertexNode::VertexIndexCollection ntmp = m_neighbors[j]->neighbors();
910 
911  // remove all neighbors
912  m_neighbors[j]->neighbors().clear();
913 
914  typename NeighborGraph::iterator p = m_neighborGraph[j].begin();
915  typename NeighborGraph::iterator p0 = p;
916  bool flag = false;
917  for (;;)
918  {
919  if (flag) { if (p == p0) break; }
920  else flag = true;
921  m_neighbors[j]->neighbors().push_back(p->value);
922  if (p->to.size() != 1)
923  {
924  std::cout << "wW!";
925  /*
926  std::cout << "ori neighbors" << std::endl;
927  for (typename std::vector<VertexPointer>::const_iterator i = neighbors.begin(); i != neighbors.end(); ++i)
928  {
929  std::cout << (*i)->pos() << std::endl;
930  }
931  std::cout << "end ori neighbors" << std::endl;
932 
933  std::cout << "my neighbor number is " << j << std::endl;
934 
935  std::cout << "neighbors" << std::endl;
936  for (typename TVertexNode::VertexIndexCollection::const_iterator i = ntmp.begin(); i != ntmp.end(); ++i)
937  {
938  std::cout << (*i)->pos() << std::endl;
939  }
940  std::cout << "end neighbors" << std::endl;
941  std::cout << "triangles" << std::endl;
942  for (typename std::list<boost::array<std::size_t,3> >::const_iterator i = tri.begin(); i != tri.end(); ++i)
943  {
944  std::cout << (*i)[0] << " " << (*i)[1] << " " << (*i)[2] << std::endl;
945  }
946  //std::copy(tri.begin(), tri.end(), std::ostream_iterator<boost::array<std::size_t,3> >(std::cout, std::endl));
947  std::cout << "end triangles" << std::endl;
948  //std::copy(norms.begin(), norms.end(), std::ostream_iterator<double>(std::cout, " "));
949  for (std::list<boost::array<std::size_t,3> >::iterator i = tri.begin(); i != tri.end(); ++i)
950  {
951  std::cout << (*i)[0] << " " << (*i)[1] << " " << (*i)[2] << std::endl;
952  }
953 
954  exit(1);
955  */
956  }
957  if (p->to.size() == 0) break;
958  p = p->to.front();
959  }
960  }
961  }
962 
963  public: // functions
964 
965 
967  bool isRemovable(VertexPointer i)
968  {
969  m_error = none;
970  //std::cout << "A" << std::endl;
971  // copy list of neighbors in a vector, for fast random indexing
972  //std::cout << m_neighbors.size() << " " << i->neighbors().size() << " = " << std::flush;
973  m_neighbors.resize(i->neighbors().size());
974  //std::cout << m_neighbors.size() << std::endl;
975  std::copy(i->neighbors().begin(), i->neighbors().end(), m_neighbors.begin());
976  if (!this->neighborTriangulation(i)) return false;
977  // initialize oriented edges
978  //std::cout << m_neighborGraph.size() << " " << m_neighbors.size() << " = ";
979  m_neighborGraph.clear();
980  m_neighborGraph.resize(m_neighbors.size());
981  //std::cout << m_neighborGraph.size() << std::endl;
982  this->initializeOrientedEdges(i);
983  // Updating neighbor graphs
984  this->updateNeighborGraph();
985  // Checking that all neighbors have at least 3 neighbors
986  if (!this->checkNeighborsHaveThreeNeighbors()) return false;
987  // Checking that neighbors have correct neighborhood
988  // Incorrect neighborhood may appear when a neighbor was already sharing an edge with another neighbor of
989  // i that is not on its side, i.e that is not n-1 or n+1.
990  //std::cout << "H" << std::endl;
991  if (!this->checkCorrectNeighborhood()) return false;
992  //std::cout << "I" << std::endl;
993  return true;
994  }
995 
998  VertexPointer remove(VertexPointer i)
999  {
1000  // adding faces
1001  this->addFaces(i);
1002  // adding neighbors
1003  this->addNeighbors(i);
1004  // remove point
1005  return remove_vertex(i, m_graph_vertices, m_graph_faces);
1006  }
1007 
1008  /*
1011  bool operator()(VertexPointer & i)
1012  {
1013  //std::cout << "." << std::flush;
1014  if (!this->isRemovable(i)) return false;
1015  i = this->remove(i);
1016  return true;
1017  }
1018  */
1019 
1020 
1021  /*
1022  bool operator()(VertexPointer & i)
1023  {
1024  std::cout << "." << std::flush;
1025 
1026  // save list of neighbors
1027  // TODO: is it still necessary to save the neighbors?
1028  std::vector<VertexPointer> neighbors(i->neighbors().size());
1029  std::copy(i->neighbors().begin(), i->neighbors().end(), neighbors.begin());
1030 
1031  // Add new faces
1032  {
1033  std::list<boost::array<std::size_t,3> > tri;
1034  // get delaunay faces for more than 4 neighbors
1035  if (neighbors.size() >= 4)
1036  {
1037  tri = simple_delaunay_triangulation(simple_neighborhood_flattening(i->pos(), neighbors));
1038  }
1039  // For three neighbors, simply add the only triangle possible
1040  else if (neighbors.size() == 3)
1041  {
1042  boost::array<std::size_t,3> tmp = {0,1,2};
1043  tri.push_back(tmp);
1044  }
1045  // For two points or less, do not add any face. Note that if this happens, it means that the mesh
1046  // is in really bad shape -- actually the following might crash.
1047  else std::cout << "w2!";
1048 
1049  // Check consistency between number of points and number of faces
1050  if (tri.size() != neighbors.size() - 2)
1051  {
1052  std::cout << "wK!" << tri.size() << "-" << neighbors.size()-2;
1053  }
1054 
1055  //initialize oriented edges
1056  std::vector<NeighborGraph> neighborGraph(i->neighbors().size());
1057  std::vector<std::map<VertexPointer, typename std::list<NeighborGraphNode>::iterator, ItComp<VertexPointer> > > convmap(i->neighbors().size());
1058  for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1059  {
1060  // first pass: vertices
1061  {
1062  for (typename TVertexNode::VertexIndexCollection::const_iterator k = neighbors[j]->neighbors().begin(); k != neighbors[j]->neighbors().end(); ++k)
1063  {
1064  if (*k == i) continue;
1065  NeighborGraphNode node(*k);
1066  convmap[j][*k] = neighborGraph[j].insert(neighborGraph[j].end(), node);
1067  }
1068  }
1069  // second pass: edges
1070  {
1071  typename TVertexNode::VertexIndexCollection::const_iterator k = neighbors[j]->neighbors().begin();
1072  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k2(neighbors[j]->neighbors(), neighbors[j]->neighbors().begin());
1073  ++k2;
1074  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k3(neighbors[j]->neighbors(), neighbors[j]->neighbors().begin());
1075  ++k3;
1076  ++k3;
1077  for (; k != neighbors[j]->neighbors().end(); ++k, ++k2, ++k3)
1078  {
1079  if (*k2 == i) continue;
1080  if (*k != i) convmap[j][*k2]->from.push_back(convmap[j][*k]);
1081  if (*k3 != i) convmap[j][*k2]->to.push_back(convmap[j][*k3]);
1082  }
1083  }
1084  }
1085 
1086  // Updating neighbor graphs
1087  {
1088  for (std::list<boost::array<std::size_t,3> >::iterator newf = tri.begin(); newf != tri.end(); ++newf)
1089  {
1090  for (std::size_t n = 0; n < 3; ++n)
1091  {
1092  typename NeighborGraph::iterator p2, p3;
1093 
1094  p2 = std::find_if(neighborGraph[(*newf)[n]].begin(), neighborGraph[(*newf)[n]].end(), valueFinder(neighbors[(*newf)[(n+1)%3]]));
1095  p3 = std::find_if(neighborGraph[(*newf)[n]].begin(), neighborGraph[(*newf)[n]].end(), valueFinder(neighbors[(*newf)[(n+2)%3]]));
1096  if (p2 == neighborGraph[(*newf)[n]].end()) p2 = neighborGraph[(*newf)[n]].insert(p2, NeighborGraphNode(neighbors[(*newf)[(n+1)%3]]));
1097  if (p3 == neighborGraph[(*newf)[n]].end()) p3 = neighborGraph[(*newf)[n]].insert(p3, NeighborGraphNode(neighbors[(*newf)[(n+2)%3]]));
1098 
1099  p2->to.push_back(p3);
1100  p3->from.push_back(p2);
1101  }
1102  }
1103  }
1104 
1105  // Checking that neighbors have at least 3 neighbors
1106  for (std::size_t k = 0; k < neighborGraph.size(); ++k)
1107  {
1108  if (neighborGraph[k].size() < 3)
1109  {
1110  std::cout << "WREJECT!(small-neighborhood)";
1111  return false;
1112  }
1113  }
1114 
1115  // Checking that neighbors have correct neighborhood
1116  // Incorrect neighborhood may appear when a neighbor was already sharing an edge with another neighbor of
1117  // i that is not on its side, i.e that is not n-1 or n+1.
1118  for (std::size_t k = 0; k < neighborGraph.size(); ++k)
1119  {
1120  typename NeighborGraph::iterator p = neighborGraph[k].begin();
1121  typename NeighborGraph::iterator p0 = p;
1122  bool flag = false;
1123  for (;;)
1124  {
1125  if (flag) { if (p == p0) break; }
1126  else flag = true;
1127  if (p->to.size() != 1 || p->from.size() != 1)
1128  {
1129  std::cout << "WREJECT!(incorrect-neighborhood)";
1130  return false;
1131  }
1132  p = p->to.front();
1133  }
1134  }
1135 
1136 
1137  // adding faces
1138  {
1139  for (std::list<boost::array<std::size_t,3> >::iterator newf = tri.begin(); newf != tri.end(); ++newf)
1140  {
1141  // convert into graph faces
1142  TFaceNode f;
1143  for (std::size_t n = 0; n < 3; ++n)
1144  {
1145  f.face[n] = neighbors[(*newf)[n]];
1146  }
1147  // add face to graph
1148  typename std::list<TFaceNode>::iterator gf = m_graph_faces.insert(m_graph_faces.end(), f);
1149  Vector<float,3> normal = cross(
1150  i->faces().front()->face[0]->pos() - i->faces().front()->face[1]->pos(),
1151  i->faces().front()->face[0]->pos() - i->faces().front()->face[2]->pos()
1152  );
1153  // add face index to face points
1154  for (std::size_t n = 0; n < 3; ++n)
1155  {
1156  GroComp<VertexPointer> grocomp(f.face[0], f.face[1], f.face[2]);
1157  typename TVertexNode::FaceIndexCollection::iterator p = find_if(f.face[n]->faces().begin(), f.face[n]->faces().end(), grocomp);
1158  if (p != f.face[n]->faces().end())
1159  {
1160  std::cout << "FATAL: face already there: " << std::endl;
1161  std::cout << &*f.face[0] << " " << &*f.face[1] << " " << &*f.face[2] << std::endl;
1162  std::cout << &*(*p)->face[0] << " " << &*(*p)->face[1] << " " << &*(*p)->face[2] << std::endl;
1163  std::cout << "I'll continue as if nothing happened, but this is a bug and your algorithm is likely to go bananas :)" << std::endl;
1164  }
1165  f.face[n]->faces().push_back(gf);
1166  }
1167  }
1168  }
1169 
1170  // Adding neighbors
1171  for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1172  {
1173  typename TVertexNode::VertexIndexCollection ntmp = neighbors[j]->neighbors();
1174 
1175  // remove all neighbors
1176  neighbors[j]->neighbors().clear();
1177 
1178  typename NeighborGraph::iterator p = neighborGraph[j].begin();
1179  typename NeighborGraph::iterator p0 = p;
1180  bool flag = false;
1181  for (;;)
1182  {
1183  if (flag) { if (p == p0) break; }
1184  else flag = true;
1185  neighbors[j]->neighbors().push_back(p->value);
1186  if (p->to.size() != 1)
1187  {
1188  std::cout << "wW!";
1189  }
1190  if (p->to.size() == 0) break;
1191  p = p->to.front();
1192  }
1193  }
1194  }
1195  // remove point
1196  i = remove_vertex(i, m_graph_vertices, m_graph_faces);
1197  return true;
1198  }
1199  */
1200 
1201  bool operator()(VertexPointer & i)
1202  {
1203  //std::cout << "." << std::flush;
1204 
1205  // save list of neighbors
1206  // TODO: is it still necessary to save the neighbors?
1207 
1208  m_neighbors.resize(i->neighbors().size());
1209  std::copy(i->neighbors().begin(), i->neighbors().end(), m_neighbors.begin());
1210 
1211  // Add new faces
1212  {
1213  // TODO: we need this -- dunno why
1214  m_tri.clear();
1215  // get delaunay faces for more than 4 neighbors
1216  if (m_neighbors.size() >= 4)
1217  {
1218  m_tri = simple_delaunay_triangulation(simple_neighborhood_flattening(i->pos(), m_neighbors));
1219  }
1220  // For three neighbors, simply add the only triangle possible
1221  else if (m_neighbors.size() == 3)
1222  {
1223  boost::array<std::size_t,3> tmp = { {0,1,2} };
1224  m_tri.push_back(tmp);
1225  }
1226  // For two points or less, do not add any face. Note that if this happens, it means that the mesh
1227  // is in really bad shape -- actually the following might crash.
1228  else std::cout << "w2!";
1229 
1230  // Check consistency between number of points and number of faces
1231  if (m_tri.size() != m_neighbors.size() - 2)
1232  {
1233  std::cout << "wK!" << m_tri.size() << "-" << m_neighbors.size() - 2;
1234  }
1235 
1236  //initialize oriented edges
1237  //std::vector<NeighborGraph> neighborGraph(i->neighbors().size());
1238  // TODO: we need this -- dunno why
1239  m_neighborGraph.clear();
1240  m_neighborGraph.resize(i->neighbors().size());
1241  //std::vector<std::map<VertexPointer, typename std::list<NeighborGraphNode>::iterator, ItComp<VertexPointer> > > convmap(i->neighbors().size());
1242  m_convmap.resize(i->neighbors().size());
1243  for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1244  {
1245  // first pass: vertices
1246  {
1247  for (typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin(); k != m_neighbors[j]->neighbors().end(); ++k)
1248  {
1249  if (*k == i) continue;
1250  NeighborGraphNode node(*k);
1251  m_convmap[j][*k] = m_neighborGraph[j].insert(m_neighborGraph[j].end(), node);
1252  }
1253  }
1254  // second pass: edges
1255  {
1256  typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin();
1257  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k2(m_neighbors[j]->neighbors(), m_neighbors[j]->neighbors().begin());
1258  ++k2;
1259  const_cyclic_iterator<typename TVertexNode::VertexIndexCollection> k3(m_neighbors[j]->neighbors(), m_neighbors[j]->neighbors().begin());
1260  ++k3;
1261  ++k3;
1262  for (; k != m_neighbors[j]->neighbors().end(); ++k, ++k2, ++k3)
1263  {
1264  if (*k2 == i) continue;
1265  if (*k != i) m_convmap[j][*k2]->from.push_back(m_convmap[j][*k]);
1266  if (*k3 != i) m_convmap[j][*k2]->to.push_back(m_convmap[j][*k3]);
1267  }
1268  }
1269  }
1270 
1271  // Updating neighbor graphs
1272  {
1273  for (std::list<boost::array<std::size_t,3> >::iterator newf = m_tri.begin(); newf != m_tri.end(); ++newf)
1274  {
1275  for (std::size_t n = 0; n < 3; ++n)
1276  {
1277  typename NeighborGraph::iterator p2, p3;
1278 
1279  p2 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+1)%3]]));
1280  p3 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+2)%3]]));
1281  if (p2 == m_neighborGraph[(*newf)[n]].end()) p2 = m_neighborGraph[(*newf)[n]].insert(p2, NeighborGraphNode(m_neighbors[(*newf)[(n+1)%3]]));
1282  if (p3 == m_neighborGraph[(*newf)[n]].end()) p3 = m_neighborGraph[(*newf)[n]].insert(p3, NeighborGraphNode(m_neighbors[(*newf)[(n+2)%3]]));
1283 
1284  p2->to.push_back(p3);
1285  p3->from.push_back(p2);
1286  }
1287  }
1288  }
1289 
1290  // Checking that neighbors have at least 3 neighbors
1291  for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
1292  {
1293  if (m_neighborGraph[k].size() < 3)
1294  {
1295  //std::cout << "WREJECT!(small-neighborhood)";
1296  return false;
1297  }
1298  }
1299 
1300  // Checking that neighbors have correct neighborhood
1301  // Incorrect neighborhood may appear when a neighbor was already sharing an edge with another neighbor of
1302  // i that is not on its side, i.e that is not n-1 or n+1.
1303  for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
1304  {
1305  typename NeighborGraph::iterator p = m_neighborGraph[k].begin();
1306  typename NeighborGraph::iterator p0 = p;
1307  bool flag = false;
1308  for (;;)
1309  {
1310  if (flag) { if (p == p0) break; }
1311  else flag = true;
1312  if (p->to.size() != 1 || p->from.size() != 1)
1313  {
1314  //std::cout << "WREJECT!(incorrect-neighborhood)";
1315  return false;
1316  }
1317  p = p->to.front();
1318  }
1319  }
1320 
1321 
1322  // adding faces
1323  {
1324  for (std::list<boost::array<std::size_t,3> >::iterator newf = m_tri.begin(); newf != m_tri.end(); ++newf)
1325  {
1326  // convert into graph faces
1327  TFaceNode f;
1328  for (std::size_t n = 0; n < 3; ++n)
1329  {
1330  f.face[n] = m_neighbors[(*newf)[n]];
1331  }
1332  // add face to graph
1333  typename std::list<TFaceNode>::iterator gf = m_graph_faces.insert(m_graph_faces.end(), f);
1334  /*numeric_array<float,3> normal = cross(
1335  i->faces().front()->face[0]->pos() - i->faces().front()->face[1]->pos(),
1336  i->faces().front()->face[0]->pos() - i->faces().front()->face[2]->pos()
1337  );*/
1338  // add face index to face points
1339  for (std::size_t n = 0; n < 3; ++n)
1340  {
1341  GroComp<VertexPointer> grocomp(f.face[0], f.face[1], f.face[2]);
1342  typename TVertexNode::FaceIndexCollection::iterator p = find_if(f.face[n]->faces().begin(), f.face[n]->faces().end(), grocomp);
1343  if (p != f.face[n]->faces().end())
1344  {
1345  std::cout << "FATAL: face already there: " << std::endl;
1346  std::cout << &*f.face[0] << " " << &*f.face[1] << " " << &*f.face[2] << std::endl;
1347  std::cout << &*(*p)->face[0] << " " << &*(*p)->face[1] << " " << &*(*p)->face[2] << std::endl;
1348  std::cout << "I'll continue as if nothing happened, but this is a bug and your algorithm is likely to go bananas :)" << std::endl;
1349  }
1350  f.face[n]->faces().push_back(gf);
1351  }
1352  }
1353  }
1354 
1355  // Adding neighbors
1356  for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1357  {
1358  typename TVertexNode::VertexIndexCollection ntmp = m_neighbors[j]->neighbors();
1359 
1360  // remove all neighbors
1361  m_neighbors[j]->neighbors().clear();
1362 
1363  typename NeighborGraph::iterator p = m_neighborGraph[j].begin();
1364  typename NeighborGraph::iterator p0 = p;
1365  bool flag = false;
1366  for (;;)
1367  {
1368  if (flag) { if (p == p0) break; }
1369  else flag = true;
1370  m_neighbors[j]->neighbors().push_back(p->value);
1371  if (p->to.size() != 1)
1372  {
1373  std::cout << "wW!";
1374  }
1375  if (p->to.size() == 0) break;
1376  p = p->to.front();
1377  }
1378  }
1379  }
1380  // remove point
1381  i = remove_vertex(i, m_graph_vertices, m_graph_faces);
1382  return true;
1383  }
1384 
1385 
1386  private: // data, input
1387 
1388  std::list<TVertexNode> & m_graph_vertices;
1389  std::list<TFaceNode> & m_graph_faces;
1390 
1391  private: // data, output
1392 
1393  Error m_error;
1394 
1395  private: // data, internal
1396 
1397  std::vector<VertexPointer> m_neighbors;
1398  std::vector<NeighborGraph> m_neighborGraph;
1399  std::vector<std::map<VertexPointer, typename std::list<NeighborGraphNode>::iterator, Lesser_PointeeAddress<VertexPointer> > > m_convmap;
1400  std::list<boost::array<std::size_t,3> > m_tri;
1401  };
1402 
1403 
1404  //---------------------------------------------------------------------------
1405 
1406  //---------------------------------//
1407  // Remove_indexed_graph_vertices //
1408  //---------------------------------//
1409 
1412  template < typename TIndexCollection >
1414  {
1415  public: // typedefs
1418  typedef std::list<VertexNode> VertexNodeCollection;
1419  typedef std::list<FaceNode> FaceNodeCollection;
1420 
1421  public: // set & get
1422 
1426  bool complete() const { return m_complete; }
1427 
1430  unsigned int niter() const { return m_iter; }
1431 
1433  unsigned int count() const { return m_count; }
1434 
1436  std::vector<unsigned char> const & removed() { return m_res; }
1437 
1438  public: // operators
1439 
1440  void operator()
1441  (
1442  std::list<VertexNode> & graph_vertices
1443  , std::list<FaceNode> & graph_faces
1444  , TIndexCollection const & removed
1445  )
1446  {
1447  std::size_t nVertices = graph_vertices.size();
1448  assert(removed.size() == nVertices);
1449 
1450  // set all vertices as unremoved (yet).
1451  m_res.resize(nVertices, 0);
1452  m_iter = 0;
1453  m_count = 0;
1454  bool done;
1455  Vertex_remover<VertexNode, FaceNode> vertexRemover(graph_vertices, graph_faces);
1456  // Sometimes, a vertex cannot be removed. But it may be that it can be removed after
1457  // other points are removed. That's why we have this loop where we iterate on points that
1458  // have not yet been able to be removed.
1459  do
1460  {
1461  m_complete = true;
1462  done = true;
1463  std::list<VertexNode>::iterator i = graph_vertices.begin();
1464  std::list<FaceNode>::iterator itmp;
1465  while (i != graph_vertices.end())
1466  {
1467  if (i->neighbors().size() != i->faces().size())
1468  {
1469  std::cout << "[SERIOUS TOPOLOGY ERROR] F!=N -- I most probably screwed up your mesh, please report error; " << std::flush;
1470  }
1471  // NB: we save i->attr to access it when i is deleted
1472  std::size_t iInd = i->attribute();
1473  // do we wish to remove current point?
1474  if (removed[iInd] == 1)
1475  {
1476  // Here, the 'done' boolean should be here.
1477  // Note that it means that to be robust, I should add a check that the number of points
1478  // has strictly decreased during two iterations.
1479  m_complete = false;
1480  if (vertexRemover(i))
1481  {
1482  // NB: i has moved, nothing can rely on i anymore because, especially since it might
1483  // now point to end().
1484  // TODO: the complete/false structure is wrong here, because a
1485  // final pass necessarily means that nothing is done, while we
1486  // could be smart and detect for the last pass if any point was
1487  // denied removal.
1488  done = false;
1489  // increase removed counter
1490  ++m_count;
1491  // mark vertex as removed in output array.
1492  m_res[iInd] = 1;
1493  // do *not* increment i, since it has a new value already
1494  continue;
1495  }
1496  }
1497  ++i;
1498  }
1499  ++m_iter;
1500  } while (!done);
1501  }
1502 
1503  private: // data, output
1504  bool m_complete;
1505  unsigned int m_iter;
1506  unsigned int m_count;
1507  std::vector<unsigned char> m_res;
1508  };
1509 
1510  //---------------------------------------------------------------------------
1511 
1512  //---------------------------//
1513  // Remove_indexed_vertices //
1514  //---------------------------//
1515 
1517  template < typename TVertexCollection, typename TFaceCollection, typename TCNeighborhoods, typename TIndexCollection >
1519  {
1520  public: // typedefs
1523  public: // set & get
1524 
1526 
1530  bool complete() { return m_remover.complete(); }
1531 
1533  unsigned int count() { return m_remover.count(); }
1534 
1536  std::vector<unsigned char> const & removed() { return m_remover.removed(); }
1537 
1538  public: // operators
1539  void operator()
1540  (
1541  TVertexCollection const & vertices
1542  , TFaceCollection const & faces
1543  , TCNeighborhoods const & neighc
1544  , TIndexCollection const & removed
1545  , TVertexCollection & verticesOut
1546  , TFaceCollection & facesOut
1547  )
1548  {
1549  // convert mesh into a graph
1550  VertexNodeCollection graph_vertices;
1551  FaceNodeCollection graph_faces;
1552  list2graph_mesh_conversion(vertices, faces, neighc, graph_vertices, graph_faces);
1553  // add an attribute to each vertex corresponding to its initial rank
1554  {
1555  typename VertexNodeCollection::iterator it = graph_vertices.begin();
1556  std::size_t gvsize = graph_vertices.size();
1557  for (std::size_t i = 0; i < gvsize; ++i, ++it)
1558  {
1559  it->attribute() = i;
1560  }
1561  }
1562  // remove vertices in the graph
1563  m_remover(graph_vertices, graph_faces, removed);
1564  // convert graph back into mesh
1566  g2l(graph_vertices, graph_faces, verticesOut, facesOut);
1567  }
1568  private: // data, internal
1570  };
1571 
1572  //---------------------------------------------------------------------------
1573 
1574 
1582  // TODO: this should obsiously go into a class.
1583  template < typename TVertexCollection, typename TFaceCollection, typename TCNeighborhoods, typename TIndexCollection >
1584  //std::pair<std::vector<unsigned char>, std::size_t>
1585  std::vector<unsigned char>
1587  (
1588  TVertexCollection & vertices,
1589  TFaceCollection & faces,
1590  TCNeighborhoods const & neighc,
1591  TIndexCollection const & removed
1592  )
1593  {
1595  remover;
1596  remover(vertices, faces, neighc, removed, vertices, faces);
1597  //return std::make_pair(remover.removed(), remover.count());
1598  return remover.removed();
1599  }
1600 
1601  //---------------------------------------------------------------------------
1602 
1605  template < typename TVertexCollection, typename TNeighborhoodCollection >
1607  {
1608  public: // typedefs
1609  typedef unsigned char Label;
1610  typedef std::vector<Label> LabelCollection;
1611  public: // constants
1616  enum { UNPROCESSED = 0, KEEP, REMOVE };
1617  public: // constructors
1619  (
1620  TVertexCollection const & vertices
1621  , TNeighborhoodCollection const & neighs
1622  , LabelCollection & label
1623  )
1624  : m_vertices(vertices)
1625  , m_neighs(neighs)
1626  , m_label(label)
1627  {
1628  assert(vertices.size() == neighs.size());
1629  m_label.resize(vertices.size(), UNPROCESSED);
1630  }
1631  public: // set & get
1632  TVertexCollection const & vertices() { return m_vertices; }
1633  TNeighborhoodCollection const & neighs() { return m_neighs; }
1634  LabelCollection & label() { return m_label; }
1635  public: // operator
1637  bool operator()(std::size_t i)
1638  {
1639  // skip point if a decision has already been taken about it
1640  if (label()[i] != UNPROCESSED) return false;
1641  // label point as removed
1642  label()[i] = REMOVE;
1643  // mark all of its neighbors as kept
1644  for (std::size_t j = 0; j < neighs()[i].size(); ++j)
1645  {
1646  assert(neighs()[i][j] < label().size());
1647  assert(label()[neighs()[i][j]] != REMOVE);
1648  label()[neighs()[i][j]] = KEEP;
1649  }
1650  return true;
1651  }
1652  private: // data, input
1653  TVertexCollection const & m_vertices;
1654  TNeighborhoodCollection const & m_neighs;
1655  private: // data, internal
1656  LabelCollection & m_label;
1657  };
1658 
1659  //---------------------------------------------------------------------------
1660 
1663  template < typename TVertexCollection, typename TFaceCollection >
1664  std::list<std::size_t>
1665  quantizer
1666  (
1667  TVertexCollection & vertices
1668  , TFaceCollection & faces
1669  , std::size_t newSize
1670  )
1671  {
1672 
1673  // initialize a list containing the index of the vertices.
1674  // at the end only the index of the remaining vertices will remain.
1675  std::list<std::size_t> res(vertices.size());
1676  std::generate(res.begin(), res.end(), Incrementor<std::size_t>(0));
1677 
1678  // do nothing if nothing to do
1679  if (newSize >= vertices.size()) return res;
1680 
1681  // main loop, which stops when enough points are removed
1682  do
1683  {
1684  std::size_t n = vertices.size();
1685  //std::vector<unsigned char> removed(n, 0);
1686  typedef std::vector<std::vector<std::size_t> > Neighborhoods;
1687  shared_ptr<Neighborhoods> neighc = circular_neighborhoods(vertices, faces);
1688 
1689  // Compute a criterion to order candidates to removal
1690  /*
1691  Mesh_curvature<MeshTraits<Mesh_N>::VertexCollection, std::vector<std::vector<std::size_t> >, float>
1692  mc(getVertices(mesh), *neighc);
1693  */
1695  std::vector<std::pair<std::size_t, float> > sortedCurv(n);
1696  for (std::size_t i = 0; i < n; ++i)
1697  {
1698  /*
1699  mc.process(i);
1700  sortedCurv[i] = std::make_pair(i, min(1.0f, std::abs(mc.gaussianCurvature())));
1701  */
1702  sortedCurv[i] = std::make_pair(i, mwe(i));
1703  }
1704  // order points according to their curvatures, higher curvatures first.
1705  std::sort(sortedCurv.begin(), sortedCurv.end(), Greater_Pair2<std::size_t, float>());
1706 
1707  //for (std::size_t i = 0; i < n; ++i) cout << sortedCurv[i].second << " ";
1708  //std::cout << std::endl;
1709 
1710  // loop through all vertices, higher curvature first
1711  std::vector<unsigned char> removed;
1713  declabeler(vertices, *neighc, removed);
1714  std::size_t count = 0;
1715  for (std::size_t i0 = 0; i0 < n; ++i0)
1716  {
1717  // get real index of current vertex
1718  std::size_t i = sortedCurv[i0].first;
1719  // Try to label i as removable, go to next vertex if unsuccessful
1720  if (!declabeler(i)) continue;
1721  // add a fraction of the displacement to neighbors
1722  for (std::size_t j = 0; j < (*neighc)[i].size(); ++j)
1723  {
1724  vertices[(*neighc)[i][j]] += (vertices[i] - vertices[(*neighc)[i][j]]) * (1.0f / (*neighc)[i].size());
1725  }
1726  ++count;
1727  // stop here if enough points are labeled
1728  if (n - count < newSize) break;
1729  }
1730  // Put 'removed' in standard binary form
1731  for (std::size_t i = 0; i < n; ++i) removed[i] = (removed[i] == 2 ? 1 : 0);
1732  //std::pair<std::vector<unsigned char>, std::size_t> tmp
1733  std::vector<unsigned char> tmp
1734  = remove_vertices(vertices, faces, *neighc, removed);
1735  // remove indices of removed vertices from the list of remaining vertices
1736  {
1737  std::size_t i = 0;
1738  std::list<std::size_t>::iterator iRes = res.begin();
1739  for (; iRes != res.end(); ++i)
1740  {
1741  if (tmp[i])
1742  {
1743  iRes = res.erase(iRes);
1744  }
1745  else
1746  {
1747  ++iRes;
1748  }
1749  }
1750  }
1751  //mesh.getNeighborIndices() = getNeighborIndices(mesh);
1752  //} while (0);
1753  } while (vertices.size() > newSize);
1754 
1755  return res;
1756  }
1757 
1758  //---------------------------------------------------------------------------
1759 
1762  template < typename TVertexCollection, typename TFaceCollection >
1763  std::list<std::size_t>
1764  quantizer_2
1765  (
1766  TVertexCollection & vertices
1767  , TFaceCollection & faces
1768  )
1769  {
1770  std::size_t n = vertices.size();
1771  // initialize a list containing the index of the vertices.
1772  // at the end only the index of the remaining vertices will remain.
1773  std::list<std::size_t> res(n);
1774  std::generate(res.begin(), res.end(), Incrementor<std::size_t>(0));
1775 
1776  typedef std::vector<std::vector<std::size_t> > Neighborhoods;
1777  shared_ptr<Neighborhoods> neighc = circular_neighborhoods(vertices, faces);
1778 
1779  // Compute a criterion to order candidates to removal
1781  std::vector<std::pair<std::size_t, float> > sortedCurv(n);
1782  for (std::size_t i = 0; i < n; ++i)
1783  {
1784  sortedCurv[i] = std::make_pair(i, mwe(i));
1785  }
1786  // order points according to their curvatures, higher curvatures first.
1787  std::sort(sortedCurv.begin(), sortedCurv.end(), Greater_Pair2<std::size_t, float>());
1788 
1789  // loop through all vertices, higher curvature first
1790  std::vector<unsigned char> removed;
1792  declabeler(vertices, *neighc, removed);
1793  for (std::size_t i0 = 0; i0 < n; ++i0)
1794  {
1795  // get real index of current vertex
1796  std::size_t i = sortedCurv[i0].first;
1797  // Try to label i as removable, go to next vertex if unsuccessful
1798  if (!declabeler(i)) continue;
1799  // add a fraction of the displacement to neighbors
1800  for (std::size_t j = 0; j < (*neighc)[i].size(); ++j)
1801  {
1802  vertices[(*neighc)[i][j]] += (vertices[i] - vertices[(*neighc)[i][j]]) * (1.0f / (*neighc)[i].size());
1803  }
1804  }
1805  // Put 'removed' in standard binary form
1806  for (std::size_t i = 0; i < n; ++i) removed[i] = (removed[i] == 2 ? 1 : 0);
1807  //std::pair<std::vector<unsigned char>, std::size_t> tmp
1808  std::vector<unsigned char> tmp
1809  = remove_vertices(vertices, faces, *neighc, removed);
1810  // remove indices of removed vertices from the list of remaining vertices
1811  {
1812  std::size_t i = 0;
1813  std::list<std::size_t>::iterator iRes = res.begin();
1814  for (; iRes != res.end(); ++i)
1815  {
1816  if (tmp[i])
1817  {
1818  iRes = res.erase(iRes);
1819  }
1820  else
1821  {
1822  ++iRes;
1823  }
1824  }
1825  }
1826  return res;
1827  }
1828 
1829 
1830  /*
1831  template < typename TIndex, typename TVertexXsr, typename TFaceXsr, typename TNeighborhoodXsr >
1832  std::list<std::size_t>
1833  quantizer2
1834  (
1835  TIndex begin,
1836  TIndex end,
1837  TVertexXsr vertexXsr,
1838  TFaceXsr faceXsr,
1839  TNeighborhoodXsr neighXsr,
1840  std::size_t newSize
1841  )
1842  {
1843  typedef TIndex index_type;
1844  typedef typename TNeighborhoodXsr::reference NeighborhoodRef;
1845  typedef typename TNeighborhoodXsr::value_type Neighborhood;
1846 
1847  std::size_t bigCount = 0;
1848 
1849  // Create a list holding the index number of the vertices.
1850  std::list<std::size_t> res(vertices.size());
1851  std::generate(res.begin(), res.end(), Incrementor<std::size_t>(0));
1852 
1853  do
1854  {
1855  std::size_t n = vertices.size();
1856  std::vector<unsigned char> removed(n, 0);
1857  // compute decimation criterion
1858  MeshWaveletEnergy2<TVertexCollection, Neighborhoods, float> mwe(vertexXsr, neighXsr);
1859  std::vector<std::pair<std::pair<TIndex, std::size_t>, float> > sortedCurv(n);
1860 
1861  std::size_t i = 0;
1862  for (index_type ind = begin; ind != end; ++ind, ++i)
1863  {
1864  sortedCurv[i] = std::make_pair(std::make_pair(ind, i), mwe(ind));
1865  }
1866  // order points according to their curvatures, higher curvatures first.
1867  std::sort(sortedCurv.begin(), sortedCurv.end(), Greater_Pair2<std::size_t, float>());
1868  // loop through all vertices, higher curvature first
1869  std::size_t count = 0;
1870  for (std::size_t i0 = 0; i0 < n; ++i0)
1871  {
1872  // get real index of current vertex
1873  std::pair<TIndex, std::size_t> tmp = sortedCurv[i0].first;
1874  TIndex ind = tmp.first;
1875  std::size_t i = tmp.second;
1876  // skip point if not labeled as 'unprocessed'
1877  if (removed[i]) continue;
1878  // label point as removed
1879  removed[i] = 2;
1880  ++count;
1881  if (n - count < newSize)
1882  {
1883  break;
1884  }
1885  // mark all of its neighbors as kept
1886  {
1887  NeighborhoodRef nh = neighXsr(ind);
1888  for (typename Neighborhood::const_iterator iN = nh.begin(); iN != nh.end(); ++iN)
1889  {
1890  assert(removed(*iN) != 2);
1891  removed(*iN) = 1;
1892  }
1893  }
1894  for (std::size_t j = 0; j < neighXsr() (*neighc)[i].size(); ++j)
1895  {
1896  if (removed[(*neighc)[i][j]] == 2)
1897  {
1898  std::cout << "(e!neighbor_marked_as_removed)";
1899  }
1900  removed[(*neighc)[i][j]] = 1;
1901  }
1902  }
1903  // add a fraction of the displacement to neighbors
1904  {
1905  for (std::size_t j = 0; j < (*neighc)[i].size(); ++j)
1906  {
1907  vertices[(*neighc)[i][j]] += (vertices[i] - vertices[(*neighc)[i][j]]) * (1.0f / (*neighc)[i].size());
1908  }
1909  }
1910  }
1911  // Put 'removed' in standard binary form
1912  for (std::size_t i = 0; i < n; ++i) removed[i] = (removed[i] == 2 ? 1 : 0) ;
1913  //std::cout << "Marked " << count << " points out of " << n << " for deletion" << std::endl;
1914  std::pair<std::vector<unsigned char>, std::size_t> tmp = remove_vertices(vertices, faces, *neighc, removed);
1915  //std::cout << count << "points could be effectively removed" << std::endl;
1916  bigCount += tmp.second;
1917 
1918  {
1919  std::size_t i = 0;
1920  std::list<std::size_t>::iterator iRes = res.begin();
1921  for (; iRes != res.end(); ++i)
1922  {
1923  if (tmp.first[i])
1924  {
1925  iRes = res.erase(iRes);
1926  }
1927  else
1928  {
1929  ++iRes;
1930  }
1931  }
1932  }
1933 
1934  //mesh.getNeighborIndices() = getNeighborIndices(mesh);
1935  //} while (0);
1936  //} while (bigCount < N);
1937  } while (vertices.size() > newSize);
1938 
1939  return res;
1940  }
1941  */
1942 
1943 } // namespace til
1944 
1945 
1946 //#include "mesh_decimation.tpp"
1947 
1948 #endif
1949 
TVertexXsr::value_type Vertex
std::vector< Label > LabelCollection
#define M_PI
Definition: til_common.h:48
numeric_array< TPrec, 3 > cross(const numeric_array< T1, 3 > &vec1, const numeric_array< T2, 3 > &vec2, prec< TPrec >)
Return the cross product of two 3D vectors.
boost::enable_if< is_Image< TImage >, typename TImage::value_type >::type min(const TImage &im)
std::vector< numeric_array< float, 2 > > simple_neighborhood_flattening(const numeric_array< float, 3 > &point, const TNeighbors &neighbors)
void sqrt(const TImage &in, TImage &out)
Definition: imageArith.h:326
MeshVertexNodeX< std::size_t > VertexNode
Distance of a vertex to the mean of its neighbors divided by the area of its Voronoi cell...
bool complete() const
Returns true if it has been able to remove all desired points.
shared_ptr< std::vector< std::vector< typename TFaceCollection::value_type::value_type > > > circular_neighborhoods(TFaceCollection const &faces, std::size_t nVertices)
Get point neighbors so that they form a loop around points.
TPrec operator()(std::size_t i)
std::list< FaceNode > FaceNodeCollection
std::vector< VertexPointer > & neighbors()
TPrec dot(const numeric_array< T1, D > &a1, const numeric_array< T2, D > &a2, prec< TPrec >)
Return the dot product of two vectors.
INLINE double norm(const T &a, const T &b)
< Euclidean norm of 2D vector (a, b)
TNeighborhoodCollection const & neighs()
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
A const cyclic iterator is a const iterator that goes back to the begining of the container when it r...
std::vector< unsigned char > const & removed()
Returns a binary index of those points who have been removed.
std::list< std::size_t > quantizer(TVertexCollection &vertices, TFaceCollection &faces, std::size_t newSize)
Decimates a mesh until a specified number of vertices is reached.
void sort(T &a, T &b, T &c)
Sort a, b, c in decreasing order (a>=b>=c).
TPrec operator()(index_type i)
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
Definition: boxTools.h:56
TNeighborhoodXsr::reference NeighborhoodRef
TVertexCollection::value_type Vertex
std::list< VertexNode > VertexNodeCollection
numeric_array< T, D > abs(const numeric_array< T, D > &a)
Absolute value, element-wise.
std::list< boost::array< std::size_t, 3 > > simple_delaunay_triangulation(std::vector< numeric_array< float, 2 > > points)
std::vector< unsigned char > const & removed()
Returns a binary index of those points who have been removed.
TImage::value_type max(const TImage &im)
Returns the maximum intensity of the input image.
std::unique_ptr< VoxelList > addNeighbors(TImage &seg, const std::vector< numeric_array< int, 3 > > &vl, const std::vector< numeric_array< int, 3 > > &vnh, Ghost &ghost, typename TImage::value_type newColor)
< New boundary points
bool operator()(std::size_t i)
Try to remove i-th point. Returns true if successful.
bool complete()
Returns true if it has been able to remove all desired points.
void process(index_type i)
Computes all the good stuff at the i-th vertex.
Definition: meshUtils.h:802
Vertex_remover(std::list< TVertexNode > &graph_vertices, std::list< TFaceNode > &graph_faces)
T angle(T x, T y, T norm)
Returns the angle between (x,y) and the x-axis, with the norm of (x,y) provided.
TPrec dist(const numeric_array< T1, D > &v1, const numeric_array< T2, D > &v2, prec< TPrec >)
Return the Euclidean distance between two arrays.
TVertexCollection const & vertices()
void copy(const TImage &in, TImage &out)
Copy one image to another.
Definition: imageTools.h:133
unsigned int count() const
Returns the number of points that have been effectively removed.
std::list< TVertexNode >::iterator remove_vertex(typename std::list< TVertexNode >::iterator i, std::list< TVertexNode > &graph_vertices, std::list< TFaceNode > &graph_faces)
Remove a vertex from a mesh.
Remove vertices from a mesh, given a set of index.
bool operator<(const AimsVector< T, D > &v1, const AimsVector< T, D > &v2)
Lexicographic order.
Definition: aims_wrap.h:37
operator< on the address in memory of the pointed object
Definition: miscUtils.h:368
A class to remove a vertex from a mesh, and remeshing the hole.
TOutIterator bounding_triangle(TPointIterator pbegin, TPointIterator pend, TOutIterator out)
Given a list of 2D points, compute a bounding equilateral triangle.
Remove vertices from a graph list mesh, given a set of index.
TNeighborhoodXsr::value_type Neighborhood
A class which returns a value that is increased everytime it is returned.
Definition: miscUtils.h:463
void max_helper(T &maxx, T x)
Little helper for something often used when looking for a maximum.
Definition: miscTools.h:213
unsigned int count()
Returns the number of points that have been effectively removed.
Remove_indexed_graph_vertices< TIndexCollection >::VertexNodeCollection VertexNodeCollection
bool isRemovable(VertexPointer i)
Check that vertex i can be removed from the mesh.
prec_type voronoiArea() const
Return computed voronoi area at vertex.
Definition: meshUtils.h:788
MeshFaceNodeX< VertexNode > FaceNode
Attempt to label a vertex as removable, and if successfull, label its neighbors as unremovable...
std::vector< unsigned char > remove_vertices(TVertexCollection &vertices, TFaceCollection &faces, TCNeighborhoods const &neighc, TIndexCollection const &removed)
NB: vertices are not removed one by one but in groups via this kind of functions, because the static ...
Remove_indexed_graph_vertices< TIndexCollection >::FaceNodeCollection FaceNodeCollection
TVertexXsr::index_type index_type
bool operator()(VertexPointer &i)
std::list< std::size_t > quantizer_2(TVertexCollection &vertices, TFaceCollection &faces)
Decimates a mesh until no more vertex with unremoved neighbors can be removed.
void list2graph_mesh_conversion(const TVerticesIn &verticesIn, const TFacesIn &facesIn, const TNeighbors &neighc, std::list< TVertexNode > &verticesOut, std::list< TFaceNode > &facesOut)
Remove_indexed_graph_vertices< TIndexCollection > & remover()
operator> on the second member of a pair.
Definition: miscUtils.h:388
A dummy class used to pass a precision type for computations to some functions.
MeshWaveletEnergy2(const TVertexXsr &vertexXsr, const TNeighborhoodXsr &neighXsr)
unsigned int niter() const
Number of iterations that has been necessary to remove all points or to reach a configuration where n...