aimstil  5.0.5
meshUtils.h
Go to the documentation of this file.
1 #ifndef _MESHUTILS_H_
2 #define _MESHUTILS_H_
3 
4 // includes from STL
5 #include <cmath>
6 #include <numeric> // accumulate
7 
8 
9 // includes from BOOST
10 #include <boost/shared_ptr.hpp>
11 using boost::shared_ptr;
12 
13 // includes from AIMS
14 #include "aims/mesh/surface.h"
15 #include "aims/vector/vector.h"
16 
17 // includes from TIL
18 #include "til/functors.h"
19 #include "til/is_traits.h"
20 #include "til/loop.h"
21 #include "til/numeric_array.h"
22 #include "til/TExpr.h"
23 #include "til/traits.h"
24 //#include "til/Vector3.h"
25 
26 // includes from TIL
27 #include "cyclic_iterator.h"
28 //#include "convert.h"
29 #include "geometrics.h"
30 #include "globalTraits.h"
31 #include "Mesh.h"
32 #include "MeshTraits.h"
33 #include "miscUtils.h"
34 
35 
36 // declarations
37 template < typename T > class MeshTraits;
38 
39 
40 
41 
42 AimsSurfaceTriangle *
44 (
45  const Point3df &center,
46  float radius,
47  int iter
48  );
49 
50 namespace til
51 {
52 
54  template < typename TMesh >
55  inline
56  std::size_t getVertexNumber(const TMesh &, std::size_t i) { return i; }
57 
59  template < typename TMesh, typename TVertex >
60  // make sure that Vertex Collection is contiguous in memory so that fast
61  // arithmetic can be used
62  //typename boost::enable_if<boost::is_same<typename MeshTraits<TMesh>::VertexCollection::difference_type, std::ptrdiff_t>, std::size_t >::type
63  inline
64  typename boost::enable_if<is_same_naked<typename MeshTraits<TMesh>::Vertex, TVertex>, std::size_t>::type
65  getVertexNumber(const TMesh & mesh, TVertex *p)
66  {
67  // NB: it seems that for some reason, we don't have to divide by sizeof.
68  // I would like to be sure this is standard...
69  //return (p - &(getVertices(mesh)[0])) / sizeof(typename MeshTraits<TMesh>::Vertex);
70  return p - &(getVertices(mesh)[0]);
71 
72  }
73 
74 
75  namespace detail
76  {
77 /* template < class TMeshFrom, class TMeshTo >
78  void convert_mesh_1(const TMeshFrom & meshFrom, TMeshTo & meshTo)
79  {
80  // allocate space for vertices
81  getVertices(meshTo).resize(getVertices(meshFrom).size());
82  // convert vertices
83  using namespace til::expr;
84  std::transform(getVertices(meshFrom).begin(), getVertices(meshFrom).end(), getVertices(meshTo).begin(),
85  ::til::functor::Cast<typename MeshTraits<TMeshTo>::Vertex, typename MeshTraits<TMeshFrom>::Vertex>());
86  //loop(getVertices(meshTo), getVertices(meshFrom), Convert2<typename MeshTraits<TMeshFrom>::Vertex, typename MeshTraits<TMeshTo>::Vertex>());
87  //convert(getVertices(meshFrom), getVertices(meshTo));
88  // allocate space for face indices
89  getFaceIndices(meshTo).resize(getFaceIndices(meshFrom).size());
90  // convert face indices
91  detail::loop_xx(castTo(*_2, *_1), getFaceIndices(meshFrom), getFaceIndices(meshTo));
92  //std::transform(getFaceIndices(meshFrom).begin(), getFaceIndices(meshFrom).end(), getFaceIndices(meshTo).begin(),
93  //loop(getFaceIndices(meshTo), getFaceIndices(meshFrom), Convert());
94  //convert(getFaceIndices(meshFrom), getFaceIndices(meshTo));
95  }
96 */
97 
98  inline void convert_aimsmeshTomesh1(const AimsTimeSurface<3, Void> & meshFrom, til::Mesh1 & meshTo)
99  {
100  // allocate space for vertices
101  int size = meshFrom.vertex().size();
102  getVertices(meshTo).resize(size);
103 
104  // convert vertices
105  using namespace til::expr;
106  std::transform(meshFrom.vertex().begin(), meshFrom.vertex().end(), getVertices(meshTo).begin(),
108  size = meshFrom.polygon().size();
109  getFaceIndices(meshTo).resize(size);
110 
111  // convert face indices
112  detail::loop_xx(castTo(*_2, *_1), meshFrom.polygon(), getFaceIndices(meshTo));
113  }
114 
115  inline void convert_mesh1Toaimsmesh(const til::Mesh1 & meshFrom, AimsTimeSurface<3, Void> & meshTo)
116  {
117  // allocate space for vertices
118  int size = getVertices(meshFrom).size();
119  meshTo.vertex().resize(size);
120 
121  // convert vertices
122  using namespace til::expr;
123  std::transform(getVertices(meshFrom).begin(), getVertices(meshFrom).end(), meshTo.vertex().begin(),
125  size = getFaceIndices(meshFrom).size();
126  meshTo.polygon().resize(size);
127 
128  // convert face indices
129  detail::loop_xx(castTo(*_2, *_1), getFaceIndices(meshFrom), meshTo.polygon());
130  }
131 
133  template < class TMeshFrom, class TMeshTo >
134  inline void convert_mesh_2(const TMeshFrom & meshFrom, TMeshTo & meshTo)
135  {
136  // allocate space for vertices
137  getVertices(meshTo).resize(getVertices(meshFrom).size());
138  // convert vertices
139  //convert(getVertices(meshFrom), getVertices(meshTo));
140  //std::transform(getVertices(meshFrom).begin(), getVertices(meshFrom).end(), getVertices(meshTo).begin,
141  // functor::Cast<typename TMeshTo::Vertex, typename TMeshFrom::Vertex>());
142  {
143  using namespace til::expr;
144  detail::loop_xx(castTo(*_1, *_2), getVertices(meshTo), getVertices(meshFrom));
145  }
146  //loop(getVertices(meshTo), getVertices(meshFrom), Convert());
147  {
148  //allocate space for face indices
149  getFaceIndices(meshTo).resize(getFaceIndices(meshFrom).size());
150  // copy face indices
153  for (; iff != getFaceIndices(meshFrom).end(); ++iff, ++ift)
154  {
155  (*ift)[0] = &(getVertices(meshTo)[(*iff)[0]]);
156  (*ift)[1] = &(getVertices(meshTo)[(*iff)[1]]);
157  (*ift)[2] = &(getVertices(meshTo)[(*iff)[2]]);
158  }
159  }
160  }
161  template < class TMeshFrom, class TMeshTo >
162  inline void convert_mesh_3(const TMeshFrom & meshFrom, TMeshTo & meshTo)
163  {
164  // allocate space for vertices
165  getVertices(meshTo).resize(getVertices(meshFrom).size());
166  // copy vertices
167  //convert(getVertices(meshFrom), getVertices(meshTo));
168  //loop(getVertices(meshTo), getVertices(meshFrom), Convert());
169  using namespace til::expr;
170  detail::loop_xx(castTo(*_1, *_2), getVertices(meshTo), getVertices(meshFrom));
171  //std::transform(getVertices(meshFrom).begin(), getVertices(meshFrom).end(), getVertices(meshTo).begin(),
172  // functor::Cast<typename TMeshTo::Vertex, typename TMeshFrom::Vertex>());
173  {
174  //allocate space for face indices
175  getFaceIndices(meshTo).resize(getFaceIndices(meshFrom).size());
176  // copy face indices
179  for (; iff != getFaceIndices(meshFrom).end(); ++iff, ++ift)
180  {
181  (*ift)[0] = getVertexNumber(meshFrom, (*iff)[0]);
182  (*ift)[1] = getVertexNumber(meshFrom, (*iff)[1]);
183  (*ift)[2] = getVertexNumber(meshFrom, (*iff)[2]);
184  }
185  }
186  }
187  }
188 
189 
190  /*
192  template < typename TVertexCollection >
193  Point3dd
194  getCentroid(const TVertexCollection &vertices)
195  {
196  typename TVertexCollection::const_iterator iVertex;
197  typename TVertexCollection::const_iterator iNextVertex;
198  Point3dd res(0.0, 0.0, 0.0);
199  double area, totalArea = 0.0;
200 
201  // Center all computations around average for numerical precision
202  Point3dd m = getAverage(vertices);
203 
204  // Loop through all pair of vertices
205  iVertex = vertices.begin();
206  iNextVertex = vertices.begin();
207  ++iNextVertex;
208  for (; iNextVertex != vertices.end(); ++iVertex, ++iNextVertex)
209  {
210  // compute the (signed) area of the triangle (Center, Vertex, NextVertex)
211  area = dot(*iNextVertex - *iVertex, *iVertex - m);
212  // add it to the total area
213  totalArea += area;
214  // add weighted centroid of this triangle to the result
215  res += area * (*iVertex + *iNextVertex + m) / 3.0;
216  }
217  // Do the same thing for the last pair
218  area = dot(*(vertices.begin()) - *iNextVertex, *iNextVertex - m);
219  totalArea += area;
220  res += area * (*(vertices.begin()) + *iNextVertex + m) / 3.0;
221  // Divide by the total area
222  res /= totalArea;
223  // Add center
224  res += m;
225  return res;
226  }
227  */
228 
229  //---------------------------------------------------------------------------
230 
231  template < typename TFaceCollection >
233  {
234  public: // typedefs
235  typedef std::size_t index_type;
236  typedef std::pair<index_type,index_type> Edge;
237  typedef std::map<Edge, std::vector<index_type> > Edges;
238  public: // functions
239  void operator()
240  (
241  TFaceCollection const & faces,
242  std::vector<Edge> & res,
243  std::vector<std::vector<index_type> > & newfaces
244  );
245  private: // functions
246  void insert_edge
247  (
248  Edges & edges,
249  Edge edge,
250  std::size_t i
251  );
252  };
253 
254  //---------------------------------------------------------------------------
255 
256  template < typename TFaceCollection >
258  (
259  Edges & edges,
260  Edge edge,
261  std::size_t i
262  )
263  {
264  typename Edges::iterator pos = edges.find(edge);
265  if (pos != edges.end())
266  {
267  pos->second.push_back(i);
268  }
269  else
270  {
271  edges.insert(typename Edges::value_type(edge, std::vector<std::size_t>(1,i)));
272  }
273  }
274 
275  //---------------------------------------------------------------------------
276 
277  template < typename TFaceCollection >
279  (
280  TFaceCollection const & faces,
281  std::vector<Edge> & res,
282  std::vector<std::vector<index_type> > & newfaces
283  )
284  {
285  Edges edges;
286  typename TFaceCollection::const_iterator iFace;
287  std::size_t i;
288  for (i = 0, iFace = faces.begin(); iFace != faces.end(); ++iFace, ++i)
289  {
290  // We sort vertex by index to input only edges (a,b) where
291  // a < b. This is to ensure that the same edge is not
292  // input twice as (a,b) and (b,a).
293  insert_edge(edges, make_sorted_pair((*iFace)[0], (*iFace)[1]), i);
294  insert_edge(edges, make_sorted_pair((*iFace)[1], (*iFace)[2]), i);
295  insert_edge(edges, make_sorted_pair((*iFace)[2], (*iFace)[0]), i);
296  }
297  // convert result into a std::vector
298  res.resize(edges.size());
299  //std::copy(edges.begin(), edges.end(), res.begin());
300  //std::transform(edges.begin(), edges.end(), res.begin(), Return_pair1<Edge, std::vector<index_type> >());
301 
302  newfaces.resize(faces.size());
303  typename Edges::const_iterator ie;
304  for (i = 0, ie = edges.begin(); ie != edges.end(); ++ie, ++i)
305  {
306  res[i] = ie->first;
307  assert(ie->second.size() == 2);
308  for (std::size_t j = 0; j < ie->second.size(); ++j)
309  {
310  newfaces[ie->second[j]].push_back(i);
311  }
312  }
313  }
314 
315  //---------------------------------------------------------------------------
316 
317  template < typename TFaceCollection >
318  inline void
319  //shared_ptr<std::vector<std::pair<std::size_t, std::size_t> > >
321  (
322  TFaceCollection const & faces,
323  std::vector<std::pair<std::size_t, std::size_t> > & res,
324  std::vector<std::vector<std::size_t> > & newfaces
325  )
326  {
327  Get_edges_and_faces<TFaceCollection>()(faces, res, newfaces);
328  }
329 
330  //---------------------------------------------------------------------------
331 
333  template < typename TFaceCollection >
335  faces2edges(TFaceCollection const & faces)
336  {
337  typedef std::size_t index_type;
338  typedef std::pair<index_type,index_type> Edge;
339 
340  std::set<Edge> edges;
341  typename TFaceCollection::const_iterator iFace = faces.begin();
342  for (; iFace != faces.end(); ++iFace)
343  {
344  // We sort vertex by index to input only edges (a,b) where
345  // a < b. This is to ensure that the same edge is not
346  // input twice as (a,b) and (b,a).
347  edges.insert(make_sorted_pair((*iFace)[0], (*iFace)[1]));
348  edges.insert(make_sorted_pair((*iFace)[1], (*iFace)[2]));
349  edges.insert(make_sorted_pair((*iFace)[2], (*iFace)[0]));
350  }
351  // convert result into a std::vector
352  shared_ptr<std::vector<Edge> > res(new std::vector<Edge>(edges.size()));
353  std::copy(edges.begin(), edges.end(), res->begin());
354  return res;
355  }
356 
357  //---------------------------------------------------------------------------
358 
361  template < typename TNeighborhoodCollection >
362  inline void
364  (
365  TNeighborhoodCollection const & neigh,
366  std::vector<std::pair<std::size_t, std::size_t> > & edges
367  )
368  {
369  typedef std::pair<std::size_t, std::size_t> Edge;
370  std::set<Edge> my_edges;
371  for (std::size_t i = 0; i < neigh.size(); ++i)
372  {
373  for (std::size_t j = 0; j < neigh[i].size(); ++j)
374  {
375  my_edges.insert(make_sorted_pair(i, neigh[i][j]));
376  }
377  }
378  edges.resize(edges.size());
379  std::copy(my_edges.begin(), my_edges.end(), edges.begin());
380  // TODO: remove this test because it does not *have* to be the case, because neighborhoods may
381  // not be symmetrical, even though I wish they are.
382  assert(edges.size() * 2 == neigh.size());
383  }
384 
385  //---------------------------------------------------------------------------
386 
392  // TODO: add templation on return type and use "if (MeshTraits::has_face_indices)" etc.
393  template < typename TFaceCollection >
395  circular_neighborhoods(TFaceCollection const & faces, std::size_t nVertices);
396 
397  //---------------------------------------------------------------------------
398 
399  template < typename TVertexCollection, typename TFaceCollection >
400  inline
402  circular_neighborhoods(const TVertexCollection & vertices, const TFaceCollection & faces)
403  { return circular_neighborhoods(faces, vertices.size()); }
404 
405  //---------------------------------------------------------------------------
406 
407  // TODO: add templation on return type and use "if (MeshTraits::has_face_indices)" etc.
408  template < typename TMesh >
410  getNeighborIndices(const TMesh & mesh)
411  {
412  typedef typename MeshTraits<TMesh>::FaceIndex::value_type VertexIndex;
413 
414  // Allocate the result -- it should have as many elements as
415  // the number of vertices of the mesh.
416  std::vector<std::set<VertexIndex> > res(size(getVertices(mesh)));
417  // for all faces
419  iFic != getFaceIndices(mesh).end(); ++iFic)
420  {
421  // for all couple of points on the face
422  typename MeshTraits<TMesh>::FaceIndex::const_iterator iFi1 = iFic->begin();
423  typename MeshTraits<TMesh>::FaceIndex::const_iterator iFi2 = iFi1+1;
424  for (;iFi2 != iFic->end(); ++iFi1, ++iFi2)
425  {
426  res[getVertexNumber(mesh, *iFi2)].insert(*iFi1);
427  res[getVertexNumber(mesh, *iFi1)].insert(*iFi2);
428  }
429  // we use iFi1 that should now points to the last element.
430  // do not use container.end() instead! This points nowhere.
431  res[getVertexNumber(mesh, *(iFic->begin()))].insert(*iFi1);
432  res[getVertexNumber(mesh, *iFi1)].insert(*(iFic->begin()));
433  }
434  //convert the result into a vector
435  shared_ptr<std::vector<std::vector<VertexIndex> > > res2(new std::vector<std::vector<VertexIndex> >);
436  allocate_sameSize(res, *res2);
437  //detail::loop_cc(*res2, res, Convert());
438  {
439  using namespace til::expr;
440  for (std::size_t i = 0; i < size(res); ++i)
441  {
442  detail::loop_xx(castTo(*_1, *_2), (*res2)[i], res[i]);
443  }
444  //detail::loop_xx(castTo(*_1, *_2), *res2, res);
445  }
446  //loop(res, *res2, Convert());
447  //convert(res, *res2);
448  //convert<std::vector<std::set<std::size_t> >, std::vector<std::vector<std::size_t> > >(res, *res2);
449  return res2;
450  }
451 
452  //---------------------------------------------------------------------------
453 
454  template < typename TVertexCollection, typename TFaceIndexCollection >
455  inline void getNeighborIndices
456  (
457  const TVertexCollection & vertices,
458  const TFaceIndexCollection & faces,
459  std::vector<std::vector<std::size_t> > & neigh
460  )
461  {
462  typedef typename TFaceIndexCollection::value_type FaceIndices;
463  typedef std::size_t VertexIndex;
464  // Allocate the result -- it should have as many elements as
465  // the number of vertices of the mesh.
466  std::vector<std::set<VertexIndex> > res(vertices.size());
467  // for all faces
468  for (typename TFaceIndexCollection::const_iterator iFic = faces.begin(); iFic != faces.end(); ++iFic)
469  {
470  // for all couple of points on the face
471  typename FaceIndices::const_iterator iFi1 = iFic->begin();
472  typename FaceIndices::const_iterator iFi2 = iFi1+1;
473  for (;iFi2 != iFic->end(); ++iFi1, ++iFi2)
474  {
475  res[*iFi2].insert(*iFi1);
476  res[*iFi1].insert(*iFi2);
477  }
478  // we use iFi1 that should now points to the last element.
479  // do not use container.end() instead! This points nowhere.
480  res[*(iFic->begin())].insert(*iFi1);
481  res[*iFi1].insert(*(iFic->begin()));
482  }
483  //convert the result into a vector
484  neigh.resize(res.size());
485  {
486  using namespace til::expr;
487  for (std::size_t i = 0; i < size(res); ++i)
488  {
489  neigh[i].resize(res[i].size());
490  detail::loop_xx(castTo(*_1, *_2), neigh[i], res[i]);
491  }
492  }
493  }
494 
495  //---------------------------------------------------------------------------
496 
497  template < typename TParam >
500  {
503  }
504 
505 
506  /*
507  MeshAttributes<Mesh1>::AddNeighborIndices
508  addNeighborsToMesh(const Mesh1 & mesh);
509  */
510 
511  namespace detail
512  {
516  template < typename TMesh, typename TContainer, typename TFunctor >
517  inline void
518  for_each_neighbors_N(const TMesh & mesh, TContainer & c, TFunctor f)
519  {
520  // Allocate output with the same structure of neighbor indices of mesh
521  // if the main container has the wrong size.
522  /*
523  if (size(c) != size(getNeighborIndices(mesh)))
524  {
525  allocate_sameSize(getNeighborIndices(mesh), c);
526  }
527  */
528  assert(size(c) == size(getNeighborIndices(mesh)));
529 
530  // for all vertices
533  typename TContainer::iterator iC = c.begin();
534  for (; iNic != getNeighborIndices(mesh).end(); ++iNic, ++iC, ++iV)
535  {
536  // for all neighbors of current vertex
537  typename MeshTraits<TMesh>::NeighborIndex::const_iterator iNi = iNic->begin();
538  typename TContainer::value_type::iterator iL = iC->begin();
539  for (; iNi != iNic->end(); ++iNi, ++iL)
540  {
541  f(*iV, getVertexNeighbor(mesh, *iNi), *iL);
542  }
543  }
544  }
545 
549  template < typename TMesh, typename TContainer, typename TFunctor >
550  inline void
551  for_each_neighbors_V(const TMesh & mesh, TContainer & c, TFunctor f)
552  {
553  /*
554  // Allocate output with the same structure of neighbor indices of mesh
555  // if the main container has the wrong size.
556  if (size(c) != size(getNeighborIndices(mesh)))
557  {
558  allocate_sameSize(getNeighborIndices(mesh), c);
559  }
560  */
561  assert(size(c) == size(getNeighborIndices(mesh)));
562 
563  // for all vertices
566  typename TContainer::iterator iC = c.begin();
567  for (; iNic != getNeighborIndices(mesh).end(); ++iNic, ++iC, ++iV)
568  {
569  // for all neighbors of current vertex
570  typename MeshTraits<TMesh>::NeighborIndex::const_iterator iNi = iNic->begin();
571  for (; iNi != iNic->end(); ++iNi)
572  {
573  f(*iV, getVertexNeighbor(mesh, *iNi), *iC);
574  }
575  }
576  }
577  }
578 
579  //---------------------------------------------------------------------------
580 
581  template < typename TMesh, typename TContainer, typename TFunctor >
582  inline typename boost::enable_if_c<
583  is_container<typename TContainer::value_type>::value
584  >::type
585  for_each_neighbors(const TMesh & mesh, TContainer & c1, TFunctor f)
586  {
587  detail::for_each_neighbors_N(mesh, c1, f);
588  }
589 
590  //---------------------------------------------------------------------------
591 
592  template < typename TMesh, typename TContainer, typename TFunctor >
593  inline typename boost::enable_if_c<
594  !is_container<typename TContainer::value_type>::value
595  >::type
596  for_each_neighbors(const TMesh & mesh, TContainer & c1, TFunctor f)
597  {
598  detail::for_each_neighbors_V(mesh, c1, f);
599  }
600 
601  //---------------------------------------------------------------------------
602 
603 
604  namespace detail
605  {
611  template < typename TMesh, typename TContainer1, typename TContainer2, typename TFunctor >
612  inline void
613  for_each_neighbors_NN(const TMesh & mesh, TContainer1 & c1, TContainer2 & c2, TFunctor f)
614  {
615  /*
616  // Allocate output with the same structure of neighbor indices of mesh
617  // if the main container has the wrong size.
618  if (size(c1) != size(getNeighborIndices(mesh)))
619  {
620  allocate_sameSize(getNeighborIndices(mesh), c1);
621  }
622  if (size(c2) != size(getNeighborIndices(mesh)))
623  {
624  allocate_sameSize(getNeighborIndices(mesh), c2);
625  }
626  */
627  assert(size(c1) == size(c2));
628  assert(size(c1) == size(getNeighborIndices(mesh)));
629 
630 
631  // for all vertices
634  typename TContainer1::iterator iC1 = c1.begin();
635  typename TContainer2::iterator iC2 = c2.begin();
636  for (; iNic != getNeighborIndices(mesh).end(); ++iNic, ++iC1, ++iC2, ++iV)
637  {
638  // for all neighbors of current vertex
639  typename MeshTraits<TMesh>::NeighborIndex::const_iterator iNi = iNic->begin();
640  typename TContainer1::value_type::iterator iL1 = iC1->begin();
641  typename TContainer2::value_type::iterator iL2 = iC2->begin();
642  for (; iNi != iNic->end(); ++iNi, ++iL1, ++iL2)
643  {
644  f(*iV, getVertexNeighbor(mesh, *iNi), *iL1, *iL2);
645  }
646  }
647  }
648 
653  template < typename TMesh, typename TContainer1, typename TContainer2, typename TFunctor >
654  inline void
655  for_each_neighbors_NV(const TMesh & mesh, TContainer1 & c1, TContainer2 & c2, TFunctor f)
656  {
657  // Allocate output with the same structure of neighbor indices of mesh
658  // if the main container has the wrong size.
659  /*
660  if (size(c1) != size(getNeighborIndices(mesh)))
661  {
662  allocate_sameSize(getNeighborIndices(mesh), c1);
663  }
664  if (size(c2) != size(getVertices(mesh)))
665  {
666  allocate_sameSize(getVertices(mesh), c2);
667  }
668  */
669  assert(size(c1) == size(c2));
670  assert(size(c1) == size(getNeighborIndices(mesh)));
671 
672  // for all vertices
675  typename stditerator<TContainer1>::type iC1 = c1.begin();
676  typename stditerator<TContainer2>::type iC2 = c2.begin();
677  for (; iNic != getNeighborIndices(mesh).end(); ++iNic, ++iC1, ++iC2, ++iV)
678  {
679  // for all neighbors of current vertex
680  typename MeshTraits<TMesh>::NeighborIndex::const_iterator iNi = iNic->begin();
682  //typename stditerator<typename TContainer1::value_type>::type iL1 = iC1->begin();
683  for (; iNi != iNic->end(); ++iNi, ++iL1)
684  {
685  f(*iV, getVertexNeighbor(mesh, *iNi), *iL1, *iC2);
686  }
687  /*
688  if (TFunctor::PerVertex) {
689  f.perVertex(v[*iNi], *iC2, size(*iNic));
690  }*/
691  }
692  }
693  }
694 
695  //---------------------------------------------------------------------------
696 
702  template < typename TMesh, typename TContainer1, typename TContainer2, typename TFunctor >
703  inline typename boost::enable_if_c<
704  is_container<typename TContainer1::value_type>::value &&
705  is_container<typename TContainer2::value_type>::value
706  >::type
707  for_each_neighbors(const TMesh & mesh, TContainer1 & c1, TContainer2 & c2, TFunctor f)
708  {
709  detail::for_each_neighbors_NN(mesh, c1, c2, f);
710  }
711 
716  template < typename TMesh, typename TContainer1, typename TContainer2, typename TFunctor >
717  inline typename boost::enable_if_c<
718  is_container<typename TContainer1::value_type>::value &&
719  !is_container<typename TContainer2::value_type>::value
720  >::type
721  for_each_neighbors(const TMesh & mesh, TContainer1 & c1, TContainer2 & c2, TFunctor f)
722  {
723  detail::for_each_neighbors_NV(mesh, c1, c2, f);
724  }
725 
726  //---------------------------------------------------------------------------
727 
736  template < typename TPrecision, typename TMesh >
737  inline typename boost::enable_if_c<
738  // Mesh must have neighbor indices
740  >::type
742  (
743  const TMesh &mesh,
744  std::vector<std::vector<TPrecision> > & lengths
745  )
746  {
747  if (size(lengths) != size(getNeighborIndices(mesh)))
748  {
749  allocate_sameSize(getNeighborIndices(mesh), lengths);
750  }
751  for_each_neighbors(mesh, lengths, functor::Diff());
752  }
753 
754  //---------------------------------------------------------------------------
755 
756  template < typename TVertexXsr, typename TCircularNeighborXsr, typename prec_type >
758  {
759  public: // typedefs
760 
761  //typedef typename precision<typename TVertexCollection::value_type>::type prec_type;
762  //typedef typename TCircularNeighborIndices::value_type Neighborhood;
763  //typedef typename TVertexCollection::value_type Vertex;
764 
765  typedef typename TCircularNeighborXsr::value_type Neighborhood;
766  typedef typename TCircularNeighborXsr::reference NeighborhoodRef;
767  //typedef typename TVertexXsr::value_type Vertex;
768  typedef typename TVertexXsr::reference VertexRef;
769  typedef typename TVertexXsr::index_type index_type;
770 
771  public: // constructors
772 
773  Mesh_curvature2(TVertexXsr vertexXsr, TCircularNeighborXsr neighXsr)
774  : m_vertexXsr(vertexXsr)
775  , m_neighXsr(neighXsr)
776  {}
777 
778  public: // set & get
779 
781  prec_type gaussianCurvature() const { return m_orientedGaussianCurvature; }
783  prec_type meanCurvature() const { return m_orientedMeanCurvature; }
786  std::pair<prec_type, prec_type> principalCurvatures() const { return m_principalCurvatures; }
788  prec_type voronoiArea() const { return m_voronoiArea; }
790  const numeric_array<prec_type, 3> & normal() const { return m_normal; }
791 
793  prec_type unorientedGaussianCurvature() const { return m_gaussianCurvature; }
795  prec_type unorientedMeanCurvature() const { return m_meanCurvature; }
796 
797 
798  public: // functions
799 
802  void process(index_type i)
803  {
804  NeighborhoodRef nh = m_neighXsr(i);
805  // Curvature cannot be computed if vertex has not at least three neighbors
806  assert(size(nh) >= 2);
807  VertexRef p = m_vertexXsr(i);
808 
809  // initializations
810  m_voronoiArea = 0;
811  // mean curvature vector
812  //Vector<prec_type, 3> m;
813  std::fill(m_normal.begin(), m_normal.end(), prec_type(0));
814  // Gaussian curvature
815  m_gaussianCurvature = 0;
816 
817  numeric_array<prec_type, 3> e1, e2, e3;
818  //numeric_array<prec_type, 3> e1, e2, e3;
819  // Loop through all neighboring triangles
820  typename Neighborhood::const_iterator iNh1 = nh.begin();
821  const_cyclic_iterator<Neighborhood> iNh2 (nh, iNh1+1);
822  for (; iNh1 != nh.end(); ++iNh1, ++iNh2)
823  {
824  // compute the edges, their squared length and their length
825  e1 = p - m_vertexXsr(*iNh1);
826  prec_type n21 = norm2<prec_type>(e1);
827  prec_type n1 = std::sqrt(n21);
828 
829  e2 = p - m_vertexXsr(*iNh2);
830  prec_type n22 = norm2<prec_type>(e2);
831  prec_type n2 = std::sqrt(n22);
832 
833  e3 = m_vertexXsr(*iNh2) - m_vertexXsr(*iNh1);
834  prec_type n23 = norm2<prec_type>(e3);
835  //prec_type n3 = std::sqrt(n23);
836  //e3 *= 1/norm<prec_type>(e3);
837 
838  prec_type d1 = dot(e1, e3);
839  prec_type d2 = dot(e2, e3);
840 
841  prec_type biarea = std::sqrt(n21*n23 - d1*d1);
842 
843  // Subtracting the angle between the two side edges to the gaussian curvature
844  m_gaussianCurvature -= std::acos( max(prec_type(-1), min(prec_type(1), dot(e1, e2) / (n1*n2))));
845 
846  //cot1 = d1 / norm<prec_type>(e1 - d1 * e3);
847  //cot2 = -d2 / norm<prec_type>(e2 - d2 * e3);
848 
849  //cot1 = d1 / dist<prec_type>(e1, d1 * e3);
850  //cot2 = -d2 / dist<prec_type>(e2, d2 * e3);
851 
852  // NB: aren't the denominator all proportional to area? In that case
853  // needed only once?
854  /*
855  prec_type cot1 = d1 / biarea;
856  prec_type cot2 = -d2 / biarea;
857  m += cot1 * e2 + cot2 * e1;
858  */
859  m_normal += (d1 * e2 - d2 * e1) * (prec_type(1)/biarea);
860 
861  if (dot(e1, e2) <= 0)
862  {
863  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
864  //area += heronsFormula(n1, n2, n3) / 2;
865  m_voronoiArea += biarea / 4;
866  }
867  else
868  {
869  if (d1 <= 0 || d2 >= 0)
870  {
871  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
872  //area += heronsFormula(n1, n2, n3) / 4;
873  m_voronoiArea += biarea / 8;
874  }
875  else
876  {
877  m_voronoiArea += 1.0/8.0 * (n22 * d1 - n21 * d2 ) / biarea;
878  }
879  }
880  }
881 
882  // finishing computation of gaussian curvature
883  m_gaussianCurvature += 2*M_PI;
884  m_gaussianCurvature /= m_voronoiArea;
885  // finishing computation of mean curvature
886  // NB: [Meyer et al.] the mean curvature is half the norm of K, hence the factor 4.
887  m_meanCurvature = norm<prec_type>(m_normal) / (4*m_voronoiArea);
888  // computes the principal curvatures from the unsigned mean and Gaussian curvatures
889  prec_type delta = std::sqrt(max(prec_type(0), square(m_meanCurvature) - m_gaussianCurvature));
890  m_principalCurvatures.first = m_meanCurvature + delta;
891  m_principalCurvatures.second = m_meanCurvature - delta;
892 
893  // takes into account the sign
894  // TODO: this test is actually not always accurate -- try to find a more robust criterion.
895  if (dot(m_normal, cross(e1, e2)) < 0)
896  {
897  m_orientedMeanCurvature = -m_meanCurvature;
898  m_orientedGaussianCurvature = -m_gaussianCurvature;
899  m_principalCurvatures.first = -m_principalCurvatures.first;
900  m_principalCurvatures.second = -m_principalCurvatures.second;
901  m_normal *= -1/norm(m_normal);
902  }
903  else
904  {
905  m_orientedMeanCurvature = m_meanCurvature;
906  m_orientedGaussianCurvature = m_gaussianCurvature;
907  m_normal *= 1/norm(m_normal);
908  }
909  }
910 
911  private: // data, input
912 
913  TVertexXsr m_vertexXsr;
914  TCircularNeighborXsr m_neighXsr;
915 
916  private: // data, output
917 
918  prec_type m_gaussianCurvature;
919  prec_type m_meanCurvature;
920  prec_type m_orientedGaussianCurvature;
921  prec_type m_orientedMeanCurvature;
922  prec_type m_voronoiArea;
923  std::pair<prec_type, prec_type> m_principalCurvatures;
925  };
926 
927  //---------------------------------------------------------------------------
928 
929  template < typename TVertexCollection, typename TCircularNeighborIndices, typename prec_type >
931  {
932  public: // typedefs
933 
934  //typedef typename precision<typename TVertexCollection::value_type>::type prec_type;
935  typedef typename TCircularNeighborIndices::value_type Neighborhood;
936  typedef typename TVertexCollection::value_type Vertex;
937 
938  public: // constructors
939 
940  Mesh_curvature(const TVertexCollection & vertices, const TCircularNeighborIndices & neighs)
941  : m_vertices(vertices), m_neighs(neighs) {}
942 
943  public: // set & get
944 
946  prec_type gaussianCurvature() const { return m_orientedGaussianCurvature; }
948  prec_type meanCurvature() const { return m_orientedMeanCurvature; }
951  std::pair<prec_type, prec_type> principalCurvatures() const { return m_principalCurvatures; }
953  prec_type voronoiArea() const { return m_voronoiArea; }
955  const numeric_array<prec_type, 3> & normal() const { return m_normal; }
956 
958  prec_type unorientedGaussianCurvature() const { return m_gaussianCurvature; }
960  prec_type unorientedMeanCurvature() const { return m_meanCurvature; }
961 
962 
963  public: // functions
964 
967  void process(std::size_t i)
968  {
969  Neighborhood nh = m_neighs[i];
970  // Curvature cannot be computed if vertex has not at least three neighbors
971  assert(size(nh) >= 2);
972  const Vertex & p = m_vertices[i];
973 
974  // initializations
975  m_voronoiArea = 0;
976  // mean curvature vector
977  //Vector<prec_type, 3> m;
978  std::fill(m_normal.begin(), m_normal.end(), prec_type(0));
979  // Gaussian curvature
980  m_gaussianCurvature = 0;
981 
982  numeric_array<prec_type, 3> e1, e2, e3;
983  //numeric_array<prec_type, 3> e1, e2, e3;
984  // Loop through all neighboring triangles
985  typename Neighborhood::const_iterator iNh1 = nh.begin();
986  const_cyclic_iterator<Neighborhood> iNh2 (nh, iNh1+1);
987  for (; iNh1 != nh.end(); ++iNh1, ++iNh2)
988  {
989  // compute the edges, their squared length and their length
990  e1 = p - m_vertices[*iNh1];
991  prec_type n21 = norm2<prec_type>(e1);
992  prec_type n1 = std::sqrt(n21);
993 
994  e2 = p - m_vertices[*iNh2];
995  prec_type n22 = norm2<prec_type>(e2);
996  prec_type n2 = std::sqrt(n22);
997 
998  e3 = m_vertices[*iNh2] - m_vertices[*iNh1];
999  prec_type n23 = norm2<prec_type>(e3);
1000  //prec_type n3 = std::sqrt(n23);
1001  //e3 *= 1/norm<prec_type>(e3);
1002 
1003  prec_type d1 = dot(e1, e3);
1004  prec_type d2 = dot(e2, e3);
1005 
1006  prec_type biarea = std::sqrt(n21*n23 - d1*d1);
1007 
1008  // Subtracting the angle between the two side edges to the gaussian curvature
1009  m_gaussianCurvature -= std::acos( max(prec_type(-1), min(prec_type(1), dot(e1, e2) / (n1*n2))));
1010 
1011  //cot1 = d1 / norm<prec_type>(e1 - d1 * e3);
1012  //cot2 = -d2 / norm<prec_type>(e2 - d2 * e3);
1013 
1014  //cot1 = d1 / dist<prec_type>(e1, d1 * e3);
1015  //cot2 = -d2 / dist<prec_type>(e2, d2 * e3);
1016 
1017  // NB: aren't the denominator all proportional to area? In that case
1018  // needed only once?
1019  /*
1020  prec_type cot1 = d1 / biarea;
1021  prec_type cot2 = -d2 / biarea;
1022  m += cot1 * e2 + cot2 * e1;
1023  */
1024  m_normal += (d1 * e2 - d2 * e1) * (prec_type(1)/biarea);
1025 
1026  if (dot(e1, e2) <= 0)
1027  {
1028  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
1029  //area += heronsFormula(n1, n2, n3) / 2;
1030  m_voronoiArea += biarea / 4;
1031  }
1032  else
1033  {
1034  if (d1 <= 0 || d2 >= 0)
1035  {
1036  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
1037  //area += heronsFormula(n1, n2, n3) / 4;
1038  m_voronoiArea += biarea / 8;
1039  }
1040  else
1041  {
1042  m_voronoiArea += 1.0/8.0 * (n22 * d1 - n21 * d2 ) / biarea;
1043  }
1044  }
1045  }
1046 
1047  // finishing computation of gaussian curvature
1048  m_gaussianCurvature += 2*M_PI;
1049  m_gaussianCurvature /= m_voronoiArea;
1050  // finishing computation of mean curvature
1051  // NB: [Meyer et al.] the mean curvature is half the norm of K, hence the factor 4.
1052  m_meanCurvature = norm<prec_type>(m_normal) / (4*m_voronoiArea);
1053  // computes the principal curvatures from the unsigned mean and Gaussian curvatures
1054  prec_type delta = std::sqrt(max(prec_type(0), square(m_meanCurvature) - m_gaussianCurvature));
1055  m_principalCurvatures.first = m_meanCurvature + delta;
1056  m_principalCurvatures.second = m_meanCurvature - delta;
1057 
1058  // takes into account the sign
1059  // TODO: this test is actually not always accurate -- try to find a more robust criterion.
1060  if (dot(m_normal, cross(e1, e2)) < 0)
1061  {
1062  m_orientedMeanCurvature = -m_meanCurvature;
1063  m_orientedGaussianCurvature = -m_gaussianCurvature;
1064  m_principalCurvatures.first = -m_principalCurvatures.first;
1065  m_principalCurvatures.second = -m_principalCurvatures.second;
1066  m_normal *= -1/norm(m_normal);
1067  }
1068  else
1069  {
1070  m_orientedMeanCurvature = m_meanCurvature;
1071  m_orientedGaussianCurvature = m_gaussianCurvature;
1072  m_normal *= 1/norm(m_normal);
1073  }
1074 
1075  }
1076 
1077  private: // data, input
1078 
1079  const TVertexCollection & m_vertices;
1080  const TCircularNeighborIndices & m_neighs;
1081 
1082  private: // data, output
1083 
1084  prec_type m_gaussianCurvature;
1085  prec_type m_meanCurvature;
1086  prec_type m_orientedGaussianCurvature;
1087  prec_type m_orientedMeanCurvature;
1088  prec_type m_voronoiArea;
1089  std::pair<prec_type, prec_type> m_principalCurvatures;
1090  numeric_array<prec_type, 3> m_normal;
1091  };
1092 
1093  //---------------------------------------------------------------------------
1094 
1095  namespace policy
1096  {
1097 
1098  //-------------------------------------------------------------------------
1099 
1103  template < typename TCollection >
1105  {
1106  public: // typedefs
1107  typedef std::size_t index_type;
1108  typedef typename TCollection::value_type value_type;
1109 
1110  public: // constructors
1111  // NB: Actually, it can be quite comfortable to have it non explicit. We can pass collections rather
1112  // than constructing explicitely an accessor.
1113  IntegerIndexing(TCollection & data) : m_data(data) {}
1114 
1115  public: // static accessors
1116  typename TCollection::reference operator()(index_type i)
1117  { return m_data[i]; }
1118  typename TCollection::const_reference operator()(index_type i) const
1119  { return m_data[i]; }
1120 
1121  private: // data
1122  TCollection & m_data;
1123  };
1124 
1125  /*
1126  template < typename TReference, typename TValueType = naked_type<TReference>::type >
1127  struct GetVertexField
1128  {
1129  typedef TValueType value_type;
1130  typedef TReference reference;
1131  template < typename TIterator >
1132  static TResult get(TIterator i) { return i->vertex(); }
1133  };
1134  */
1135 
1136  //-------------------------------------------------------------------------
1137 
1139  template < typename TIterator > //, typename Getter >
1141  {
1142  public: // typedefs
1143  typedef typename TIterator::value_type value_type;
1144  typedef TIterator index_type;
1145  public: // static accessors
1146  value_type & operator()(index_type i) const
1147  { return *i; }
1148  };
1149 
1150  //-------------------------------------------------------------------------
1151 
1152  template < typename TIterator > //, typename Getter >
1153  //struct IteratorIndexing
1155  {
1156  public: // typedefs
1157  typedef typename TIterator::value_type::Vertex value_type;
1158  typedef typename TIterator::value_type::VertexIndex index_type;
1159  public: // static accessors
1160  // NB: it is not stupid to fix the reference at value_type, because the index_type, hence the iterator,
1161  // is also fixed inside the meshvertexnode class.
1162  value_type & operator()(index_type i) const
1163  { return i->pos(); }
1164  //{ return Getter::get(i); }
1165  };
1166 
1167  //-------------------------------------------------------------------------
1168 
1169  template < typename TIterator >
1171  {
1172  public: // typedefs
1173  typedef typename TIterator::value_type::VertexIndexCollection value_type;
1174  typedef typename TIterator::value_type::VertexIndex index_type;
1175  public: // static accessors
1176  value_type & operator()(index_type i) const
1177  { return i->neighbors(); }
1178  };
1179 
1180  //-------------------------------------------------------------------------
1181 
1182  } // namespace policy
1183 
1184  //---------------------------------------------------------------------------
1185 
1186  template < typename TVertexAccessPolicy, typename TCircularNeighborhoodAccessPolicy, typename prec_type >
1188  {
1189  public: // typedefs
1190 
1191  //typedef typename precision<typename TVertexCollection::value_type>::type prec_type;
1192  typedef typename TCircularNeighborhoodAccessPolicy::value_type Neighborhood;
1193  //typedef typename TVertexCollection::value_type Vertex;
1194  typedef typename TVertexAccessPolicy::value_type Vertex;
1195  typedef typename TVertexAccessPolicy::index_type VertexIndex;
1196  //typedef typename TVertexAccessPolicy::collection_type VertexCollection;
1197 
1198  public: // constructors
1199 
1200  MeshCurvature2(TVertexAccessPolicy vertexAccess, TCircularNeighborhoodAccessPolicy neighborAccess)
1201  : m_vertexAccess(vertexAccess), m_neighborAccess(neighborAccess) {}
1202 
1203  public: // set & get
1204 
1206  prec_type gaussianCurvature() const { return m_orientedGaussianCurvature; }
1208  prec_type meanCurvature() const { return m_orientedMeanCurvature; }
1211  std::pair<prec_type, prec_type> principalCurvatures() const { return m_principalCurvatures; }
1213  prec_type voronoiArea() const { return m_voronoiArea; }
1215  const numeric_array<prec_type, 3> & normal() const { return m_normal; }
1216 
1218  prec_type unorientedGaussianCurvature() const { return m_gaussianCurvature; }
1220  prec_type unorientedMeanCurvature() const { return m_meanCurvature; }
1221 
1222 
1223  public: // functions
1224 
1227  void process(VertexIndex i)
1228  {
1229  const Neighborhood & nh = m_neighborAccess(i);
1230  // Curvature cannot be computed if vertex has not at least three neighbors
1231  assert(size(nh) >= 2);
1232  const Vertex & p = m_vertexAccess(i);
1233 
1234  // initializations
1235  m_voronoiArea = 0;
1236  // mean curvature vector
1238  // Gaussian curvature
1239  m_gaussianCurvature = 0;
1240 
1241  numeric_array<prec_type, 3> e1, e2, e3;
1242  // Loop through all neighboring triangles
1243  typename Neighborhood::const_iterator iNh1 = nh.begin();
1244  const_cyclic_iterator<Neighborhood> iNh2 (nh, nh.begin()); ++iNh2;
1245  for (; iNh1 != nh.end(); ++iNh1, ++iNh2)
1246  {
1247  // compute the edges, their squared length and their length
1248  e1 = p - m_vertexAccess(*iNh1);
1249  prec_type n21 = norm2<prec_type>(e1);
1250  prec_type n1 = std::sqrt(n21);
1251 
1252  e2 = p - m_vertexAccess(*iNh2);
1253  prec_type n22 = norm2<prec_type>(e2);
1254  prec_type n2 = std::sqrt(n22);
1255 
1256  e3 = m_vertexAccess(*iNh2) - m_vertexAccess(*iNh1);
1257  prec_type n23 = norm2<prec_type>(e3);
1258  //prec_type n3 = std::sqrt(n23);
1259  //e3 *= 1/norm<prec_type>(e3);
1260 
1261  prec_type d1 = dot(e1, e3);
1262  prec_type d2 = dot(e2, e3);
1263 
1264  prec_type biarea = std::sqrt(n21*n23 - d1*d1);
1265 
1266  // Subtracting the angle between the two side edges to the gaussian curvature
1267  m_gaussianCurvature -= std::acos( max(prec_type(-1), min(prec_type(1), dot(e1, e2) / (n1*n2))));
1268 
1269  //cot1 = d1 / norm<prec_type>(e1 - d1 * e3);
1270  //cot2 = -d2 / norm<prec_type>(e2 - d2 * e3);
1271 
1272  //cot1 = d1 / dist<prec_type>(e1, d1 * e3);
1273  //cot2 = -d2 / dist<prec_type>(e2, d2 * e3);
1274 
1275  // NB: aren't the denominator all proportional to area? In that case
1276  // needed only once?
1277  /*
1278  prec_type cot1 = d1 / biarea;
1279  prec_type cot2 = -d2 / biarea;
1280  m += cot1 * e2 + cot2 * e1;
1281  */
1282  m_normal += (d1 * e2 - d2 * e1) * (prec_type(1)/biarea);
1283 
1284  if (dot(e1, e2) <= 0)
1285  {
1286  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
1287  //area += heronsFormula(n1, n2, n3) / 2;
1288  m_voronoiArea += biarea / 4;
1289  }
1290  else
1291  {
1292  if (d1 <= 0 || d2 >= 0)
1293  {
1294  //n3 = dist<prec_type>(m_vertices[*iNh1], m_vertices[*iNh2]);
1295  //area += heronsFormula(n1, n2, n3) / 4;
1296  m_voronoiArea += biarea / 8;
1297  }
1298  else
1299  {
1300  m_voronoiArea += 1.0/8.0 * (n22 * d1 - n21 * d2 ) / biarea;
1301  }
1302  }
1303  }
1304 
1305  // finishing computation of gaussian curvature
1306  m_gaussianCurvature += 2*M_PI;
1307  m_gaussianCurvature /= m_voronoiArea;
1308  // finishing computation of mean curvature
1309  // NB: [Meyer et al.] the mean curvature is half the norm of K, hence the factor 4.
1310  m_meanCurvature = norm<prec_type>(m_normal) / (4*m_voronoiArea);
1311  // computes the principal curvatures from the unsigned mean and Gaussian curvatures
1312  prec_type delta = std::sqrt(max(prec_type(0), square(m_meanCurvature) - m_gaussianCurvature));
1313  m_principalCurvatures.first = m_meanCurvature + delta;
1314  m_principalCurvatures.second = m_meanCurvature - delta;
1315 
1316  // takes into account the sign
1317  if (dot(m_normal, cross(e1, e2)) < 0)
1318  {
1319  m_orientedMeanCurvature = -m_meanCurvature;
1320  m_orientedGaussianCurvature = -m_gaussianCurvature;
1321  m_principalCurvatures.first = -m_principalCurvatures.first;
1322  m_principalCurvatures.second = -m_principalCurvatures.second;
1323  m_normal *= -1/norm(m_normal);
1324  }
1325  else
1326  {
1327  m_orientedMeanCurvature = m_meanCurvature;
1328  m_orientedGaussianCurvature = m_gaussianCurvature;
1329  m_normal *= 1/norm(m_normal);
1330  }
1331  }
1332 
1333  private: // data, input
1334 
1335  TVertexAccessPolicy m_vertexAccess;
1336  TCircularNeighborhoodAccessPolicy m_neighborAccess;
1337 
1338  private: // data, output
1339 
1340  prec_type m_gaussianCurvature;
1341  prec_type m_meanCurvature;
1342  prec_type m_orientedGaussianCurvature;
1343  prec_type m_orientedMeanCurvature;
1344  prec_type m_voronoiArea;
1345  std::pair<prec_type, prec_type> m_principalCurvatures;
1346  numeric_array<prec_type, 3> m_normal;
1347  };
1348 
1349 //-----------------------------------------------------------------------------
1350 
1351  //----------------------//
1352  // GonzalezClustering //
1353 //----------------------//
1354 
1356 template < typename TData, typename TPrec, typename TDist = SquaredEuclideanDist<TPrec> >
1358 {
1359 private: // typedefs
1360  typedef typename TData::const_iterator iterator;
1361 
1362 public: // typedefs
1363  typedef TPrec prec_type;
1364  typedef typename TData::value_type value_type;
1365 
1366 public: // constructors
1367 
1368  GonzalezClustering(const TData & data)
1369  : m_begin(data.begin())
1370  , m_end(data.end())
1371  , m_dist()
1372  , m_quant(new std::vector<iterator>(1, data.begin()))
1373  , m_labels(new std::vector<std::size_t>(data.size(), 0))
1374  {}
1375 
1376 public: // set & get
1377 
1380 
1382 
1383 public: // functions, main
1384 
1386  void clusterize_maxDiam(prec_type maxDiam)
1387  {
1388  unsigned int niter = 0;
1389  for (;;)
1390  {
1391  ++niter;
1392  //std::cout << "iter " << niter << std::endl;
1393 
1394  this->computeClusters();
1395  this->moveClusterSeeds();
1396 
1397  // Stop criterion
1398  std::size_t count = 0;
1399  bool flag = true;
1400  {
1401  for (iterator i = m_begin; i != m_end; ++i, ++count)
1402  {
1403  std::size_t label = (*m_labels)[count];
1404  if (m_dist(*i, *(*m_quant)[label]) > maxDiam)
1405  {
1406  flag = false;
1407  break;
1408  }
1409  }
1410  }
1411  if (flag) break;
1412 
1413  this->addNewClusterSeed();
1414 
1415  if (m_quant->size() != (niter+1))
1416  {
1417  std::cerr << "Warning: early termination of clustering" << std::endl;
1418  break;
1419  }
1420  }
1421  }
1422 
1423 public: // functions, detail
1424 
1427  {
1428  // for all points
1429  std::size_t count = 0;
1430  for (iterator i = m_begin; i != m_end; ++i, ++count)
1431  {
1432  // look for the quantized vector closest to point
1433  prec_type min_dist = std::numeric_limits<prec_type>::max();
1434  for (std::size_t j = 0; j < m_quant->size(); ++j)
1435  {
1436  prec_type tmp = m_dist(*i, *(*m_quant)[j]);
1437  if (tmp < min_dist)
1438  {
1439  min_dist = tmp;
1440  (*m_labels)[count] = j;
1441  }
1442  }
1443  }
1444  }
1445 
1448  {
1449  std::vector<value_type> centers(m_quant->size(), value_type());
1450  {
1451  // for all points
1452  std::vector<unsigned int> counts(m_quant->size(), 0);
1453  std::size_t count = 0;
1454  for (iterator i = m_begin; i != m_end; ++i, ++count)
1455  {
1456  std::size_t label = (*m_labels)[count];
1457  // accumulate center points
1458  centers[label] += *i;
1459  ++counts[label];
1460  }
1461  // finish computation of centers
1462  for (std::size_t i = 0; i < centers.size(); ++i)
1463  {
1464  assert(counts[i] > 0);
1465  centers[i] *= prec_type(1)/counts[i];
1466  //(*m_quant)[i] = centers[i] / counts[i];
1467  }
1468  }
1469  std::vector<prec_type> dists(m_quant->size(), std::numeric_limits<prec_type>::max());
1470  // for all points
1471  std::size_t count = 0;
1472  for (iterator i = m_begin; i != m_end; ++i, ++count)
1473  {
1474  std::size_t label = (*m_labels)[count];
1475  // set point closest to its cluster centroid as cluster quantization
1476  prec_type tmp = m_dist(*i, centers[label]);
1477  if (tmp < dists[label])
1478  {
1479  dists[label] = tmp;
1480  (*m_quant)[label] = i;
1481  }
1482  }
1483  }
1484 
1487  {
1488  prec_type max_dist = 0.0;
1489  iterator newSeed = m_begin;
1490  // for all points
1491  std::size_t count = 0;
1492  for (iterator i = m_begin; i != m_end; ++i, ++count)
1493  {
1494  std::size_t label = (*m_labels)[count];
1495  // look for the point with largest distance to its cluster quantized vector
1496  prec_type tmp = m_dist(*i, *(*m_quant)[label]);
1497  if (tmp > max_dist)
1498  {
1499  max_dist = tmp;
1500  newSeed = i;
1501  }
1502  }
1503  // Check that point can be added
1504  if (max_dist == 0.0)
1505  {
1506  std::cerr << "Seed cannot be added" << std::endl;
1507  return;
1508  }
1509 #ifndef NDEBUG
1510  // Check that added vector quant is not already there
1511  {
1512  typename std::vector<iterator>::iterator i = std::find(m_quant->begin(), m_quant->end(), newSeed);
1513  assert( i == m_quant->end() );
1514  }
1515 #endif
1516  // add point
1517  m_quant->push_back(newSeed);
1518  }
1519 
1520 
1521 private: //data, input
1522 
1523  iterator m_begin;
1524  iterator m_end;
1525  TDist m_dist;
1526 
1527 private: // data, output
1528 
1530 
1531 private: // data, internals
1532 
1533  //std::vector<prec_type> m_dist;
1535 };
1536 
1537 
1538 
1540 template < typename TCollection, typename TPrec >
1542 gonzalez_clustering(const TCollection & data, TPrec maxDiam)
1543 {
1545  gc.clusterize_maxDiam(maxDiam);
1546  return gc.quantization();
1547 }
1548 
1549 
1550 /*
1551 template < typename TVertexCollection, typename TFaceCollection >
1552 void remove_vertex(typename TVertexCollection::iterator i, const TVertexCollection & v, const TFaceCollection & f)
1553 {
1554  for (std::list<std::list<MeshFaceNode>::iterator>::iterator j = i->faces.begin(); j != i->faces.end(); ++j)
1555  {
1556  // Remove index to this face
1557  for (std::size_t k = 0; k < 3; ++k)
1558  {
1559  if ((*j)->face[k] == i) continue;
1560  std::size_t tmp = til::size((*j)->face[k]->faces);
1561  (*j)->face[k]->faces.remove(*j);
1562  }
1563  // remove face itself
1564  graph_faces.erase(*j);
1565  }
1566  // remove point in neighbor's list
1567  for (std::list<std::list<MeshVertexNode>::iterator>::iterator j = i->neighbors.begin(); j != i->neighbors.end(); ++j)
1568  {
1569  (*j)->neighbors.remove(i);
1570  }
1571  // remove point
1572  i = graph_vertices.erase(i);
1573  //++i;
1574 }
1575 */
1576 
1581  /*
1582  class SimpleNeighborFlattening
1583  {
1584  public: // typedef
1585  typedef std::vector<Point<float,2> > Res;
1586  public: // constructors
1587  SimpleNeighborFlattening() : m_res() {}
1588  public: // set & get
1589  const Res & res() const { return m_res; }
1590  Res & res() { return m_res; }
1591  public: // operators
1593  void operator()(
1594  const Point<float,3> & point,
1595  const std::vector<std::list<MeshVertexNode>::iterator> & neighbors
1596  )
1597  {
1598  m_angles.clear();
1599  m_norms.clear();
1600  m_angles.reserve(til::size(neighbors));
1601  m_norms.reserve(til::size(neighbors));
1602 
1603  std::vector<std::list<MeshVertexNode>::iterator>::const_iterator n = neighbors.begin();
1604  const_cyclic_iterator<std::vector<std::list<MeshVertexNode>::iterator> > n2(neighbors, ++neighbors.begin());
1605  for (; n != neighbors.end(); ++n, ++n2)
1606  {
1607  m_norms.push_back(norm<double>((*n)->pos-point));
1608  m_angles.push_back(std::acos(dot((*n2)->pos-point, (*n)->pos-point) / (norm<double>((*n2)->pos-point) * norm<double>((*n)->pos-point))));
1609  }
1610  std::partial_sum(m_angles.begin(), m_angles.end(), m_angles.begin());
1611  std::transform(m_angles.begin(), m_angles.end(), m_angles.begin(), std::bind2nd(std::multiplies<double>(), 2*M_PI/angles.back()));
1612 
1613  m_res.clear();
1614  //m_res.resize(til::size(neighbors));
1615  m_res.reserve(til::size(neighbors));
1616  for (std::size_t i = 0; i < size(res); ++i)
1617  {
1618  m_res.push_back(Point<float,2>(std::cos(angles[i]) * norms[i], std::sin(angles[i]) * norms[i]));
1619  }
1620  }
1621  private: // data
1622  Res m_res;
1623  private: // computation variables
1624  std::vector<double> m_angles;
1625  std::vector<double> m_norms;
1626  };
1627 
1628  */
1629 
1630  //---------------------------------------------------------------------------
1631 
1632  template < typename TPrec, typename TVertexIndex, typename TVertexCollection, typename TNeighborhood, typename TVertex >
1633  inline TPrec
1634  dist2_surface(const TVertex & p, TVertexIndex i, const TVertexCollection & vertices, const TNeighborhood & neighc)
1635  {
1636  typedef typename TVertex::value_type prec_type;
1637  prec_type dmin = std::numeric_limits<prec_type>::max();
1639  typename TNeighborhood::const_iterator ineigh = neighc.begin();
1640  const_cyclic_iterator<TNeighborhood> ineigh2(neighc, neighc.begin());
1641  ++ineigh2;
1642  for (; ineigh != neighc.end(); ++ineigh, ++ineigh2)
1643  {
1644  geo::Project::PointOnTriangle3D<typename TVertexCollection::value_type, numeric_array<TPrec, 3> >()(p, vertices[i], vertices[*ineigh], vertices[*ineigh2], tmp);
1645  prec_type d = dist2(p, tmp, prec<prec_type>());
1646  if (d < dmin)
1647  {
1648  dmin = d;
1649  }
1650  }
1651  return dmin;
1652  }
1653 
1654  //---------------------------------------------------------------------------
1655 
1657  template < typename TPrec, typename TVertexIndex, typename TVertexCollection, typename TNeighborhood, typename TVertex >
1659  closest_normal(const TVertex & p, TVertexIndex i, const TVertexCollection & vertices, const TNeighborhood & neighc)
1660  {
1661  typedef typename TVertex::value_type prec_type;
1662  prec_type dmin = std::numeric_limits<prec_type>::max();
1664  typename TNeighborhood::const_iterator ineigh = neighc.begin();
1665  const_cyclic_iterator<TNeighborhood> ineigh2(neighc, neighc.begin());
1667  ++ineigh2;
1668  for (; ineigh != neighc.end(); ++ineigh, ++ineigh2)
1669  {
1670  geo::Project::PointOnTriangle3D<typename TVertexCollection::value_type, numeric_array<TPrec, 3> >()(p, vertices[i], vertices[*ineigh], vertices[*ineigh2], tmp);
1671  prec_type d = dist2(p, tmp, prec<prec_type>());
1672  if (d < dmin)
1673  {
1674  geo::triangle_normal(vertices[i], vertices[*ineigh], vertices[*ineigh2], res);
1675  dmin = d;
1676  }
1677  else if (d == dmin)
1678  {
1680  geo::triangle_normal(vertices[i], vertices[*ineigh], vertices[*ineigh2], tmp);
1681  res += tmp;
1682  }
1683  }
1684  return res;
1685  }
1686 
1687  // --------------------------------------------------------------------------
1688 
1689  template < typename TVertexAccessPolicy, typename TNeighborhoodAccessPolicy, typename TVertexAccessPolicy2 >
1691  {
1692  public: // typedefs
1693 
1694  typedef typename TNeighborhoodAccessPolicy::value_type Neighborhood;
1695  typedef typename TVertexAccessPolicy::value_type Vertex;
1696  typedef typename TVertexAccessPolicy::index_type VertexIndex;
1697  typedef typename TVertexAccessPolicy2::index_type VertexIndex2;
1698  typedef typename Vertex::value_type prec_type;
1699 
1700  public: // constructors
1701 
1703  (
1704  TVertexAccessPolicy vertexAccess,
1705  TNeighborhoodAccessPolicy neighborAccess,
1706  TVertexAccessPolicy2 vertexAccess2,
1707  prec_type lambda
1708  )
1709  : m_vertexAccess(vertexAccess)
1710  , m_neighborAccess(neighborAccess)
1711  , m_vertexAccess2(vertexAccess2)
1712  , m_lambda(lambda)
1713  {}
1714 
1715  public: // functions
1716 
1717  void operator()(VertexIndex begin, VertexIndex end, VertexIndex2 begin2)
1718  {
1719  for (; begin != end; ++begin, ++begin2)
1720  {
1721  m_buffer[0] = m_buffer[1] = m_buffer[2] = 0;
1722  prec_type E = 0;
1723  m_vertexAccess2(begin2) = m_vertexAccess(begin);
1724  //prec_type coeff = m_lambda / m_neighborAccess(begin).size();
1725  for (typename Neighborhood::const_iterator iNeigh = m_neighborAccess(begin).begin(); iNeigh != m_neighborAccess(begin).end(); ++iNeigh)
1726  {
1727  m_tmp = m_vertexAccess(*iNeigh) - m_vertexAccess(begin);
1728  prec_type d = norm(m_tmp); //dist(m_vertexAccess(*iNeigh), m_vertexAccess(begin));
1729  E += d;
1730  m_tmp *= 1/d;
1731  m_buffer += m_tmp;
1732  //m_vertexAccess2(begin2) += (m_vertexAccess(*iNeigh) - m_vertexAccess2(begin2));
1733  }
1734  m_vertexAccess2(begin2) += m_lambda * (2/E) * m_buffer;
1735  }
1736  }
1737 
1738  private: // data, input
1739 
1740  TVertexAccessPolicy m_vertexAccess;
1741  TNeighborhoodAccessPolicy m_neighborAccess;
1742  TVertexAccessPolicy2 m_vertexAccess2;
1743  prec_type m_lambda;
1744 
1745  private: // data, internals
1746 
1747  numeric_array<prec_type, 3> m_buffer;
1749  };
1750 
1751  //---------------------------------------------------------------------------
1752 
1753  //----------------------//
1754  // LaplacianSmoothing //
1755  //----------------------//
1756 
1759  template < typename TInputAccessPolicy, typename TOutputAccessPolicy, typename TNeighborhoodAccessPolicy >
1761  {
1762  public: // typedefs
1763 
1764  typedef typename TNeighborhoodAccessPolicy::value_type Neighborhood;
1765  typedef typename TInputAccessPolicy::value_type Data;
1766  typedef typename TInputAccessPolicy::index_type InputIndex;
1767  typedef typename TOutputAccessPolicy::index_type OutputIndex;
1769 
1770  public: // constructors
1771 
1773  (
1774  TInputAccessPolicy inputAccess,
1775  TOutputAccessPolicy outputAccess,
1776  TNeighborhoodAccessPolicy neighborAccess,
1777  prec_type lambda
1778  )
1779  : m_inputAccess(inputAccess)
1780  , m_outputAccess(outputAccess)
1781  , m_neighborAccess(neighborAccess)
1782  , m_lambda(lambda)
1783  {}
1784 
1785  public: // functions
1786 
1787  void operator()(InputIndex begin, InputIndex end, OutputIndex begin2)
1788  {
1789  for (; begin != end; ++begin, ++begin2)
1790  {
1791  // Check that now to avoid division by zero later
1792  assert(m_neighborAccess(begin).size() > 0);
1793 
1794  m_outputAccess(begin2) = m_inputAccess(begin) * (1 - m_lambda);
1795  prec_type coeff = m_lambda / m_neighborAccess(begin).size();
1796  typename Neighborhood::const_iterator iNeigh = m_neighborAccess(begin).begin();
1797  for (; iNeigh != m_neighborAccess(begin).end(); ++iNeigh)
1798  {
1799  m_outputAccess(begin2) += coeff * m_inputAccess(*iNeigh);
1800 
1801  // NB: this could be in a policy
1802  if (is_nan(m_outputAccess(begin2)))
1803  {
1804  std::cout << "(LS:is-nan)";
1805  }
1806  }
1807  }
1808  }
1809 
1810  private: // data, input
1811 
1812  TInputAccessPolicy m_inputAccess;
1813  TOutputAccessPolicy m_outputAccess;
1814  TNeighborhoodAccessPolicy m_neighborAccess;
1815  prec_type m_lambda;
1816  };
1817 
1818 
1820  template < typename TVertex >
1821  inline void laplacian_smoothing
1822  (
1823  std::vector<TVertex> & vertices,
1824  std::vector<std::vector<std::size_t> > & neighbors,
1825  unsigned int nstep,
1826  double coeff
1827  )
1828  {
1829  typedef std::vector<TVertex> TVertexCollection;
1830  typedef policy::IntegerIndexing<TVertexCollection> VertexIndexing;
1833 
1834  std::size_t n = vertices.size();
1835 
1836  std::vector<TVertex> verticesBuff(n);
1837  VertexIndexing indVertex(vertices);
1838  VertexIndexing indVertexBuff(verticesBuff);
1839  NeighborIndexing indNeigh(neighbors);
1840  Smoother smoothToBuffer(indVertex, indVertexBuff, indNeigh, coeff);
1841  Smoother smoothFromBuffer(indVertexBuff, indVertex, indNeigh, coeff);
1842  for (unsigned int i = 0; i < nstep; ++i)
1843  {
1844  smoothToBuffer(0, n, 0);
1845  smoothFromBuffer(0, n, 0);
1846  }
1847  }
1848 
1849  //---------------------------------------------------------------------------
1850 
1851 
1852  template < typename TVertexAccessPolicy, typename TNeighborhoodAccessPolicy > //, typename TPrec >
1854  {
1855  public: // typedefs ---------------------------------------------------------
1856 
1857  //typedef TPrec prec_type;
1858  typedef typename TNeighborhoodAccessPolicy::value_type Neighborhood;
1859  typedef typename TVertexAccessPolicy::value_type Vertex;
1860  typedef typename TVertexAccessPolicy::index_type VertexIndex;
1861  typedef typename Vertex::value_type prec_type;
1862 
1863  public: // constructors -----------------------------------------------------
1864 
1866  (
1867  TVertexAccessPolicy vertexAccess,
1868  TNeighborhoodAccessPolicy neighborAccess,
1869  const prec_type lambda,
1870  const prec_type mu,
1871  int bufferSize
1872  )
1873  : m_vertexAccess(vertexAccess)
1874  , m_neighborAccess(neighborAccess)
1875  , m_lambda(lambda)
1876  , m_mu(mu)
1877  {
1878  this->setBufferSize(bufferSize);
1879  }
1880 
1881 
1882  public: // set & get --------------------------------------------------------
1883 
1884  prec_type & lambda() { return m_lambda; }
1885  prec_type & mu() { return m_mu; }
1886  void setBufferSize(int bufferSize) { m_vertices.resize(bufferSize); }
1887 
1888  public: // functions --------------------------------------------------------
1889 
1890  void operator()(VertexIndex begin, VertexIndex end)
1891  {
1892  this->lambda_step(begin, end);
1893  this->mu_step(begin, end);
1894  }
1895 
1896  private: // functions -------------------------------------------------------
1897 
1898  void lambda_step(VertexIndex begin, VertexIndex end)
1899  {
1900  for (std::size_t i = 0; begin != end; ++begin, ++i)
1901  {
1902  m_vertices[i] = m_vertexAccess(begin) * (1 - m_lambda);
1903  prec_type coeff = m_lambda / m_neighborAccess(begin).size();
1904  typename Neighborhood::const_iterator iNeigh = m_neighborAccess(begin).begin();
1905  for (; iNeigh != m_neighborAccess(begin).end(); ++iNeigh)
1906  {
1907  m_vertices[i] += coeff * m_vertexAccess(*iNeigh);
1908  }
1909  }
1910  }
1911 
1912  void mu_step(VertexIndex begin, VertexIndex end)
1913  {
1914  for (std::size_t i = 0; begin != end; ++begin, ++i)
1915  {
1916  m_vertexAccess(begin) = m_vertices[i] * (1 + m_mu);
1917  prec_type coeff = m_mu / m_neighborAccess(begin).size();
1918  typename Neighborhood::const_iterator iNeigh = m_neighborAccess(begin).begin();
1919  for (; iNeigh != m_neighborAccess(begin).end(); ++iNeigh)
1920  {
1921  m_vertexAccess(begin) -= coeff * m_vertexAccess(*iNeigh);
1922  }
1923  }
1924  }
1925 
1926  private: // data, input -----------------------------------------------------
1927 
1928  TVertexAccessPolicy m_vertexAccess;
1929  TNeighborhoodAccessPolicy m_neighborAccess;
1930  prec_type m_lambda;
1931  prec_type m_mu;
1932 
1933  private: // data, internals -------------------------------------------------
1934 
1935  std::vector<Vertex> m_vertices;
1936  };
1937 
1938  //----------------------------------------------------------------------------
1939 
1941  template < typename NeighborCollection, typename NeighborCollectionOut >
1942  void
1944  (
1945  NeighborCollection const & neigh
1946  , NeighborCollectionOut & neigh_n_out
1947  , unsigned int n
1948  );
1949 
1950  //---------------------------------------------------------------------------
1951 
1955  template < typename T >
1956  void
1958  (
1959  std::vector<std::vector<T> > const & neighbors
1960  , std::vector<std::pair<T, T> > & edges
1961  );
1962 
1963  //---------------------------------------------------------------------------
1964 
1965  template < typename T >
1967  {
1968  public: // exceptions
1969  struct InconsistentArguments : public std::exception {};
1970  public: // operator
1974  void operator()
1975  (
1976  std::vector<std::vector<T> > const & cneighs
1977  , std::vector<til::numeric_array<T, 3> > const & faces
1978  , std::vector<std::vector<T> > & neighborfaces
1979  );
1980  };
1981 
1982  //---------------------------------------------------------------------------
1983 
1987  template < typename T >
1988  inline void
1990  (
1991  std::vector<std::vector<T> > const & cneighs
1992  , std::vector<til::numeric_array<T, 3> > const & faces
1993  , std::vector<std::vector<T> > & neighborfaces
1994  )
1995  {
1996  Neighboring_faces<T>()(cneighs, faces, neighborfaces);
1997  }
1998 
1999  //---------------------------------------------------------------------------
2000 
2001 } // namespace til
2002 
2003 
2004 // package include
2005 #include "mesh_utils.tpp"
2006 
2007 #endif //_MESHUTILS_H_
prec_type voronoiArea() const
Return computed voronoi area at vertex.
Definition: meshUtils.h:953
namespace for template expressions.
prec_type & lambda()
Definition: meshUtils.h:1884
Project a point onto a 3D triangle.
Definition: geometrics.h:393
std::pair< T, T > make_sorted_pair(T a, T b)
Return (a, b) if a >= b, (b, a) else.
A class to represent a very basic mesh, consisting of a set of vertices and a set of edges...
Numerical precision of the data for storage classes.
Definition: traits.h:48
#define M_PI
Definition: til_common.h:48
void operator()(VertexIndex begin, VertexIndex end, VertexIndex2 begin2)
Definition: meshUtils.h:1717
numeric_array< double, 3 > closest_normal(const TVertex &p, TVertexIndex i, const TVertexCollection &vertices, const TNeighborhood &neighc)
Returns the index of the neighborhood that is the closest.
Definition: meshUtils.h:1659
TVertexAccessPolicy::value_type Vertex
Definition: meshUtils.h:1859
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)
TCollection::reference operator()(index_type i)
Definition: meshUtils.h:1116
void sqrt(const TImage &in, TImage &out)
Definition: imageArith.h:326
TNeighborhoodAccessPolicy::value_type Neighborhood
Definition: meshUtils.h:1764
prec_type unorientedGaussianCurvature() const
Return unoriented Gaussian curvature at vertex.
Definition: meshUtils.h:958
TInputAccessPolicy::index_type InputIndex
Definition: meshUtils.h:1766
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.
boost::enable_if_c< is_container< typename TContainer::value_type >::value >::type for_each_neighbors(const TMesh &mesh, TContainer &c1, TFunctor f)
Definition: meshUtils.h:585
shared_ptr< std::vector< std::pair< std::size_t, std::size_t > > > faces2edges(TFaceCollection const &faces)
Collects edges from a set of faces.
Definition: meshUtils.h:335
std::map< Edge, std::vector< index_type > > Edges
Definition: meshUtils.h:237
prec_type & mu()
Definition: meshUtils.h:1885
IntegerIndexing(TCollection &data)
Definition: meshUtils.h:1113
MeshTraits< Mesh_N >::NeighborIndexCollection & getNeighborIndices(Mesh_N &mesh)
Definition: MeshTraits.h:380
Return value pointed at by an iterator.
Definition: meshUtils.h:1140
TCollection::const_reference operator()(index_type i) const
Definition: meshUtils.h:1118
Mesh_curvature2(TVertexXsr vertexXsr, TCircularNeighborXsr neighXsr)
Definition: meshUtils.h:773
void process(VertexIndex i)
Computes all the good stuff at the i-th vertex.
Definition: meshUtils.h:1227
const numeric_array< prec_type, 3 > & normal() const
Return computed normal.
Definition: meshUtils.h:790
shared_ptr< std::vector< typename TCollection::const_iterator > > gonzalez_clustering(const TCollection &data, TPrec maxDiam)
Gonzalez clustering.
Definition: meshUtils.h:1542
TCircularNeighborXsr::value_type Neighborhood
Definition: meshUtils.h:765
prec_type meanCurvature() const
Return computed (signed) mean curvature at vertex.
Definition: meshUtils.h:948
TPrec dot(const numeric_array< T1, D > &a1, const numeric_array< T2, D > &a2, prec< TPrec >)
Return the dot product of two vectors.
std::size_t getVertexNumber(const TMesh &, std::size_t i)
Return the index of vertex v[i] – which is, obviously, i.
Definition: meshUtils.h:56
void convert_mesh1Toaimsmesh(const til::Mesh1 &meshFrom, AimsTimeSurface< 3, Void > &meshTo)
Definition: meshUtils.h:115
INLINE double norm(const T &a, const T &b)
< Euclidean norm of 2D vector (a, b)
TVertexXsr::reference VertexRef
Definition: meshUtils.h:768
STL namespace.
TVertexXsr::index_type index_type
Definition: meshUtils.h:769
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
TExpr< TExprBinaryOperator< Expr1, Expr2, functor::CastTo > > castTo(TExpr< Expr1 > e1, TExpr< Expr2 > e2)
bool triangle_normal(const TArray &A, const TArray &B, const TArray &C, TResArray &result)
Compute the normal of a triangle.
A const cyclic iterator is a const iterator that goes back to the begining of the container when it r...
value_type & operator()(index_type i) const
Definition: meshUtils.h:1162
TIterator::value_type::VertexIndex index_type
Definition: meshUtils.h:1158
value_type & operator()(index_type i) const
Definition: meshUtils.h:1176
void addNewClusterSeed()
Add a new cluster to the list.
Definition: meshUtils.h:1486
TNeighborhoodAccessPolicy::value_type Neighborhood
Definition: meshUtils.h:1694
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
Definition: boxTools.h:56
prec_type unorientedMeanCurvature() const
Return unoriented mean curvature at vertex.
Definition: meshUtils.h:1220
prec_type gaussianCurvature() const
Return computed (signed) Gaussian curvature at vertex.
Definition: meshUtils.h:781
MeshCurvature2(TVertexAccessPolicy vertexAccess, TCircularNeighborhoodAccessPolicy neighborAccess)
Definition: meshUtils.h:1200
TCollection::value_type value_type
Definition: meshUtils.h:1108
prec_type meanCurvature() const
Return computed (signed) mean curvature at vertex.
Definition: meshUtils.h:1208
void setBufferSize(int bufferSize)
Definition: meshUtils.h:1886
void convert_mesh_3(const TMeshFrom &meshFrom, TMeshTo &meshTo)
Definition: meshUtils.h:162
TVertexAccessPolicy::index_type VertexIndex
Definition: meshUtils.h:1696
void for_each_neighbors_NV(const TMesh &mesh, TContainer1 &c1, TContainer2 &c2, TFunctor f)
Apply a functor for each pair (vertex, neighbor_of_vertex), given a mesh and two extra containers...
Definition: meshUtils.h:655
void for_each_neighbors_V(const TMesh &mesh, TContainer &c, TFunctor f)
Apply a functor for each pair (vertex, neighbor_of_vertex), given a mesh and another container...
Definition: meshUtils.h:551
TVertexAccessPolicy::index_type VertexIndex
Definition: meshUtils.h:1860
TPrec dist2_surface(const TVertex &p, TVertexIndex i, const TVertexCollection &vertices, const TNeighborhood &neighc)
Simple flattening of a point and its neighborhood.
Definition: meshUtils.h:1634
void get_edges_and_faces(TFaceCollection const &faces, std::vector< std::pair< std::size_t, std::size_t > > &res, std::vector< std::vector< std::size_t > > &newfaces)
Definition: meshUtils.h:321
TData::value_type value_type
Definition: meshUtils.h:1364
TIterator::value_type::Vertex value_type
Definition: meshUtils.h:1157
Mesh policy for vertices indexed with an integer.
Definition: meshUtils.h:1104
void laplacian_smoothing(std::vector< TVertex > &vertices, std::vector< std::vector< std::size_t > > &neighbors, unsigned int nstep, double coeff)
Laplacian smoothing – helper function.
Definition: meshUtils.h:1822
value_type & operator()(index_type i) const
Definition: meshUtils.h:1146
TVertexCollection::value_type Vertex
Definition: meshUtils.h:936
TImage::value_type max(const TImage &im)
Returns the maximum intensity of the input image.
void computeClusters()
update labels to reflect current clustering.
Definition: meshUtils.h:1426
void process(index_type i)
Computes all the good stuff at the i-th vertex.
Definition: meshUtils.h:802
void loop_xx(expr::TExpr< Expr > expr, TIterator1 start1, const TIterator1 end1, TIterator2 start2)
Definition: TExpr.h:427
prec_type unorientedGaussianCurvature() const
Return unoriented Gaussian curvature at vertex.
Definition: meshUtils.h:793
const numeric_array< prec_type, 3 > & normal() const
Return computed normal.
Definition: meshUtils.h:1215
void copy(const TImage &in, TImage &out)
Copy one image to another.
Definition: imageTools.h:133
std::pair< prec_type, prec_type > principalCurvatures() const
Return computed (signed) principal curvatures at vertex.
Definition: meshUtils.h:1211
void get_n_neighborhood(NeighborCollection const &neigh, NeighborCollectionOut &neigh_n_out, unsigned int n)
Computes the n-neighborhood, i.e. collection of neighbors that are at most n jumps away...
Gonzalez clustering.
Definition: meshUtils.h:1357
TIterator::value_type::VertexIndexCollection value_type
Definition: meshUtils.h:1173
const TExpr< expr::SecondArgument > _2
Placeholder for the second argument.
Definition: TExpr.h:207
TVertexAccessPolicy::value_type Vertex
Definition: meshUtils.h:1194
const TExpr< expr::FirstArgument > _1
Placeholder for the first argument.
Definition: TExpr.h:205
void convert_mesh_2(const TMeshFrom &meshFrom, TMeshTo &meshTo)
When indices of from are numbers and two are pointers.
Definition: meshUtils.h:134
void clusterize_maxDiam(prec_type maxDiam)
Clustering, until max cluster diameter is less than a threshold.
Definition: meshUtils.h:1386
TCircularNeighborIndices::value_type Neighborhood
Definition: meshUtils.h:935
AimsSurfaceTriangle * makeSphere(const Point3df &center, float radius, int iter)
TInputAccessPolicy::value_type Data
Definition: meshUtils.h:1765
Computes the Euclidean distance between two vectors.
Definition: miscUtils.h:266
shared_ptr< std::vector< std::size_t > > labels()
Definition: meshUtils.h:1381
TIterator::value_type value_type
Definition: meshUtils.h:1143
prec_type unorientedGaussianCurvature() const
Return unoriented Gaussian curvature at vertex.
Definition: meshUtils.h:1218
detail::AddNeighborIndexAttribute< Mesh< TParam > > addNeighborsToMesh(const Mesh< TParam > &mesh)
Definition: meshUtils.h:499
std::pair< prec_type, prec_type > principalCurvatures() const
Return computed (signed) principal curvatures at vertex.
Definition: meshUtils.h:951
void allocate_sameSize(const TContainer1 &c1, TContainer2 &c2)
A simple function to allocate a container so that its size matches the size of a second container...
Definition: miscUtils.h:201
prec_type unorientedMeanCurvature() const
Return unoriented mean curvature at vertex.
Definition: meshUtils.h:960
void neighboring_faces(std::vector< std::vector< T > > const &cneighs, std::vector< til::numeric_array< T, 3 > > const &faces, std::vector< std::vector< T > > &neighborfaces)
Computes the index of the neighboring faces.
Definition: meshUtils.h:1990
This file contains all the material a library user should need to use template expressions.
Discrete Laplacian smoothing.
Definition: meshUtils.h:1760
const MeshTraits< Mesh_N >::Vertex & getVertexNeighbor(const Mesh_N &mesh, const MeshTraits< Mesh_N >::NeighborIndex::value_type &iNi)
Returns the vertex neighbors of a mesh of type Mesh_N given by its index.
Definition: MeshTraits.h:513
std::pair< prec_type, prec_type > principalCurvatures() const
Return computed (signed) principal curvatures at vertex.
Definition: meshUtils.h:786
Traits for meshes.
const MeshTraits< AimsSurface< D, T > >::FaceIndexCollection & getFaceIndices(const AimsSurface< D, T > &mesh)
Definition: aims_wrap.h:505
prec_type gaussianCurvature() const
Return computed (signed) Gaussian curvature at vertex.
Definition: meshUtils.h:1206
GonzalezClustering(const TData &data)
Definition: meshUtils.h:1368
void operator()(InputIndex begin, InputIndex end, OutputIndex begin2)
Definition: meshUtils.h:1787
prec_type voronoiArea() const
Return computed voronoi area at vertex.
Definition: meshUtils.h:788
void neighborhoods2edges(TNeighborhoodCollection const &neigh, std::vector< std::pair< std::size_t, std::size_t > > &edges)
Collects edges from a set of neighbors.
Definition: meshUtils.h:364
void for_each_neighbors_N(const TMesh &mesh, TContainer &c, TFunctor f)
Apply a functor for each pair (vertex, neighbor_of_vertex), given a mesh and another container...
Definition: meshUtils.h:518
void neighbors2edges(std::vector< std::vector< T > > const &neighbors, std::vector< std::pair< T, T > > &edges)
Convert a set of neighborhoods into a set of edges.
void operator()(VertexIndex begin, VertexIndex end)
Definition: meshUtils.h:1890
TNeighborhoodAccessPolicy::value_type Neighborhood
Definition: meshUtils.h:1858
precision< Data >::type prec_type
Definition: meshUtils.h:1768
const numeric_array< prec_type, 3 > & normal() const
Return computed normal.
Definition: meshUtils.h:955
void square(const TImage &in, TImage &out)
Definition: imageArith.h:310
void convert_aimsmeshTomesh1(const AimsTimeSurface< 3, Void > &meshFrom, til::Mesh1 &meshTo)
Definition: meshUtils.h:98
prec_type voronoiArea() const
Return computed voronoi area at vertex.
Definition: meshUtils.h:1213
Mesh_curvature(const TVertexCollection &vertices, const TCircularNeighborIndices &neighs)
Definition: meshUtils.h:940
TVertexAccessPolicy2::index_type VertexIndex2
Definition: meshUtils.h:1697
This class enhance a mesh class with a neighbor index attribute.
shared_ptr< std::vector< iterator > > quantization()
Returns data quantization, i.e. a subset of the original data of representative of its clusters...
Definition: meshUtils.h:1379
void for_each_neighbors_NN(const TMesh &mesh, TContainer1 &c1, TContainer2 &c2, TFunctor f)
Apply a functor for each pair (vertex, neighbor_of_vertex), given a mesh and two extra containers...
Definition: meshUtils.h:613
std::pair< index_type, index_type > Edge
Definition: meshUtils.h:236
std::size_t index_type
Definition: meshUtils.h:235
void fill(sparse_vector< T, BaselinePolicy > &v, typename boost::call_traits< T >::param_type value)
Specialized fill for sparse_vector.
prec_type gaussianCurvature() const
Return computed (signed) Gaussian curvature at vertex.
Definition: meshUtils.h:946
void moveClusterSeeds()
Move cluster quantized vector as close to cluster center as possible.
Definition: meshUtils.h:1447
boost::enable_if_c< MeshTraits< TMesh >::has_neighbor_indices >::type getEdgeLengths(const TMesh &mesh, std::vector< std::vector< TPrecision > > &lengths)
Computes edge lengths of a mesh.
Definition: meshUtils.h:742
TCircularNeighborhoodAccessPolicy::value_type Neighborhood
Definition: meshUtils.h:1192
TOutputAccessPolicy::index_type OutputIndex
Definition: meshUtils.h:1767
TVertexAccessPolicy::index_type VertexIndex
Definition: meshUtils.h:1195
prec_type meanCurvature() const
Return computed (signed) mean curvature at vertex.
Definition: meshUtils.h:783
TIterator::value_type::VertexIndex index_type
Definition: meshUtils.h:1174
prec_type unorientedMeanCurvature() const
Return unoriented mean curvature at vertex.
Definition: meshUtils.h:795
Vertex::value_type prec_type
Definition: meshUtils.h:1861
A dummy class used to pass a precision type for computations to some functions.
Static cast functor.
Definition: functors.h:163
void process(std::size_t i)
Computes all the good stuff at the i-th vertex.
Definition: meshUtils.h:967
TCircularNeighborXsr::reference NeighborhoodRef
Definition: meshUtils.h:766
TVertexAccessPolicy::value_type Vertex
Definition: meshUtils.h:1695
const MeshTraits< AimsSurface< D, T > >::VertexCollection & getVertices(const AimsSurface< D, T > &mesh)
Definition: aims_wrap.h:474
TPrec dist2(const numeric_array< T1, D > &v1, const numeric_array< T2, D > &v2, prec< TPrec >)
Return the squared Euclidean distance between two vectors, computed with a precision given as the fir...
bool is_nan(const numeric_array< T, D > &a)
Check that numeric_array does not contain any NAN TODO: Actually, is_nan should be a functor...