aimsalgo  5.1.2
Neuroimaging image processing
geodesic_mesh.h
Go to the documentation of this file.
1 //Copyright (C) 2008 Danil Kirsanov, MIT License
2 #ifndef GEODESIC_MESH_20071231
3 #define GEODESIC_MESH_20071231
4 
5 #include <cstddef>
6 #include <vector>
7 #include <cmath>
8 #include <iostream>
9 #include <algorithm>
10 #include <fstream>
11 
12 #include "geodesic_mesh_elements.h"
13 #include "geodesic_memory.h"
15 
16 namespace geodesic{
17 
19 {
20  unsigned source;
22 };
23 
24 class Mesh
25 {
26 public:
27  Mesh()
28  {};
29 
30  ~Mesh(){};
31 
32  template<class Points, class Faces>
33  void initialize_mesh_data(unsigned num_vertices,
34  Points& p,
35  unsigned num_faces,
36  Faces& tri, const float* curvature, int mode,int strain); //build mesh from regular point-triangle representation
37 
38  template<class Points, class Faces>
39  void initialize_mesh_data(Points& p, Faces& tri, const float* curvature, int mode,int strain); //build mesh from regular point-triangle representation
40 
41  void update_weight(const float *curvature,int mode,double strain, double sigmo); //build internal structure of the mesh
42 
43  std::vector<Vertex>& vertices(){return m_vertices;};
44  std::vector<Edge>& edges(){return m_edges;};
45  std::vector<Face>& faces(){return m_faces;};
46 
47  unsigned closest_vertices(SurfacePoint* p,
48  std::vector<vertex_pointer>* storage = NULL); //list vertices closest to the point
49 
50 private:
51 
52  void build_adjacencies(const float *curvature,int mode,int strain); //build internal structure of the mesh
53  bool verify(); //verifies connectivity of the mesh and prints some debug info
54 
55  typedef void* void_pointer;
56  void_pointer allocate_pointers(unsigned n)
57  {
58  return m_pointer_allocator.allocate(n);
59  }
60 
61  std::vector<Vertex> m_vertices;
62  std::vector<Edge> m_edges;
63  std::vector<Face> m_faces;
64 
65  SimlpeMemoryAllocator<void_pointer> m_pointer_allocator; //fast memory allocating for Face/Vertex/Edge cross-references
66 };
67 
69  std::vector<vertex_pointer>* storage)
70 {
71  assert(p->type() != UNDEFINED_POINT);
72 
73  if(p->type() == VERTEX)
74  {
75  if(storage)
76  {
77  storage->push_back(static_cast<vertex_pointer>(p->base_element()));
78  }
79  return 1;
80  }
81  else if(p->type() == FACE)
82  {
83  if(storage)
84  {
86  storage->push_back(*vp);
87  storage->push_back(*(vp+1));
88  storage->push_back(*(vp+2));
89  }
90  return 2;
91  }
92  else if(p->type() == EDGE) //for edge include all 4 adjacent vertices
93  {
94  edge_pointer edge = static_cast<edge_pointer>(p->base_element());
95 
96  if(storage)
97  {
98  storage->push_back(edge->adjacent_vertices()[0]);
99  storage->push_back(edge->adjacent_vertices()[1]);
100 
101  for(unsigned i = 0; i < edge->adjacent_faces().size(); ++i)
102  {
103  face_pointer face = edge->adjacent_faces()[i];
104  storage->push_back(face->opposite_vertex(edge));
105  }
106  }
107  return 2 + edge->adjacent_faces().size();
108  }
109 
110  assert(0);
111  return 0;
112 }
113 
114 template<class Points, class Faces>
115 void Mesh::initialize_mesh_data(Points& p, Faces& tri, const float* curvature, int mode, int strain) //build mesh from regular point-triangle representation
116 {
117  assert(p.size() % 3 == 0);
118  unsigned const num_vertices = p.size() / 3;
119  assert(tri.size() % 3 == 0);
120  unsigned const num_faces = tri.size() / 3;
121 
122  initialize_mesh_data(num_vertices, p, num_faces, tri, curvature, mode, strain);
123 }
124 
125 template<class Points, class Faces>
126 void Mesh::initialize_mesh_data(unsigned num_vertices,
127  Points& p,
128  unsigned num_faces,
129  Faces& tri, const float* curvature, int mode, int strain)
130 {
131  //printf("initialize_mesh_data\n");
132 
133  unsigned const approximate_number_of_internal_pointers = (num_vertices + num_faces)*4;
134 
135  //printf("approximate_number_of_internal_pointers = \n");
136 
137  unsigned const max_number_of_pointer_blocks = 100;
138  m_pointer_allocator.reset(approximate_number_of_internal_pointers,
139  max_number_of_pointer_blocks);
140 
141  //printf("copy coordinates to vertices\n");
142 
143  m_vertices.resize(num_vertices);
144  for(unsigned i=0; i<num_vertices; ++i) //copy coordinates to vertices
145  {
146  Vertex& v = m_vertices[i];
147  v.id() = i;
148 
149  unsigned shift = 3*i;
150  v.x() = p[shift];
151  v.y() = p[shift + 1];
152  v.z() = p[shift + 2];
153  }
154 
155  //printf("copy adjacent vertices to polygons/faces \n");
156 
157  m_faces.resize(num_faces);
158  for(unsigned i=0; i<num_faces; ++i) //copy adjacent vertices to polygons/faces
159  {
160  //std::cout << i << std::endl;
161  Face& f = m_faces[i];
162  f.id() = i;
163  f.adjacent_vertices().set_allocation(allocate_pointers(3),3); //allocate three units of memory
164 
165  unsigned shift = 3*i;
166  unsigned vertex_index;
167  for(unsigned j=0; j<3; ++j)
168  {
169  //std::cout << shift + j;
170  vertex_index = tri[shift + j];
171  assert(vertex_index < num_vertices);
172  //if (vertex_index < num_vertices)
173  f.adjacent_vertices()[j] = &m_vertices[vertex_index];
174  }
175  }
176 
177  //printf("build the structure of the mesh \n");
178 
179  build_adjacencies(curvature,mode,strain); //build the structure of the mesh
180 }
181 
182 inline void Mesh::build_adjacencies(const float *curvature, int mode, int strain)
183 {
184  // Vertex->adjacent Faces
185  std::vector<unsigned> count(m_vertices.size()); //count adjacent vertices
186  for(unsigned i=0; i<m_faces.size(); ++i)
187  {
188  Face& f = m_faces[i];
189  for(unsigned j=0; j<3; ++j)
190  {
191  unsigned vertex_id = f.adjacent_vertices()[j]->id();
192 // assert(vertex_id < m_vertices.size());
193  count[vertex_id]++;
194  }
195  }
196 
197  for(unsigned i=0; i<m_vertices.size(); ++i) //reserve space
198  {
199  Vertex& v = m_vertices[i];
200  unsigned num_adjacent_faces = count[i];
201 
202  v.adjacent_faces().set_allocation(allocate_pointers(num_adjacent_faces), //allocate three units of memory
203  num_adjacent_faces);
204  }
205 
206  std::fill(count.begin(), count.end(), 0);
207  for(unsigned i=0; i<m_faces.size(); ++i)
208  {
209  Face& f = m_faces[i];
210  for(unsigned j=0; j<3; ++j)
211  {
212  vertex_pointer v = f.adjacent_vertices()[j];
213  v->adjacent_faces()[count[v->id()]++] = &f;
214  }
215  }
216 
217  //find all edges
218  //i.e. find all half-edges, sort and combine them into edges
219  std::vector<HalfEdge> half_edges(m_faces.size()*3);
220  unsigned k = 0;
221  for(unsigned i=0; i<m_faces.size(); ++i)
222  {
223  Face& f = m_faces[i];
224  for(unsigned j=0; j<3; ++j)
225  {
226  half_edges[k].face_id = i;
227  unsigned vertex_id_1 = f.adjacent_vertices()[j]->id();
228  unsigned vertex_id_2 = f.adjacent_vertices()[(j+1) % 3]->id();
229  half_edges[k].vertex_0 = std::min(vertex_id_1, vertex_id_2);
230  half_edges[k].vertex_1 = std::max(vertex_id_1, vertex_id_2);
231 
232  k++;
233  }
234  }
235  std::sort(half_edges.begin(), half_edges.end());
236 
237  unsigned number_of_edges = 1;
238  bool last_shared = false;
239  bool warned = false;
240  for(unsigned i=1; i<half_edges.size(); ++i)
241  {
242  if( half_edges[i] != half_edges[i-1] || last_shared )
243  {
244  ++number_of_edges;
245  last_shared = false;
246  }
247  else
248  {
249  last_shared = true;
250  if(i<half_edges.size()-1) //sanity check: there should be at most two equal half-edges
251  { //if it fails, most likely the input data are messed up
252  if( half_edges[i] == half_edges[i+1])
253  {
254 // throw std::logic_error("Duplicate edge. The mesh is malformed: some "
255 // "triangles share an edge with more than one other triangle.");
256  if( !warned )
257  {
258  std::cerr << "Warning: Duplicate edges. The mesh is malformed: "
259  << "some triangles share an edge with more than one "
260  << "other triangle.\n";
261  warned = true;
262  }
263  }
264  }
265  }
266  }
267 
268  // Edges->adjacent Vertices and Faces
269  m_edges.resize(number_of_edges);
270  unsigned edge_id = 0;
271  for(unsigned i=0; i<half_edges.size();)
272  {
273  std::cout << "\ri: " << i << std::flush;
274 
275  Edge& e = m_edges[edge_id];
276  e.id() = edge_id++;
277 
278  e.adjacent_vertices().set_allocation(allocate_pointers(2),2); //allocate two units of memory
279 
280  e.adjacent_vertices()[0] = &m_vertices[half_edges[i].vertex_0];
281  e.adjacent_vertices()[1] = &m_vertices[half_edges[i].vertex_1];
282 
283  //ARN
284  vertex_pointer v1 = e.adjacent_vertices()[0];
285  vertex_pointer v2 = e.adjacent_vertices()[1];
286 
287  //cout << i << "v1 = " << v1->id() << " curv = " << curvature[v1->id()];;
288  //cout << " v2 = " << v2->id() << " curv = " << curvature[v2->id()] << endl;
289 
290 // if (curvature!= NULL)
291 // e.length() = (v1->distance(v2)*(fabs(curvature[v2->id()] - curvature[v1->id()])) ) ;
292 // else
293 // e.length() = e.adjacent_vertices()[0]->distance(e.adjacent_vertices()[1]);
294 //
295  double a1 = 0.0,a2 = 0.0;
296 
297  if (curvature!= NULL && mode != 0)
298  {
299  // Sulcal
300  if (mode == 1)
301  {
302  a1 = pow ((1.0)/(1.0 + exp(-strain*curvature[v1->id()])), 2);
303  a2 = pow ((1.0)/(1.0 + exp(-strain*curvature[v2->id()])), 2);
304  }
305 
306  // Gyral
307  if (mode == 2)
308  {
309  a1 = pow ((1.0)/(1.0 + exp(strain*curvature[v1->id()])), 2);
310  a2 = pow ((1.0)/(1.0 + exp(strain*curvature[v2->id()])), 2);
311  }
312 
313  e.length() = (v1->distance(v2) * (a1 + a2));
314  }
315  else
316  e.length() = e.adjacent_vertices()[0]->distance(e.adjacent_vertices()[1]);
317 
318  //assert(e.length() > 1e-100);
319  //algorithm works well with non-degenerate meshes only
320 
321  if(i != half_edges.size()-1 && half_edges[i] == half_edges[i+1]) //double edge
322  {
323  e.adjacent_faces().set_allocation(allocate_pointers(2),2);
324  e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
325  e.adjacent_faces()[1] = &m_faces[half_edges[i+1].face_id];
326  i += 2;
327  }
328  else //single edge
329  {
330  e.adjacent_faces().set_allocation(allocate_pointers(1),1); //one adjucent faces
331  e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
332  i += 1;
333  }
334  }
335 
336  // Vertices->adjacent Edges
337  std::fill(count.begin(), count.end(), 0);
338  for(unsigned i=0; i<m_edges.size(); ++i)
339  {
340  Edge& e = m_edges[i];
341  assert(e.adjacent_vertices().size()==2);
342  count[e.adjacent_vertices()[0]->id()]++;
343  count[e.adjacent_vertices()[1]->id()]++;
344  }
345  for(unsigned i=0; i<m_vertices.size(); ++i)
346  {
347  m_vertices[i].adjacent_edges().set_allocation(allocate_pointers(count[i]),
348  count[i]);
349  }
350  std::fill(count.begin(), count.end(), 0);
351  for(unsigned i=0; i<m_edges.size(); ++i)
352  {
353  Edge& e = m_edges[i];
354  for(unsigned j=0; j<2; ++j)
355  {
356  vertex_pointer v = e.adjacent_vertices()[j];
357  v->adjacent_edges()[count[v->id()]++] = &e;
358  }
359  }
360 
361  // Faces->adjacent Edges
362  for(unsigned i=0; i<m_faces.size(); ++i)
363  {
364  m_faces[i].adjacent_edges().set_allocation(allocate_pointers(3),3);
365  }
366 
367  count.resize(m_faces.size());
368  std::fill(count.begin(), count.end(), 0);
369  for(unsigned i=0; i<m_edges.size(); ++i)
370  {
371  Edge& e = m_edges[i];
372  for(unsigned j=0; j<e.adjacent_faces().size(); ++j)
373  {
374  face_pointer f = e.adjacent_faces()[j];
375  assert(count[f->id()]<3);
376  f->adjacent_edges()[count[f->id()]++] = &e;
377  }
378  }
379 
380  //compute angles for the faces
381  for(unsigned i=0; i<m_faces.size(); ++i)
382  {
383  Face& f = m_faces[i];
384  double abc[3];
385  double sum = 0;
386  for(unsigned j=0; j<3; ++j) //compute angle adjacent to the vertex j
387  {
388  for(unsigned k=0; k<3; ++k)
389  {
390  vertex_pointer v = f.adjacent_vertices()[(j + k)%3];
391  abc[k] = f.opposite_edge(v)->length();
392  }
393 
394  double angle = angle_from_edges(abc[0], abc[1], abc[2]);
395 
396  //ARN
397  //assert(angle>1e-5); //algorithm works well with non-degenerate meshes only
398 
399  f.corner_angles()[j] = angle;
400  sum += angle;
401  }
402  //assert(std::abs(sum - M_PI) < 1e-5); //algorithm works well with non-degenerate meshes only
403  }
404 
405  //define m_turn_around_flag for vertices
406  std::vector<double> total_vertex_angle(m_vertices.size());
407  for(unsigned i=0; i<m_faces.size(); ++i)
408  {
409  Face& f = m_faces[i];
410  for(unsigned j=0; j<3; ++j)
411  {
413  total_vertex_angle[v->id()] += f.corner_angles()[j];
414  }
415  }
416 
417  for(unsigned i=0; i<m_vertices.size(); ++i)
418  {
419  Vertex& v = m_vertices[i];
420  v.saddle_or_boundary() = (total_vertex_angle[v.id()] > 2.0*M_PI - 1e-5);
421  }
422 
423  for(unsigned i=0; i<m_edges.size(); ++i)
424  {
425  Edge& e = m_edges[i];
426  if(e.is_boundary())
427  {
428  e.adjacent_vertices()[0]->saddle_or_boundary() = true;
429  e.adjacent_vertices()[1]->saddle_or_boundary() = true;
430  }
431  }
432 
433  //assert(verify());
434 }
435 
436 inline void Mesh::update_weight(const float *curvature, int mode,double strain,double sigmo)
437 {
438  // Vertex->adjacent Faces
439  std::vector<unsigned> count(m_vertices.size()); //count adjacent vertices
440  for(unsigned i=0; i<m_faces.size(); ++i)
441  {
442  Face& f = m_faces[i];
443  for(unsigned j=0; j<3; ++j)
444  {
445  unsigned vertex_id = f.adjacent_vertices()[j]->id();
446  assert(vertex_id < m_vertices.size());
447  count[vertex_id]++;
448  }
449  }
450 
451  for(unsigned i=0; i<m_vertices.size(); ++i) //reserve space
452  {
453  Vertex& v = m_vertices[i];
454  unsigned num_adjacent_faces = count[i];
455 
456  v.adjacent_faces().set_allocation(allocate_pointers(num_adjacent_faces), //allocate three units of memory
457  num_adjacent_faces);
458  }
459 
460  std::fill(count.begin(), count.end(), 0);
461  for(unsigned i=0; i<m_faces.size(); ++i)
462  {
463  Face& f = m_faces[i];
464  for(unsigned j=0; j<3; ++j)
465  {
467  v->adjacent_faces()[count[v->id()]++] = &f;
468  }
469  }
470 
471  //find all edges
472  //i.e. find all half-edges, sort and combine them into edges
473  std::vector<HalfEdge> half_edges(m_faces.size()*3);
474  unsigned k = 0;
475  for(unsigned i=0; i<m_faces.size(); ++i)
476  {
477  Face& f = m_faces[i];
478  for(unsigned j=0; j<3; ++j)
479  {
480  half_edges[k].face_id = i;
481  unsigned vertex_id_1 = f.adjacent_vertices()[j]->id();
482  unsigned vertex_id_2 = f.adjacent_vertices()[(j+1) % 3]->id();
483  half_edges[k].vertex_0 = std::min(vertex_id_1, vertex_id_2);
484  half_edges[k].vertex_1 = std::max(vertex_id_1, vertex_id_2);
485 
486  k++;
487  }
488  }
489  std::sort(half_edges.begin(), half_edges.end());
490 
491  unsigned number_of_edges = 1;
492  for(unsigned i=1; i<half_edges.size(); ++i)
493  {
494  if(half_edges[i] != half_edges[i-1])
495  {
496  ++number_of_edges;
497  }
498  else
499  {
500  if(i<half_edges.size()-1) //sanity check: there should be at most two equal half-edges
501  { //if it fails, most likely the input data are messed up
502  assert(half_edges[i] != half_edges[i+1]);
503  }
504  }
505  }
506 
507  // Edges->adjacent Vertices and Faces
508  m_edges.resize(number_of_edges);
509  unsigned edge_id = 0;
510  for(unsigned i=0; i<half_edges.size();)
511  {
512  Edge& e = m_edges[edge_id];
513  e.id() = edge_id++;
514 
515  e.adjacent_vertices().set_allocation(allocate_pointers(2),2); //allocate two units of memory
516 
517  e.adjacent_vertices()[0] = &m_vertices[half_edges[i].vertex_0];
518  e.adjacent_vertices()[1] = &m_vertices[half_edges[i].vertex_1];
519 
520  //ARN
521  vertex_pointer v1 = e.adjacent_vertices()[0];
522  vertex_pointer v2 = e.adjacent_vertices()[1];
523 
524  //cout << i << "v1 = " << v1->id() << " curv = " << curvature[v1->id()];;
525  //cout << " v2 = " << v2->id() << " curv = " << curvature[v2->id()] << endl;
526 
527 // if (curvature!= NULL)
528 // e.length() = (v1->distance(v2)*(fabs(curvature[v2->id()] - curvature[v1->id()])) ) ;
529 // else
530 // e.length() = e.adjacent_vertices()[0]->distance(e.adjacent_vertices()[1]);
531 //
532  double a1 = 0.0,a2 = 0.0;
533 
534  if (curvature!= NULL && mode != 0)
535  {
536  // Sulcal
537  if (mode == 1)
538  {
539  a1 = pow ((double)(1.0)/(1.0 + exp(-strain*curvature[v1->id()])), (double)sigmo);
540  a2 = pow ((double)(1.0)/(1.0 + exp(-strain*curvature[v2->id()])), (double)sigmo);
541  }
542 
543  // Gyral
544  if (mode == 2)
545  {
546  a1 = pow ((double)(1.0)/(1.0 + exp(strain*curvature[v1->id()])), (double)sigmo);
547  a2 = pow ((double)(1.0)/(1.0 + exp(strain*curvature[v2->id()])), (double)sigmo);
548  }
549 
550  e.length() = (v1->distance(v2) * (a1 + a2));
551  }
552  else
553  e.length() = e.adjacent_vertices()[0]->distance(e.adjacent_vertices()[1]);
554 
555  //assert(e.length() > 1e-100); //algorithm works well with non-degenerate meshes only
556 
557  if(i != half_edges.size()-1 && half_edges[i] == half_edges[i+1]) //double edge
558  {
559  e.adjacent_faces().set_allocation(allocate_pointers(2),2);
560  e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
561  e.adjacent_faces()[1] = &m_faces[half_edges[i+1].face_id];
562  i += 2;
563  }
564  else //single edge
565  {
566  e.adjacent_faces().set_allocation(allocate_pointers(1),1); //one adjucent faces
567  e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
568  i += 1;
569  }
570  }
571 
572  // Vertices->adjacent Edges
573  std::fill(count.begin(), count.end(), 0);
574  for(unsigned i=0; i<m_edges.size(); ++i)
575  {
576  Edge& e = m_edges[i];
577  assert(e.adjacent_vertices().size()==2);
578  count[e.adjacent_vertices()[0]->id()]++;
579  count[e.adjacent_vertices()[1]->id()]++;
580  }
581  for(unsigned i=0; i<m_vertices.size(); ++i)
582  {
583  m_vertices[i].adjacent_edges().set_allocation(allocate_pointers(count[i]),
584  count[i]);
585  }
586  std::fill(count.begin(), count.end(), 0);
587  for(unsigned i=0; i<m_edges.size(); ++i)
588  {
589  Edge& e = m_edges[i];
590  for(unsigned j=0; j<2; ++j)
591  {
593  v->adjacent_edges()[count[v->id()]++] = &e;
594  }
595  }
596 
597  // Faces->adjacent Edges
598  for(unsigned i=0; i<m_faces.size(); ++i)
599  {
600  m_faces[i].adjacent_edges().set_allocation(allocate_pointers(3),3);
601  }
602 
603  count.resize(m_faces.size());
604  std::fill(count.begin(), count.end(), 0);
605  for(unsigned i=0; i<m_edges.size(); ++i)
606  {
607  Edge& e = m_edges[i];
608  for(unsigned j=0; j<e.adjacent_faces().size(); ++j)
609  {
610  face_pointer f = e.adjacent_faces()[j];
611  assert(count[f->id()]<3);
612  f->adjacent_edges()[count[f->id()]++] = &e;
613  }
614  }
615 
616  //compute angles for the faces
617  for(unsigned i=0; i<m_faces.size(); ++i)
618  {
619  Face& f = m_faces[i];
620  double abc[3];
621  double sum = 0;
622  for(unsigned j=0; j<3; ++j) //compute angle adjacent to the vertex j
623  {
624  for(unsigned k=0; k<3; ++k)
625  {
626  vertex_pointer v = f.adjacent_vertices()[(j + k)%3];
627  abc[k] = f.opposite_edge(v)->length();
628  }
629 
630  double angle = angle_from_edges(abc[0], abc[1], abc[2]);
631 
632  //ARN
633  //assert(angle>1e-5); //algorithm works well with non-degenerate meshes only
634 
635  f.corner_angles()[j] = angle;
636  sum += angle;
637  }
638  //assert(std::abs(sum - M_PI) < 1e-5); //algorithm works well with non-degenerate meshes only
639  }
640 
641  //define m_turn_around_flag for vertices
642  std::vector<double> total_vertex_angle(m_vertices.size());
643  for(unsigned i=0; i<m_faces.size(); ++i)
644  {
645  Face& f = m_faces[i];
646  for(unsigned j=0; j<3; ++j)
647  {
649  total_vertex_angle[v->id()] += f.corner_angles()[j];
650  }
651  }
652 
653  for(unsigned i=0; i<m_vertices.size(); ++i)
654  {
655  Vertex& v = m_vertices[i];
656  v.saddle_or_boundary() = (total_vertex_angle[v.id()] > 2.0*M_PI - 1e-5);
657  }
658 
659  for(unsigned i=0; i<m_edges.size(); ++i)
660  {
661  Edge& e = m_edges[i];
662  if(e.is_boundary())
663  {
664  e.adjacent_vertices()[0]->saddle_or_boundary() = true;
665  e.adjacent_vertices()[1]->saddle_or_boundary() = true;
666  }
667  }
668 
669  //assert(verify());
670  //assert(verify());
671 }
672 inline bool Mesh::verify() //verifies connectivity of the mesh and prints some debug info
673 {
674  std::cout << std::endl;
675  // make sure that all vertices are mentioned at least once.
676  // though the loose vertex is not a bug, it most likely indicates that something is wrong with the mesh
677  std::vector<bool> map(m_vertices.size(), false);
678  for(unsigned i=0; i<m_edges.size(); ++i)
679  {
680  edge_pointer e = &m_edges[i];
681  map[e->adjacent_vertices()[0]->id()] = true;
682  map[e->adjacent_vertices()[1]->id()] = true;
683  }
684  assert(std::find(map.begin(), map.end(), false) == map.end());
685 
686  //make sure that the mesh is connected trough its edges
687  //if mesh has more than one connected component, it is most likely a bug
688  std::vector<face_pointer> stack(1,&m_faces[0]);
689  stack.reserve(m_faces.size());
690 
691  map.resize(m_faces.size());
692  std::fill(map.begin(), map.end(), false);
693  map[0] = true;
694 
695  while(!stack.empty())
696  {
697  face_pointer f = stack.back();
698  stack.pop_back();
699 
700  for(unsigned i=0; i<3; ++i)
701  {
702  edge_pointer e = f->adjacent_edges()[i];
703  face_pointer f_adjacent = e->opposite_face(f);
704  if(f_adjacent && !map[f_adjacent->id()])
705  {
706  map[f_adjacent->id()] = true;
707  stack.push_back(f_adjacent);
708  }
709  }
710  }
711  assert(std::find(map.begin(), map.end(), false) == map.end());
712 
713  //print some mesh statistics that can be useful in debugging
714  std::cout << "mesh has " << m_vertices.size()
715  << " vertices, " << m_faces.size()
716  << " faces, " << m_edges.size()
717  << " edges\n";
718 
719  unsigned total_boundary_edges = 0;
720  double longest_edge = 0;
721  double shortest_edge = 1e100;
722  for(unsigned i=0; i<m_edges.size(); ++i)
723  {
724  Edge& e = m_edges[i];
725  total_boundary_edges += e.is_boundary() ? 1 : 0;
726  longest_edge = std::max(longest_edge, e.length());
727  shortest_edge = std::min(shortest_edge, e.length());
728  }
729  std::cout << total_boundary_edges << " edges are boundary edges\n";
730  std::cout << "shortest/longest edges are "
731  << shortest_edge << "/"
732  << longest_edge << " = "
733  << shortest_edge/longest_edge
734  << std::endl;
735 
736  double minx = 1e100;
737  double maxx = -1e100;
738  double miny = 1e100;
739  double maxy = -1e100;
740  double minz = 1e100;
741  double maxz = -1e100;
742  for(unsigned i=0; i<m_vertices.size(); ++i)
743  {
744  Vertex& v = m_vertices[i];
745  minx = std::min(minx, v.x());
746  maxx = std::max(maxx, v.x());
747  miny = std::min(miny, v.y());
748  maxy = std::max(maxy, v.y());
749  minz = std::min(minz, v.z());
750  maxz = std::max(maxz, v.z());
751  }
752  std::cout << "enclosing XYZ box:"
753  <<" X[" << minx << "," << maxx << "]"
754  <<" Y[" << miny << "," << maxy << "]"
755  <<" Z[" << minz << "," << maxz << "]"
756  << std::endl;
757 
758  double dx = maxx - minx;
759  double dy = maxy - miny;
760  double dz = maxz - minz;
761  std::cout << "approximate diameter of the mesh is "
762  << sqrt(dx*dx + dy*dy + dz*dz)
763  << std::endl;
764 
765  double min_angle = 1e100;
766  double max_angle = -1e100;
767  for(unsigned i=0; i<m_faces.size(); ++i)
768  {
769  Face& f = m_faces[i];
770  for(unsigned j=0; j<3; ++j)
771  {
772  double angle = f.corner_angles()[j];
773  min_angle = std::min(min_angle, angle);
774  max_angle = std::max(max_angle, angle);
775  }
776  }
777  std::cout << "min/max face angles are "
778  << min_angle/M_PI*180.0 << "/"
779  << max_angle/M_PI*180.0
780  << " degrees\n";
781 
782  std::cout << std::endl;
783  return true;
784 }
785 
787  double* data,
788  Mesh* mesh)
789 {
790  point->set(data);
791  unsigned type = (unsigned) data[3];
792  unsigned id = (unsigned) data[4];
793 
794 
795  if(type == 0) //vertex
796  {
797  point->base_element() = &mesh->vertices()[id];
798  }
799  else if(type == 1) //edge
800  {
801  point->base_element() = &mesh->edges()[id];
802  }
803  else //face
804  {
805  point->base_element() = &mesh->faces()[id];
806  }
807 }
808 
810  double* data,
811  long /*mesh_id*/)
812 {
813  data[0] = point->x();
814  data[1] = point->y();
815  data[2] = point->z();
816  data[4] = point->base_element()->id();
817 
818  if(point->type() == VERTEX) //vertex
819  {
820  data[3] = 0;
821  }
822  else if(point->type() == EDGE) //edge
823  {
824  data[3] = 1;
825  }
826  else //face
827  {
828  data[3] = 2;
829  }
830 }
831 
832 } //geodesic
833 
834 #endif
vertex_pointer opposite_vertex(edge_pointer e)
edge_pointer opposite_edge(vertex_pointer v)
vertex_pointer_vector & adjacent_vertices()
edge_pointer_vector & adjacent_edges()
face_pointer_vector & adjacent_faces()
void update_weight(const float *curvature, int mode, double strain, double sigmo)
void initialize_mesh_data(unsigned num_vertices, Points &p, unsigned num_faces, Faces &tri, const float *curvature, int mode, int strain)
std::vector< Edge > & edges()
Definition: geodesic_mesh.h:44
std::vector< Vertex > & vertices()
Definition: geodesic_mesh.h:43
unsigned closest_vertices(SurfacePoint *p, std::vector< vertex_pointer > *storage=NULL)
Definition: geodesic_mesh.h:68
std::vector< Face > & faces()
Definition: geodesic_mesh.h:45
void set(double new_x, double new_y, double new_z)
double distance(double *v)
pointer allocate(unsigned const n)
void reset(unsigned block_size, unsigned max_number_of_blocks)
void set_allocation(DataPointer begin, unsigned size)
float min(float x, float y)
Definition: thickness.h:106
float max(float x, float y)
Definition: thickness.h:98
DataTypeTraits< T >::LongType sum(const Volume< T > &vol)
void fill_surface_point_structure(geodesic::SurfacePoint *point, double *data, Mesh *mesh)
double angle_from_edges(double const a, double const b, double const c)
void fill_surface_point_double(geodesic::SurfacePoint *point, double *data, long)
Vertex * vertex_pointer