aimsalgo 6.0.0
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
13#include "geodesic_memory.h"
15
16namespace geodesic{
17
23
24class Mesh
25{
26public:
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
48 std::vector<vertex_pointer>* storage = NULL); //list vertices closest to the point
49
50private:
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
114template<class Points, class Faces>
115void 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
125template<class Points, class Faces>
126void 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
182inline 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
436inline 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
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}
672inline 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)
edge_pointer_vector & adjacent_edges()
vertex_pointer_vector & adjacent_vertices()
face_pointer_vector & adjacent_faces()
std::vector< Edge > & edges()
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< Face > & faces()
std::vector< Vertex > & vertices()
unsigned closest_vertices(SurfacePoint *p, std::vector< vertex_pointer > *storage=NULL)
void set(double new_x, double new_y, double new_z)
double distance(double *v)
pointer allocate(unsigned const n)
void set_allocation(DataPointer begin, unsigned size)
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