MEPP2 Project
AIFTopologyHelpers.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 // Warning: do NOT include this file outside of AIFMesh.hpp
14 
15 #include <boost/range/iterator_range.hpp>
16 #include <exception>
17 #include <utility>
18 #include <algorithm>
19 #include <stack>
20 #include <iostream>
21 #include <type_traits>
22 
24 
25 // The helpers functions are in 4 sections : vertex, edge, face, mesh. The
26 // functions are set in a section if the main parameter (thus the first)
27 // correspond to the section. eg : vertex_position(edge, vertex) for the
28 // position, V1 or V2, in an edge -> in the edge section.
29 
30 // For the moment, only link_... and unlink_... functions realize topological
31 // changes (and it should stay like this until a really good reason) This
32 // statement certify that the topological caching (one ring, adjacency
33 // relations, ...) need to be delete only in these functions (the delete
34 // is actually realize by the private add_... and remove_... functions that
35 // are called)
36 
37 // The topological caching is not yet refactored -> no one ring, adjacency
38 // relations, ... for now, at least with caching scheme
39 
40 // For the moment, functions with no topological change use the static
41 // incident_...(vertex/edge/face) to get the incident relations whereas, the
42 // functions including topological changes use the non-const
43 // vertex/edge/face.Getincident...() functions
44 
45 namespace FEVV {
46 namespace DataStructures {
47 namespace AIF {
48 
57 {
58 public:
59  typedef AIFMesh mesh_type;
63 
66  typedef mesh_type *ptr_mesh;
67  typedef const mesh_type *ptr_cmesh;
68  typedef mesh_type &ref_mesh;
69  typedef typename std::add_lvalue_reference< const mesh_type >::type ref_cmesh;
73 
86 
87  typedef unsigned int size_type;
88 
89  typedef edge_container_in_vertex::const_iterator out_edge_iterator;
90  typedef edge_container_in_vertex::size_type degree_size_type;
91 
92  typedef vertex_container_in_vertex::const_iterator adjacency_iterator;
93 
94  typedef edge_container_in_face::iterator incident_edge_iterator;
95  typedef face_container_in_edge::iterator incident_face_iterator;
96 
97  typedef edge_container_in_face::const_iterator const_incident_edge_iterator;
98  typedef face_container_in_edge::const_iterator const_incident_face_iterator;
99 
110 
111  // nulls
115 
116 public:
119 
128  {
129  if(vertex == null_vertex())
130  return true;
131 
132  auto eRange = incident_edges(vertex);
133  for(auto eIt = eRange.begin(); eIt != eRange.end(); ++eIt)
134  {
135  if(*eIt == null_edge() ||
136  (*eIt)->get_first_vertex() == (*eIt)->get_second_vertex())
137  return true;
138  }
139 
140  return false;
141  }
142 
149  {
150  return vertex->GetDegree();
151  }
160  {
161  return vertex->GetDegree() == 0u;
162  }
173  static bool is_cut_vertex(vertex_descriptor vertex)
174  {
175  typedef edge_container_in_vertex::const_iterator it_type;
176  int nbBoundaryEdges = 0;
177  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
178 
179  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
180  {
181  if(is_surface_border_edge(*it))
182  nbBoundaryEdges++;
183  }
184 
185  if((nbBoundaryEdges < 4) || (nbBoundaryEdges % 2 == 1))
186  return false;
187  else
188  return ((nbBoundaryEdges - 4) % 2 == 0);
189  }
190 
200  {
201  auto incidentEdgesRange = incident_edges(vertex);
202  auto it = incidentEdgesRange.begin();
203  auto ite = incidentEdgesRange.end();
204  for(; it != ite; ++it)
205  {
206  if(is_complex_edge(*it) || is_dangling_edge(*it))
207  return true;
208  }
209  return false;
210  }
211 
221  {
223  return false;
224 
225  return true;
226  }
227 
238  {
239  if(is_degenerated_vertex(vertex) || is_isolated_vertex(vertex) ||
240  is_cut_vertex(vertex))
241  return false;
242 
243  auto incidentEdgesRange = incident_edges(vertex);
244  auto it = incidentEdgesRange.begin();
245  auto ite = incidentEdgesRange.end();
246  for(; it != ite; ++it)
247  {
248  if(is_degenerated_edge(*it) || is_isolated_edge(*it) ||
249  is_dangling_edge(*it) || is_complex_edge(*it))
250  return false;
251  }
252 
253  return true;
254  }
255 
265  {
266  if(is_isolated_vertex(vertex))
267  return false;
268 
269  typedef edge_container_in_vertex::const_iterator it_type;
270  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
271 
272  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
273  {
274  if(is_surface_border_edge(*it))
275  return true;
276  }
277  return false;
278  }
289  {
290  return !is_surface_border_vertex(vertex) && !is_isolated_vertex(vertex);
291  }
304  {
305  if(vertex == null_vertex())
306  return false;
307  typedef edge_container_in_vertex::const_iterator it_type;
308  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
309 
310  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
311  {
312  if(*it == edge)
313  return true;
314  }
315  return false;
316  }
327  static bool are_incident(vertex_descriptor vertex,
330  {
331  if(vertex == null_vertex())
332  return false;
333 
335  if(edge != null_edge())
336  {
337  typedef edge_container_in_vertex::const_iterator it_type;
338  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
339 
340  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
341  {
342  if(*it == edge)
343  return true;
344  }
345  }
346  return false;
347  }
358  static bool are_adjacent(vertex_descriptor vertex1, vertex_descriptor vertex2)
359  {
360  typedef edge_container_in_vertex::const_iterator it_type;
361  boost::iterator_range< it_type > edges_range = incident_edges(vertex1);
362 
363  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
364  {
365  if(opposite_vertex(*it, vertex1) == vertex2)
366  return true;
367  }
368  return false;
369  }
376  static std::vector< vertex_descriptor >
378  {
379  std::vector< vertex_descriptor > adjacent_v;
380 
381  auto incidentEdgesRange = incident_edges(vertex);
382  adjacent_v.reserve(incidentEdgesRange.size());
383  auto it = incidentEdgesRange.begin();
384  auto ite = incidentEdgesRange.end();
385  for (; it != ite; ++it)
386  {
387  adjacent_v.push_back(opposite_vertex(*it, vertex));
388  }
389 
390  return adjacent_v;
391  }
398  static boost::iterator_range< edge_container_in_vertex::const_iterator >
400  {
401  if(vertex == null_vertex())
402  throw std::invalid_argument(
403  "AIFTopologyHelpers::incident_edges -> no incident relation exists "
404  "for a null vertex.");
405 
406  return vertex->GetIncidentEdges();
407  }
414  static boost::iterator_range< face_container_in_vertex::const_iterator >
416  {
417  if(!vertex->m_Incident_PtrFaces_Computed)
418  {
419  typedef edge_container_in_vertex::const_iterator it_type;
420  typedef face_container_in_edge::const_iterator it_type2;
421 
422  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
423 
424  std::set< face_descriptor > incFaces;
425 
426  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
427  {
428  boost::iterator_range< it_type2 > faces_range =
429  incident_faces(*it); // get all incident faces of current edge
430  incFaces.insert(faces_range.begin(), faces_range.end());
431  }
432  face_container_in_vertex common_faces(incFaces.begin(), incFaces.end());
433  vertex->m_Incident_PtrFaces = common_faces;
434  vertex->m_Incident_PtrFaces_Computed = true;
435  }
436  return boost::make_iterator_range(vertex->m_Incident_PtrFaces.cbegin(),
437  vertex->m_Incident_PtrFaces.cend());
438  }
447  {
448  incident_faces(vertex); // update calculus
449  return face_container_in_vertex(vertex->m_Incident_PtrFaces.cbegin(),
450  vertex->m_Incident_PtrFaces.cend());
451  }
459  vertex_descriptor vertex2)
460  {
461  typedef edge_container_in_vertex::const_iterator it_type;
462  // if (vertex1 == null_vertex() || vertex2 == null_vertex())
463  // return null_edge();
464  boost::iterator_range< it_type > edges_range = incident_edges(
465  vertex1); // we need to use the first vertex (the source in concept!!)
466 
467 
468  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
469  {
470  if(opposite_vertex(*it, vertex1) == vertex2)
471  return *it;
472  }
473  return null_edge();
474  }
482  static std::vector< edge_descriptor > common_edges(vertex_descriptor vertex1,
483  vertex_descriptor vertex2)
484  {
485  typedef edge_container_in_vertex::const_iterator it_type;
486  std::vector< edge_descriptor > com_edges;
487  boost::iterator_range< it_type > edges_range = incident_edges(vertex1);
488 
489  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
490  {
491  if(opposite_vertex(*it, vertex1) == vertex2)
492  com_edges.push_back(*it);
493  }
494  return com_edges;
495  }
517  vertex_pos position)
518  {
519  if(!are_incident(vertex, edge))
520  {
521  add_vertex_to_edge(edge, vertex, position);
522  add_edge_to_vertex(vertex, edge);
523  }
524  else
525  throw std::invalid_argument(
526  "AIFTopologyHelpers::link_vertex_and_edge -> incident relation "
527  "already exists between the two elements.");
528  }
529 
546  {
547  bool edge_has_that_incident_vertex = are_incident(edge, vertex);
548  bool vertex_has_that_incident_edge = are_incident(vertex, edge);
549 
550  if(!edge_has_that_incident_vertex && !vertex_has_that_incident_edge)
551  throw std::invalid_argument(
552  "AIFTopologyHelpers::unlink_vertex_and_edge -> no incident relation "
553  "existing between the two elements.");
554 
555  if(edge_has_that_incident_vertex)
556  {
557  remove_vertex_from_edge(edge, vertex);
558  }
559 
560  if(vertex_has_that_incident_edge)
561  {
562  remove_edge_from_vertex(vertex, edge);
563  }
564  }
565 
574  template< typename ComparatorType >
575  static boost::iterator_range< vertex_container::const_iterator >
576  sort_vertices(ptr_mesh mesh, const ComparatorType &cmp)
577  {
578  sort(mesh->GetVertices().begin(),
579  mesh->GetVertices().end(),
580  cmp);
581  return mesh->GetVertices();
582  }
583 
592  template< typename ComparatorType >
593  static boost::iterator_range< vertex_container::const_iterator >
594  sort_vertices(smart_ptr_mesh mesh, const ComparatorType &cmp)
595  {
596  return sort_vertices< ComparatorType >(mesh.get(), cmp);
597  }
598 
607  template< typename ComparatorType >
608  static boost::iterator_range< vertex_container::const_iterator >
609  sort_vertices(ref_mesh mesh, const ComparatorType &cmp)
610  {
611  return sort_vertices< ComparatorType >(&mesh, cmp);
612  }
628  template< typename ComparatorType >
629  static boost::iterator_range< edge_container_in_vertex::const_iterator >
631  const ComparatorType &cmp,
633  bool do_full_incident_edge_sorting)
634  {
635  if(do_full_incident_edge_sorting)
636  {
637  sort(vertex->m_Incident_PtrEdges.begin(),
638  vertex->m_Incident_PtrEdges.end(),
639  cmp); // possible break of clockwise ordering (but no matter since
640  // usual order is insertion order)
641  }
643  std::list< edge_descriptor > ltmp, ltmpnext;
644  edge_container_in_vertex::const_iterator
645  it = vertex->m_Incident_PtrEdges.begin(),
646  ite = vertex->m_Incident_PtrEdges.end();
647  while(it != ite && *it != edge)
648  {
649  ltmpnext.push_back(*it);
650  ++it;
651  }
652  if(it == ite)
653  { // starting edge not found, do nothing
654  return incident_edges(vertex);
655  }
656  while(it != ite)
657  {
658  ltmp.push_back(*it);
659  ++it;
660  }
662  vertex->m_Incident_PtrEdges.clear();
663  vertex->m_Incident_PtrEdges.insert(
664  vertex->m_Incident_PtrEdges.end(), ltmp.begin(), ltmp.end());
665  vertex->m_Incident_PtrEdges.insert(
666  vertex->m_Incident_PtrEdges.end(), ltmpnext.begin(), ltmpnext.end());
668  return incident_edges(vertex);
669  }
670 
684  template< typename ComparatorType >
685  static boost::iterator_range< edge_container_in_vertex::const_iterator >
687  const ComparatorType &cmp,
688  bool do_full_incident_edge_sorting)
689  {
690 
691  return sort_incident_edges_starting_with_edge< ComparatorType >(
692  vertex,
693  cmp,
694  *std::min_element(vertex->m_Incident_PtrEdges.begin(),
695  vertex->m_Incident_PtrEdges.end(),
696  cmp),
697  do_full_incident_edge_sorting);
698  }
699 
710  template< typename ComparatorType >
712  const ComparatorType &cmp,
713  bool do_full_incident_edge_sorting)
714  {
715  sort_incident_edges< ComparatorType >(
716  edge->get_first_vertex(), cmp, do_full_incident_edge_sorting);
717  sort_incident_edges< ComparatorType >(
718  edge->get_second_vertex(), cmp, do_full_incident_edge_sorting);
719  }
720 
729  template< typename ComparatorType >
731  const ComparatorType &cmp)
732  {
733  typedef edge_container_in_vertex::const_iterator it_type;
734  boost::iterator_range< it_type > edges_range =
735  incident_edges(edge->get_first_vertex());
736  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
737  sort_incident_edges< ComparatorType >(
738  opposite_vertex(*it, edge->get_first_vertex()), cmp);
739 
740  edges_range = incident_edges(edge->get_second_vertex());
741  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
742  sort_incident_edges< ComparatorType >(
743  opposite_vertex(*it, edge->get_second_vertex()), cmp);
744  }
745 
746 
754  static std::vector< edge_descriptor >
756  {
757  std::vector< edge_descriptor > res;
758  if(is_isolated_vertex(vertex))
759  return res;
760 
761  typedef edge_container_in_vertex::const_iterator it_type;
762  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
763 
764  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
765  {
766  if((is_surface_border_edge(*it) &&
767  (degree((*it)->get_first_vertex()) > 2) &&
768  (degree((*it)->get_second_vertex()) > 2)) ||
769  (is_dangling_edge(*it) && (degree((*it)->get_first_vertex()) >= 2) &&
770  (degree((*it)->get_second_vertex()) >= 2)))
771  res.push_back(*it);
772  }
773  if(res.size() == 1)
774  {
775  std::vector< edge_descriptor > res_init(res.begin(), res.end());
776  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
777  {
778  if(std::find(res_init.begin(), res_init.end(), *it) == res_init.end())
779  {
780  auto iter = res_init.begin();
781  for(; iter != res_init.end(); ++iter)
782  {
783  if(are_adjacent(opposite_vertex(*it, vertex),
784  opposite_vertex(*iter, vertex)))
785  {
786  res.push_back(*it);
787  break;
788  }
789  }
790  }
791  }
792  }
793  return res;
794  }
795 
804  static std::vector< edge_descriptor >
806  edge_descriptor edge_to_remove)
807  {
808  std::vector< edge_descriptor > res = get_incident_hole_border_edges(vertex);
809 
810  auto iter = std::find(res.begin(), res.end(), edge_to_remove);
811  if(iter != res.end())
812  res.erase(iter);
813 
814  return res;
815  }
816 
825  {
826  typedef edge_container_in_vertex::const_iterator it_type;
827 
828  boost::iterator_range< it_type > edges_range = incident_edges(
829  vertex); // we need to use the first vertex (the source in concept!!)
830 
831  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
832  {
833  if(are_incident(face, *it))
834  return *it;
835  }
836  return null_edge();
837  }
838 
849  edge_descriptor not_that_edge)
850  {
851  typedef edge_container_in_vertex::const_iterator it_type;
852 
853  boost::iterator_range< it_type > edges_range = incident_edges(
854  vertex); // we need to use the first vertex (the source in concept!!)
855 
856  for(it_type it = edges_range.begin(); it != edges_range.end(); ++it)
857  {
858  if(are_incident(face, *it) && (*it != not_that_edge))
859  return *it;
860  }
861  return null_edge();
862  }
874  static bool
876  face_descriptor face1,
877  face_descriptor face2)
878  {
879  if(!are_incident(vertex, face1) || !are_incident(vertex, face2))
880  return false;
881 
882  auto face_range = incident_faces(vertex);
883  std::set< face_descriptor > current_faces(face_range.begin(),
884  face_range.end());
885 
886  edge_descriptor e1 = common_edge(vertex, face1);
887  edge_descriptor e2 = common_edge(vertex, face1, e1);
888  if((e1 == null_edge()) && (e2 == null_edge()))
889  return false;
890  if(are_incident(face2, e1) || are_incident(face2, e2))
891  return true;
892  face_descriptor current_f_tmp = face1;
893  while((e1 != null_edge()) && (degree(e1) == 2) &&
894  (current_faces.find(current_f_tmp) != current_faces.end()))
895  {
896  auto face_range2 = incident_faces(e1);
897  auto it_f2 = face_range2.begin();
898  for(; it_f2 != face_range2.end(); ++it_f2)
899  {
900  if(*it_f2 != current_f_tmp)
901  {
902  current_faces.erase(current_f_tmp);
903  current_f_tmp = *it_f2;
904  e1 = common_edge(vertex, current_f_tmp, e1);
905  if(are_incident(face2, e1))
906  return true;
907  break;
908  }
909  }
910  }
911  if(current_f_tmp != face1)
912  current_faces.erase(current_f_tmp);
913  if(degree(e2) == 2)
914  current_faces.insert(face1);
915  while((e2 != null_edge()) && (degree(e2) == 2) &&
916  (current_faces.find(face1) != current_faces.end()))
917  {
918  auto face_range2 = incident_faces(e2);
919  auto it_f2 = face_range2.begin();
920  for(; it_f2 != face_range2.end(); ++it_f2)
921  {
922  if(*it_f2 != face1)
923  {
924  current_faces.erase(face1);
925  face1 = *it_f2;
926  e2 = common_edge(vertex, face1, e2);
927  if(are_incident(face2, e2))
928  return true;
929  break;
930  }
931  }
932  }
933  return false;
934  }
937 
942  static size_type degree(edge_descriptor edge) { return edge->GetDegree(); }
950  {
951  return degree(edge) == 1;
952  }
961  {
962  return degree(edge) == 2;
963  }
972  {
974  }
983  {
986  else
988  }
996  {
997  return (edge->get_first_vertex()->GetDegree() == 1u) &&
998  (edge->get_second_vertex()->GetDegree() == 1u);
999  }
1000 
1010  {
1011  return (edge->GetDegree() == 0u) && !is_isolated_edge(edge);
1012  }
1023  {
1024  return edge->GetDegree() > 2u;
1025  }
1035  {
1036  return (edge == null_edge()) // a null edge is degenerated
1037  || (edge->get_first_vertex() == edge->get_second_vertex()) // null-length edge are
1038  // degenereated, thus edge with 2
1039  // identical vertices are too.
1040  || (edge->get_first_vertex() == null_vertex())
1041  || (edge->get_second_vertex() == null_vertex());
1042  }
1043 
1056  edge_descriptor edge2)
1057  {
1058  if(edge1 == edge2)
1059  throw std::invalid_argument("AIFTopologyHelpers::common_vertex -> the 2 "
1060  "edge arguments are identical.");
1061 
1062  if((edge1->get_first_vertex() == edge2->get_first_vertex()) ||
1063  (edge1->get_first_vertex() == edge2->get_second_vertex()))
1064  {
1065  return edge1->get_first_vertex();
1066  }
1067  else if((edge1->get_second_vertex() == edge2->get_first_vertex()) ||
1068  (edge1->get_second_vertex() == edge2->get_second_vertex()))
1069  return edge1->get_second_vertex();
1070 
1071  return null_vertex();
1072  }
1073 
1080  {
1081  size_type cpt = 0;
1082  auto edges_range = incident_edges(vertex);
1083  auto iterE = edges_range.begin();
1084  for(; iterE != edges_range.end(); ++iterE)
1085  {
1086  if(is_dangling_edge(*iterE))
1087  ++cpt;
1088  }
1089  return cpt;
1090  }
1099  {
1100  return (num_incident_dangling_edge(vertex) > 0);
1101  }
1102 
1110  {
1111  edge_descriptor de = null_edge();
1112  auto edges_range = incident_edges(vertex);
1113  auto iterE = edges_range.begin();
1114  for(; iterE != edges_range.end(); ++iterE)
1115  {
1116  if(is_dangling_edge(*iterE))
1117  {
1118  de = *iterE;
1119  break;
1120  }
1121  }
1122  return de;
1123  }
1135  {
1136  if(edge == null_edge())
1137  return false;
1138  return (edge->get_first_vertex() == vertex) ||
1139  (edge->get_second_vertex() == vertex);
1140  }
1152  {
1153  if(edge == null_edge())
1154  return false;
1155  typedef face_container_in_edge::const_iterator it_type;
1156  boost::iterator_range< it_type > faces_range = incident_faces(edge);
1157 
1158  for(it_type it = faces_range.begin(); it != faces_range.end(); ++it)
1159  {
1160  if(*it == face)
1161  return true;
1162  }
1163  return false;
1164  }
1175  {
1176  if(edge1 == edge2)
1177  return false;
1178  return are_incident(edge2, edge1->get_first_vertex()) ||
1179  are_incident(edge2, edge1->get_second_vertex());
1180  }
1181 
1188  static boost::iterator_range< vertex_container_in_edge::const_iterator >
1190  { // Return type can't be iterator_range type cause vertex_container_in_edge
1191  // is an std::pair
1192  if(edge == null_edge())
1193  throw std::invalid_argument("AIFTopologyHelpers::incident_vertices -> no "
1194  "incident relation exists for a null edge.");
1195  return edge->GetIncidentVertices();
1196  }
1203  static std::vector< edge_descriptor > adjacent_edges(edge_descriptor edge)
1204  {
1205  std::vector< edge_descriptor > adEdges1(
1206  edge->get_first_vertex()->GetIncidentEdges().begin(),
1207  edge->get_first_vertex()->GetIncidentEdges().end());
1208  std::vector< edge_descriptor > adEdges2(
1209  edge->get_second_vertex()->GetIncidentEdges().begin(),
1210  edge->get_second_vertex()->GetIncidentEdges().end());
1211 
1212  std::vector< edge_descriptor > res(edge->get_first_vertex()->GetDegree() +
1213  edge->get_second_vertex()->GetDegree() -
1214  2);
1215 
1216  std::sort(adEdges1.begin(), adEdges1.end());
1217  std::sort(adEdges2.begin(), adEdges2.end());
1218  adEdges1.erase(std::find(adEdges1.begin(), adEdges1.end(), edge));
1219  adEdges2.erase(std::find(adEdges2.begin(), adEdges2.end(), edge));
1220 
1221  std::set_union(adEdges1.begin(),
1222  adEdges1.end(),
1223  adEdges2.begin(),
1224  adEdges2.end(),
1225  res.begin());
1226 
1227  return res; // note that it is a non-sens to manage a memory caching as
1228  // adjacent edges can be quickly computed
1229  }
1236  static boost::iterator_range< incident_face_iterator >
1238  {
1239  if(edge == null_edge())
1240  throw std::invalid_argument("AIFTopologyHelpers::incident_faces -> no "
1241  "incident relation exists for a null edge.");
1242 
1243  return edge->GetIncidentFaces();
1244  }
1253  vertex_descriptor vertex)
1254  {
1255  if(edge->get_first_vertex() == vertex)
1256  return vertex_pos::FIRST;
1257  else if(edge->get_second_vertex() == vertex)
1258  return vertex_pos::SECOND;
1259  else
1260  throw std::invalid_argument(
1261  "AIFTopologyHelpers::vertex_position -> given vertex not found.");
1262  }
1271  vertex_descriptor vertex)
1272  {
1273  if(edge->get_first_vertex() == vertex)
1274  return edge->get_second_vertex();
1275  else if(edge->get_second_vertex() == vertex)
1276  return edge->get_first_vertex();
1277  else
1278  throw std::invalid_argument(
1279  "AIFTopologyHelpers::opposite_vertex -> given vertex not found.");
1280  }
1287  { // No std::swap cause get_first_vertex is a const function
1288  vertex_descriptor v_temp = edge->get_first_vertex();
1289  edge->set_first_vertex(edge->get_second_vertex());
1290  edge->set_second_vertex(v_temp);
1291  }
1306  {
1307  bool face_has_that_incident_edge = are_incident(face, edge);
1308  bool edge_has_that_incident_face = are_incident(edge, face);
1309 
1310  if(!face_has_that_incident_edge || !edge_has_that_incident_face)
1311  {
1312  if(!face_has_that_incident_edge)
1314  if(!edge_has_that_incident_face)
1316  }
1317  else
1318  throw std::invalid_argument(
1319  "AIFTopologyHelpers::link_edge_and_face -> incident relation already "
1320  "exists between the two elements.");
1321  }
1322 
1338  static void
1341  edge_descriptor prev_edge)
1342  {
1343  bool face_has_that_incident_edge = are_incident(face, edge);
1344  bool edge_has_that_incident_face = are_incident(edge, face);
1345 
1346  if(!face_has_that_incident_edge || !edge_has_that_incident_face)
1347  {
1348  if(!face_has_that_incident_edge)
1349  add_edge_to_face_after_edge(face, prev_edge, edge);
1350  if(!edge_has_that_incident_face)
1352  }
1353  else
1354  throw std::invalid_argument(
1355  "AIFTopologyHelpers::link_edge_and_face_around_face_after_edge -> "
1356  "incident relation already "
1357  "exists between the two elements.");
1358  }
1359 
1377  std::vector< edge_descriptor > &edges,
1379  edge_descriptor prev_edge)
1380  {
1381  edge_descriptor current_edge;
1382  std::vector< edge_descriptor >::iterator it(edges.begin()),
1383  ite(edges.end());
1384  for(; it != ite; ++it)
1385  {
1386  edge_descriptor current_edge = *it;
1387  link_edge_and_face_around_face_after_edge(current_edge, face, prev_edge);
1388  prev_edge = current_edge;
1389  }
1390  }
1391 
1392 
1399  {
1400  bool face_has_that_incident_edge = are_incident(face, edge);
1401  bool edge_has_that_incident_face = are_incident(edge, face);
1402 
1403  if(!face_has_that_incident_edge && !edge_has_that_incident_face)
1404  throw std::invalid_argument(
1405  "AIFTopologyHelpers::unlink_edge_and_face -> no incident relation "
1406  "existing between the two elements.");
1407 
1408  if(edge_has_that_incident_face)
1409  {
1411  }
1412 
1413  if(face_has_that_incident_edge)
1414  {
1416  }
1417  }
1423  static void unlink_edges_and_face(std::vector< edge_descriptor > edges,
1425  {
1426  std::vector< edge_descriptor >::iterator it(edges.begin()),
1427  ite(edges.end());
1428  for(; it != ite; ++it)
1429  unlink_edge_and_face(*it, face);
1430  }
1431 
1442  {
1444  return false;
1445 
1446  return is_2_manifold_vertex(edge->get_first_vertex()) &&
1447  is_2_manifold_vertex(edge->get_second_vertex());
1448  }
1449 
1457  template< typename ComparatorType >
1458  static boost::iterator_range< edge_container::const_iterator >
1459  sort_edges(ptr_mesh mesh, const ComparatorType &cmp)
1460  {
1461  sort(mesh->GetEdges().begin(),
1462  mesh->GetEdges().end(),
1463  cmp); // here std::sort is not ok (issue detected in some code)
1464  return mesh->GetEdges();
1465  }
1466 
1474  template< typename ComparatorType >
1475  static boost::iterator_range< edge_container::const_iterator >
1476  sort_edges(smart_ptr_mesh mesh, const ComparatorType &cmp)
1477  {
1478  return sort_edges< ComparatorType >(mesh.get(), cmp);
1479  }
1480 
1488  template< typename ComparatorType >
1489  static boost::iterator_range< edge_container::const_iterator >
1490  sort_edges(ref_mesh mesh, const ComparatorType &cmp)
1491  {
1492  return sort_edges< ComparatorType >(&mesh, cmp);
1493  }
1496 
1501  static size_type degree(face_descriptor face) { return face->GetDegree(); }
1502 
1512  {
1513  auto edges_range = incident_edges(face);
1514  auto it = edges_range.begin();
1515  for(; it != edges_range.end(); ++it)
1516  {
1517  if((degree((*it)->get_first_vertex()) > 2) ||
1518  (degree((*it)->get_second_vertex()) > 2))
1519  return false;
1520  }
1521  return true;
1522  }
1531  {
1532  if((face == null_face()) || // a null face is degenerated
1533  (degree(face) <
1534  3) // a face with degree strictly less than 3 is degenerated
1535  )
1536  return true;
1537  auto eRange = incident_edges(face);
1538  edge_descriptor last = null_edge();
1539  for(auto eIt = eRange.begin(); eIt != eRange.end(); ++eIt)
1540  {
1541  if (last == *eIt)
1542  return true; // 2 consecutive identical edges
1543 
1544  if(is_degenerated_edge(*eIt))
1545  return true;
1546 
1547  last = *eIt;
1548  }
1549  return false;
1550  }
1551 
1562  {
1564  return false;
1565 
1566  auto edges_range = incident_edges(face);
1567  auto it = edges_range.begin();
1568  for(; it != edges_range.end(); ++it)
1569  {
1570  if(!is_2_manifold_edge(*it))
1571  return false;
1572  }
1573  return true;
1574  }
1575 
1583  {
1584  bool at_least_one_vertex_with_degree_greater_than_2 = false;
1585  auto edges_range = incident_edges(face);
1586  auto it = edges_range.begin();
1587  for(; it != edges_range.end(); ++it)
1588  {
1589  if(degree(*it) > 1)
1590  return false;
1591  if(!at_least_one_vertex_with_degree_greater_than_2 &&
1592  ((degree((*it)->get_first_vertex()) > 2) ||
1593  (degree((*it)->get_second_vertex()) > 2)))
1594  at_least_one_vertex_with_degree_greater_than_2 = true;
1595  }
1596  return at_least_one_vertex_with_degree_greater_than_2;
1597  }
1598 
1607  {
1608  auto edges_range = incident_edges(face);
1609  auto it = edges_range.begin();
1610  for(; it != edges_range.end(); ++it)
1611  {
1612  if(degree(*it) > 1)
1613  return false;
1614  }
1615  return true;
1616  }
1617 
1626  static bool
1629  {
1630  auto edges_range = incident_edges(face);
1631  auto it = edges_range.begin();
1632  if(!are_incident(face, edge))
1633  return false;
1634  if(degree(edge) <= 1)
1635  return false;
1636  for(; it != edges_range.end(); ++it)
1637  {
1638  if((degree(*it) > 1) && (*it != edge))
1639  return false;
1640  }
1641  return true;
1642  }
1643 
1653  {
1654  auto edges_range = incident_edges(face);
1655  auto it = edges_range.begin();
1656  for (; it != edges_range.end(); ++it)
1657  {
1658  if (is_surface_border_edge(*it))
1659  return true;
1660  }
1661  return false;
1662  }
1663 
1677  {
1678  auto edges_range = incident_edges(face);
1679  auto it = edges_range.begin();
1680  for (; it != edges_range.end(); ++it)
1681  {
1682  if (is_surface_border_edge(*it) && are_incident(*it, v))
1683  {
1684  auto it2 = it;
1685  ++it2;
1686  if(it2==edges_range.end())
1687  it2 = edges_range.begin();
1688  if(are_incident(*it2, v)){
1689  return border_edge_before_v || is_surface_border_edge(*it2);
1690  }
1691  else if(!border_edge_before_v) // because *it is after v
1692  return true;
1693  }
1694  }
1695  return false;
1696  }
1697 
1707  {
1708  return !is_surface_border_face(face);
1709  }
1710 
1722  {
1723  if(face == null_face())
1724  return false;
1725  if(face->m_Is_Incident_PtrVertices_Computed) // optimization by using
1726  // topological caching
1727  {
1728  return (std::find(face->m_Incident_PtrVertices.begin(),
1729  face->m_Incident_PtrVertices.end(),
1730  vertex) != face->m_Incident_PtrVertices.end());
1731  }
1732  else
1733  {
1734  auto edges_range = incident_edges(face);
1735  auto it = edges_range.begin();
1736  for(; it != edges_range.end(); ++it)
1737  {
1738  if(are_incident(*it, vertex))
1739  return true;
1740  }
1741  }
1742  return false;
1743  }
1744 
1756  {
1757  if(vertex == null_vertex())
1758  return false;
1759  if(vertex->m_Incident_PtrFaces_Computed) // optimization by using
1760  // topological caching
1761  {
1762  return (std::find(vertex->m_Incident_PtrFaces.begin(),
1763  vertex->m_Incident_PtrFaces.end(),
1764  face) != vertex->m_Incident_PtrFaces.end());
1765  }
1766  else
1767  {
1768  auto edges_range = incident_edges(vertex);
1769  auto it = edges_range.begin();
1770  for(; it != edges_range.end(); ++it)
1771  {
1772  if(are_incident(*it, face))
1773  return true;
1774  }
1775  }
1776  return false;
1777  }
1793  {
1794  if(face == null_face())
1795  return false;
1796  auto edges_range = incident_edges(face);
1797  auto it = edges_range.begin();
1798  for(; it != edges_range.end(); ++it)
1799  {
1800  if(*it == edge)
1801  return true;
1802  }
1803  return false;
1804  }
1816  {
1817  if(face1 == face2)
1818  return false;
1819 
1820  boost::iterator_range< incident_edge_iterator > edges_range =
1821  incident_edges(face1);
1822 
1823  for(incident_edge_iterator it = edges_range.begin();
1824  it != edges_range.end();
1825  ++it)
1826  {
1827  if(are_incident(*it, face2))
1828  return true;
1829  }
1830  return false;
1831  }
1838  static boost::iterator_range< vertex_container_in_face::const_iterator >
1840  {
1841  if(face == null_face())
1842  throw std::invalid_argument("AIFTopologyHelpers::incident_vertices -> no "
1843  "incident relation exists for a null face.");
1844 
1845  return face->GetIncidentVertices();
1846  }
1853  static boost::iterator_range< incident_edge_iterator >
1855  {
1856  if(face == null_face())
1857  throw std::invalid_argument("AIFTopologyHelpers::incident_edges -> no "
1858  "incident relation exists for a null face.");
1859 
1860  return face->GetIncidentEdges();
1861  }
1870  static std::vector< face_descriptor >
1872  bool one_neighborhood_sharing_edge = true)
1873  {
1874  std::set< face_descriptor > adFaces;
1875  if(one_neighborhood_sharing_edge)
1876  {
1877  auto eRange = incident_edges(face);
1878  for(auto eIt = eRange.begin(); eIt != eRange.end(); ++eIt)
1879  {
1880  auto fRange = incident_faces(*eIt);
1881  std::vector< face_descriptor > incidentFaces(fRange.begin(),
1882  fRange.end());
1883  incidentFaces.erase(
1884  std::find(incidentFaces.begin(), incidentFaces.end(), face));
1885  adFaces.insert(incidentFaces.begin(), incidentFaces.end());
1886  }
1887  }
1888  else
1889  {
1890  auto vRange = incident_vertices(face);
1891  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
1892  {
1893  auto fRange = incident_faces(*vIt);
1894  std::vector< face_descriptor > incidentFaces(fRange.begin(),
1895  fRange.end());
1896  incidentFaces.erase(
1897  std::find(incidentFaces.begin(), incidentFaces.end(), face));
1898  adFaces.insert(incidentFaces.begin(), incidentFaces.end());
1899  }
1900  }
1901  return std::vector< face_descriptor >(
1902  adFaces.begin(),
1903  adFaces.end()); // note that it is a non-sens to manage a memory caching
1904  // as adjacent faces can be quickly computed
1905  }
1906 
1916  static bool
1918  face_descriptor face2)
1919  {
1920  if(are_adjacent(face1, face2))
1921  return true;
1922 
1923  vertex_descriptor shared = null_vertex();
1924  auto vRange1 = incident_vertices(face1);
1925  auto vRange2 = incident_vertices(face2);
1926  for(auto vIt1 = vRange1.begin(); vIt1 != vRange1.end(); ++vIt1){
1927  for(auto vIt2 = vRange2.begin(); vIt2 != vRange2.end(); ++vIt2){
1928  if(*vIt1 == *vIt2)
1929  {
1930  shared = *vIt1;
1931  break;
1932  }
1933  }
1934  if(shared != null_vertex())
1935  {
1936  break;
1937  }
1938  }
1939  if(shared == null_vertex()) // if the 2 faces do not share any vertex
1940  return false; // there are not locally connected
1941 
1942  auto facesRange = incident_faces(shared);
1943  std::stack<face_descriptor> s;
1944  std::map< face_descriptor, bool> already_met;
1945  s.push(face1);
1946  while(!s.empty()){
1947  face_descriptor current = s.top();
1948  already_met[current] = true;
1949  s.pop();
1950 
1951  auto itF = facesRange.begin();
1952  for(; itF != facesRange.end(); ++itF){
1953  if(are_adjacent(current, *itF)){
1954  if(*itF==face2)
1955  return true;
1956  if(already_met.find(*itF)== already_met.end()) // not yet met
1957  s.push(*itF);
1958  }
1959  }
1960  }
1961  return false;
1962  }
1963 
1973  face_descriptor face2)
1974  {
1975  auto vertices_range1 = incident_vertices(face1);
1976  auto vertices_range2 = incident_vertices(face2);
1977  auto it1 = vertices_range1.begin();
1978  for(; it1 != vertices_range1.end(); ++it1)
1979  {
1980  auto it2 = vertices_range2.begin();
1981  for(; it2 != vertices_range2.end(); ++it2)
1982  {
1983  if(*it1 == *it2)
1984  {
1985  auto it1_b = it1;
1986  if(it1_b == vertices_range1.begin())
1987  it1_b = vertices_range1.end();
1988  --it1_b;
1989 
1990  ++it1;
1991  if(it1 == vertices_range1.end())
1992  it1 = vertices_range1.begin();
1993 
1994  auto it2_b = it2;
1995  if(it2_b == vertices_range2.begin())
1996  it2_b = vertices_range2.end();
1997  --it2_b;
1998 
1999  ++it2;
2000  if(it2 == vertices_range2.end())
2001  it2 = vertices_range2.begin();
2002 
2003  if((*it1 == *it2) || (*it1_b == *it2_b))
2004  {
2005  return false;
2006  }
2007  if((*it1 == *it2_b) || (*it1_b == *it2))
2008  {
2009  return true;
2010  }
2011  }
2012  }
2013  }
2014  return false;
2015  }
2016 
2024  static bool
2026  {
2027  auto deg_e = degree(edge);
2028  if(deg_e > 2)
2029  return false;
2030  else if(deg_e == 2)
2031  {
2032  auto faceRange = incident_faces(edge);
2033  auto iter_f1 = faceRange.begin();
2034  auto iter_f2 = std::next(iter_f1);
2035  if(!have_consistent_orientation(*iter_f1, *iter_f2))
2036  return false;
2037  }
2038  return true;
2039  }
2040 
2046  {
2047  auto edgeRange = incident_edges(face);
2048  std::reverse(edgeRange.begin(), edgeRange.end());
2049  face->clear_vertex_incidency();
2050  }
2058  {
2059  auto edge_range = incident_edges(face);
2060  auto iter_e = edge_range.begin(), iter_e_e = edge_range.end();
2061  for(; iter_e != iter_e_e; ++iter_e)
2062  if(is_complex_edge(*iter_e))
2063  return false;
2064 
2065  return true;
2066  }
2067 
2075  edge_descriptor edge2)
2076  {
2077  typedef face_container_in_edge::const_iterator it_type;
2078 
2079  boost::iterator_range< it_type > faces_range = incident_faces(edge1);
2080 
2081  for(it_type it = faces_range.begin(); it != faces_range.end(); ++it)
2082  {
2083  if(are_incident(*it, edge2))
2084  return *it;
2085  }
2086  return null_face();
2087  }
2088 
2096  face_descriptor face2)
2097  {
2098  typedef edge_container_in_face::const_iterator it_type;
2099  // if (face1 == null_face() || face2 == null_face())
2100  // return null_edge();
2101  boost::iterator_range< it_type > edges_range1 = incident_edges(face1);
2102  boost::iterator_range< it_type > edges_range2 = incident_edges(face2);
2103 
2104  for(it_type it1 = edges_range1.begin(); it1 != edges_range1.end(); ++it1)
2105  {
2106  for(it_type it2 = edges_range2.begin(); it2 != edges_range2.end(); ++it2)
2107  {
2108  if(*it1 == *it2)
2109  return *it1;
2110  }
2111  }
2112  return null_edge();
2113  }
2121  static std::vector< edge_descriptor > common_edges(face_descriptor face1,
2122  face_descriptor face2)
2123  {
2124  typedef edge_container_in_vertex::const_iterator it_type;
2125  std::vector< edge_descriptor > com_edges;
2126  boost::iterator_range< it_type > edges_range1 = incident_edges(face1);
2127  boost::iterator_range< it_type > edges_range2 = incident_edges(face2);
2128 
2129  for(it_type it1 = edges_range1.begin(); it1 != edges_range1.end(); ++it1)
2130  {
2131  for(it_type it2 = edges_range2.begin(); it2 != edges_range2.end(); ++it2)
2132  {
2133  if((*it1 == *it2) &&
2134  (std::find(com_edges.begin(), com_edges.end(), *it1) ==
2135  com_edges.end()))
2136  com_edges.push_back(*it1);
2137  }
2138  }
2139  return com_edges;
2140  }
2143 
2149  {
2150  return mesh->GetNumberOfVertices();
2151  }
2158  {
2159  return num_vertices(mesh.get());
2160  }
2167  static size_type num_vertices(ref_cmesh mesh) { return num_vertices(&mesh); }
2168 
2175  {
2176  return mesh->GetNumberOfEdges();
2177  }
2184  {
2185  return num_edges(mesh.get());
2186  }
2192  static size_type num_edges(ref_cmesh mesh) { return num_edges(&mesh); }
2193 
2194 
2201  {
2202  return mesh->GetNumberOfFaces();
2203  }
2210  {
2211  return num_faces(mesh.get());
2212  }
2218  static size_type num_faces(ref_cmesh mesh) { return num_faces(&mesh); }
2219 
2226  static boost::iterator_range< vertex_container::const_iterator >
2228  {
2229  return mesh->GetVertices();
2230  }
2237  static boost::iterator_range< vertex_container::const_iterator >
2239  {
2240  return vertices(mesh.get());
2241  }
2248  static boost::iterator_range< vertex_container::const_iterator >
2250  {
2251  return vertices(&mesh);
2252  }
2253 
2260  static boost::iterator_range< edge_container::const_iterator >
2262  {
2263  return mesh->GetEdges();
2264  }
2271  static boost::iterator_range< edge_container::const_iterator >
2273  {
2274  return edges(mesh.get());
2275  }
2282  static boost::iterator_range< edge_container::const_iterator >
2284  {
2285  return edges(&mesh);
2286  }
2287 
2297  static bool is_2_manifold_mesh(ptr_cmesh mesh)
2298  {
2299  auto verticesRange = mesh->GetVertices();
2300  auto vertexIter = verticesRange.begin(), vertexIterE = verticesRange.end();
2301  for(; vertexIter != vertexIterE; ++vertexIter)
2302  {
2303  if(!is_2_manifold_vertex(*vertexIter))
2304  return false;
2305  }
2306  return true;
2307  }
2308 
2318  {
2319  return edges(mesh.get());
2320  }
2321 
2331  static bool is_2_manifold_mesh(ref_cmesh mesh)
2332  {
2333  return is_2_manifold_mesh(&mesh);
2334  }
2335 
2345  static bool
2347  {
2348  auto edgesRange = mesh->GetEdges();
2349  auto edgeIter = edgesRange.begin(), edgeIterE = edgesRange.end();
2350  for(; edgeIter != edgeIterE; ++edgeIter)
2351  {
2353  return true;
2354  }
2355  return false;
2356  }
2357 
2367  static bool
2369  {
2371  }
2372 
2382  static bool
2384  {
2386  }
2387 
2397  {
2398  auto verticesRange = mesh->GetVertices();
2399  auto vertexIter = verticesRange.begin(), vertexIterE = verticesRange.end();
2400  for(; vertexIter != vertexIterE; ++vertexIter)
2401  {
2402  if(is_cut_vertex(*vertexIter))
2403  return true;
2404  }
2405  return false;
2406  }
2407 
2417  {
2418  return contains_a_cut_vertex(mesh.get());
2419  }
2420 
2430  {
2431  return contains_a_cut_vertex(&mesh);
2432  }
2433 
2440  {
2441  auto edgesRange = mesh->GetEdges();
2442  auto edgeIter = edgesRange.begin(), edgeIterE = edgesRange.end();
2443  bool meetFirstBorderEdge = false;
2444  for(; edgeIter != edgeIterE; ++edgeIter)
2445  {
2446  if(is_surface_border_edge(*edgeIter))
2447  {
2448  if(!meetFirstBorderEdge)
2449  meetFirstBorderEdge = true;
2450  }
2451  else
2452  {
2453  if(meetFirstBorderEdge)
2454  return false;
2455  }
2456  }
2457  return true;
2458  }
2465  {
2466  return normalized_border_is_valid(mesh.get());
2467  }
2474  {
2475  return normalized_border_is_valid(&mesh);
2476  }
2477 
2482  {
2483  auto edgesRange = mesh->GetEdges();
2484  auto edgeIter = edgesRange.begin(), edgeIterE = edgesRange.end();
2485  size_type cpt = 0;
2486  for(; edgeIter != edgeIterE; ++edgeIter)
2487  {
2488  if(is_surface_border_edge(*edgeIter))
2489  {
2490  ++cpt;
2491  }
2492  }
2493  return cpt;
2494  }
2499  {
2500  return size_of_border_edges(mesh.get());
2501  }
2506  {
2507  return size_of_border_edges(&mesh);
2508  }
2509 
2516  static void normalize_border(ptr_mesh mesh)
2517  {
2518  auto edgesRange = mesh->GetEdges();
2519  auto edgeIter = edgesRange.begin(), edgeIterE = edgesRange.end();
2520  --edgeIterE;
2521  while(edgeIter != edgeIterE)
2522  {
2523  if(is_surface_border_edge(*edgeIter))
2524  {
2525  if(!is_surface_border_edge(*edgeIterE))
2526  {
2527  swap(*edgeIter, *edgeIterE);
2528  ++edgeIter;
2529  }
2530  --edgeIterE;
2531  }
2532  else
2533  ++edgeIter;
2534  }
2535  assert(normalized_border_is_valid(mesh));
2536  }
2544  {
2545  normalize_border(mesh.get());
2546  }
2553  static void normalize_border(ref_mesh mesh) { normalize_border(&mesh); }
2554 
2561  static boost::iterator_range< edge_container::const_iterator >
2563  {
2564  if(!normalized_border_is_valid(mesh))
2565  throw std::invalid_argument(
2566  "AIFTopologyHelpers::border_edges(m) -> mesh' edges have not been "
2567  "normalized, thus cannot deduced an iterator range over border "
2568  "edges.");
2569 
2570  auto edgesRange = mesh->GetEdges();
2571  auto edgeIter = edgesRange.begin(), edgeIterE = edgesRange.end();
2572  while((edgeIter != edgeIterE) && (!is_surface_border_edge(*edgeIter)))
2573  ++edgeIter;
2574  return boost::make_iterator_range(edgeIter, edgeIterE);
2575  }
2582  static boost::iterator_range< edge_container::const_iterator >
2584  {
2585  return border_edges(mesh.get());
2586  }
2593  static boost::iterator_range< edge_container::const_iterator >
2595  {
2596  return border_edges(&mesh);
2597  }
2598 
2605  static boost::iterator_range< face_container::const_iterator >
2607  {
2608  return mesh->GetFaces();
2609  }
2616  static boost::iterator_range< face_container::const_iterator >
2618  {
2619  return faces(mesh.get());
2620  }
2627  static boost::iterator_range< face_container::const_iterator >
2629  {
2630  return faces(&mesh);
2631  }
2632 
2641  static bool check_mesh_validity(ptr_cmesh mesh)
2642  {
2643  auto iter_range_v = vertices(mesh);
2644  auto iter_v = iter_range_v.begin();
2645  for(; iter_v != iter_range_v.end(); ++iter_v)
2646  if(is_degenerated_vertex(*iter_v))
2647  return false;
2648  auto iter_range_e = edges(mesh);
2649  auto iter_e = iter_range_e.begin();
2650  for(; iter_e != iter_range_e.end(); ++iter_e)
2651  if(is_degenerated_edge(*iter_e))
2652  return false;
2653  auto iter_range_f = faces(mesh);
2654  auto iter_f = iter_range_f.begin();
2655  for(; iter_f != iter_range_f.end(); ++iter_f)
2656  if(is_degenerated_face(*iter_f))
2657  return false;
2658 
2659  return true;
2660  }
2670  {
2671  return check_mesh_validity(mesh.get());
2672  }
2681  static bool check_mesh_validity(ref_cmesh mesh)
2682  {
2683  return check_mesh_validity(&mesh);
2684  }
2685 
2694  template< typename InputIt >
2695  static bool contains_a_degenerated_face(InputIt first, InputIt last)
2696  {
2697  for(; first != last; ++first)
2698  if(is_degenerated_face(*first))
2699  return true;
2700 
2701  return false;
2702  }
2703 
2710  {
2712  mesh->InsertIsolatedVertex(vertex);
2713  return vertex;
2714  }
2721  {
2722  return add_vertex(mesh.get());
2723  }
2730  {
2731  return add_vertex(&mesh);
2732  }
2733 
2740  static void add_vertex(vertex_descriptor vertex, ptr_mesh mesh)
2741  {
2742  mesh->InsertIsolatedVertex(vertex);
2743  }
2744 
2751  static void add_vertex(vertex_descriptor vertex, smart_ptr_mesh mesh)
2752  {
2753  add_vertex(vertex, mesh.get());
2754  }
2755 
2762  static void add_vertex(vertex_descriptor vertex, ref_mesh mesh)
2763  {
2764  add_vertex(vertex, &mesh);
2765  }
2766 
2773  {
2775  mesh->InsertIsolatedEdge(edge);
2776  return edge;
2777  }
2784  {
2785  return add_edge(mesh.get());
2786  }
2792  static edge_descriptor add_edge(ref_mesh mesh) { return add_edge(&mesh); }
2793 
2801  {
2802  mesh->InsertIsolatedEdge(edge);
2803  }
2804 
2812  {
2813  add_edge(edge, mesh.get());
2814  }
2815 
2823  {
2824  add_edge(edge, &mesh);
2825  }
2826 
2836  static std::pair< edge_descriptor, bool >
2838  {
2839  bool is_edge_insertion_done = false;
2841  if(edge == null_edge())
2842  {
2843  edge = add_edge(mesh); // does the mesh->InsertIsolatedEdge(edge);
2844  link_vertex_and_edge(v, edge, vertex_pos::FIRST);
2845  link_vertex_and_edge(u, edge, vertex_pos::SECOND);
2846  is_edge_insertion_done = true;
2847  }
2848 
2849  return std::pair< edge_descriptor, bool >(edge, is_edge_insertion_done);
2850  }
2851 
2861  static std::pair< edge_descriptor, bool >
2863  {
2864  return add_edge(v, u, mesh.get());
2865  }
2866 
2876  static std::pair< edge_descriptor, bool >
2878  {
2879  return add_edge(v, u, &mesh);
2880  }
2881 
2888  {
2890  mesh->InsertIsolatedFace(face);
2891  return face;
2892  }
2899  {
2900  return add_face(mesh.get());
2901  }
2907  static face_descriptor add_face(ref_mesh mesh) { return add_face(&mesh); }
2915  {
2916  mesh->InsertIsolatedFace(face);
2917  }
2925  {
2926  add_face(face, mesh.get());
2927  }
2935  {
2936  add_face(face, &mesh);
2937  }
2939 
2946  static void clear_vertex(vertex_descriptor vertex)
2947  {
2948  if(vertex == null_vertex())
2949  throw std::invalid_argument(
2950  "AIFTopologyHelpers::clear_vertex(v) -> vertex is null, cannot clear "
2951  "its connectivity from mesh.");
2952  unlink_all_edges(vertex);
2953  }
2960  static void remove_vertex(vertex_descriptor vertex, ptr_mesh mesh)
2961  {
2962  if(vertex == null_vertex())
2963  throw std::invalid_argument(
2964  "AIFTopologyHelpers::remove_vertex(v, m) -> vertex is null, cannot "
2965  "suppress it from mesh.");
2966  clear_vertex(vertex); // in common mesh datastructures this check is not
2967  // done beacause a call to clear_vertex is supposed to
2968  // done just before a call to remove_vertex
2969  mesh->EraseIsolatedVertex(vertex);
2970  }
2978  {
2979  remove_vertex(vertex, mesh.get());
2980  }
2987  static void remove_vertex(vertex_descriptor vertex, ref_mesh mesh)
2988  {
2989  remove_vertex(vertex, &mesh);
2990  }
2999  template< typename InputIt, typename MeshType >
3000  static void remove_vertices(InputIt first, InputIt last, MeshType& mesh)
3001  {
3002  for(; first != last; ++first)
3003  remove_vertex(*first, mesh);
3004  }
3013  {
3014  if(edge == null_edge())
3015  throw std::invalid_argument(
3016  "AIFTopologyHelpers::remove_edge(e, m) -> edge is null, cannot "
3017  "suppress it from mesh.");
3019  std::set< vertex_descriptor > verticesToRemove;
3020  if(edge->get_first_vertex() != null_vertex() &&
3021  edge->get_first_vertex()->GetDegree() == 1)
3022  verticesToRemove.insert(edge->get_first_vertex());
3023  if(edge->get_second_vertex() != null_vertex() &&
3024  edge->get_second_vertex()->GetDegree() == 1)
3025  verticesToRemove.insert(edge->get_second_vertex());
3027  mesh->EraseIsolatedEdge(edge);
3028 
3029  std::set< vertex_descriptor >::iterator itv = verticesToRemove.begin(),
3030  itve = verticesToRemove.end();
3031  for(; itv != itve; ++itv)
3032  {
3033  mesh->EraseIsolatedVertex(*itv);
3034  }
3035  }
3044  {
3045  remove_edge(edge, mesh.get());
3046  }
3055  {
3056  remove_edge(edge, &mesh);
3057  }
3066  template< typename InputIt, typename MeshType >
3067  static void remove_edges(InputIt first, InputIt last, MeshType& mesh)
3068  {
3069  for(; first != last; ++first)
3070  remove_edge(*first, mesh);
3071  }
3080  static void
3082  {
3084  remove_edge(edge, mesh); // to ensure same behavior with
3085  // remove_edge(edge_descriptor edge, ptr_mesh mesh)
3086  }
3095  static void
3097  {
3098  remove_edge(v, u, mesh.get());
3099  }
3108  static void
3110  {
3111  remove_edge(v, u, &mesh);
3112  }
3121  {
3122  if(face == null_face())
3123  throw std::invalid_argument(
3124  "AIFTopologyHelpers::remove_face(f, m) -> face is null, cannot "
3125  "suppress it from mesh.");
3126  // correction towards CGAL-like implementation [done on 2017-05-03]
3127  // removes edges from the graph if they were already border edges.
3128  // If this creates isolated vertices remove them as well (at the the
3129  // remove_edge level).
3130  auto edgesRange = face->GetIncidentEdges();
3131  std::list< edge_descriptor > edgesToRemove;
3132  std::set< vertex_descriptor > vertexWhichNeedsToClearPrecomputation;
3133  auto itE = edgesRange.begin();
3134  for(; itE != edgesRange.end(); ++itE)
3135  {
3136  vertexWhichNeedsToClearPrecomputation.insert((*itE)->get_first_vertex());
3137  vertexWhichNeedsToClearPrecomputation.insert((*itE)->get_second_vertex());
3138  if((*itE)->GetDegree() == 1)
3139  {
3140  edgesToRemove.push_back(*itE);
3141  }
3142  }
3144  mesh->EraseIsolatedFace(face);
3145  std::list< edge_descriptor >::iterator it = edgesToRemove.begin(),
3146  ite = edgesToRemove.end();
3147  for(; it != ite; ++it)
3148  {
3149  unlink_all_vertices(*it);
3150  remove_edge(*it, mesh);
3151  }
3152 
3153  std::set< vertex_descriptor >::iterator
3154  itv = vertexWhichNeedsToClearPrecomputation.begin(),
3155  itve = vertexWhichNeedsToClearPrecomputation.end();
3156  for(; itv != itve; ++itv)
3157  {
3158  (*itv)->m_Incident_PtrFaces.clear();
3159  (*itv)->m_Incident_PtrFaces_Computed = false;
3160  }
3161  }
3170  {
3171  remove_face(face, mesh.get());
3172  }
3181  {
3182  remove_face(face, &mesh);
3183  }
3192  template< typename InputIt, typename MeshType >
3193  static void remove_faces(InputIt first, InputIt last, MeshType& mesh)
3194  {
3195  for(; first != last; ++first)
3196  remove_face(*first, mesh);
3197  }
3205  {
3206  vertex_descriptor v1 = edge->get_first_vertex(),
3207  v2 = edge->get_second_vertex();
3208  if(v1 != null_vertex())
3210  if(v2 != null_vertex())
3212  }
3218  {
3219  typedef edge_container_in_vertex::const_iterator it_type;
3220  boost::iterator_range< it_type > edges_range = incident_edges(vertex);
3221  std::vector< edge_descriptor > edgesToUnlink;
3222 
3223  std::copy(
3224  edges_range.begin(),
3225  edges_range.end(),
3226  std::back_inserter(edgesToUnlink)); // the relations need to be copied
3227  // to keep iterator valid
3228 
3229  for(std::vector< edge_descriptor >::const_iterator it =
3230  edgesToUnlink.cbegin();
3231  it != edgesToUnlink.cend();
3232  ++it)
3233  unlink_vertex_and_edge(vertex, *it);
3234  }
3240  {
3241  typedef incident_edge_iterator it_type;
3242  boost::iterator_range< it_type > edges_range = incident_edges(face);
3243  std::vector< edge_descriptor > edgesToUnlink;
3244 
3245  std::copy(
3246  edges_range.begin(),
3247  edges_range.end(),
3248  std::back_inserter(edgesToUnlink)); // the relations need to be copied
3249  // to keep iterator valid
3250 
3251  for(std::vector< edge_descriptor >::const_iterator it =
3252  edgesToUnlink.cbegin();
3253  it != edgesToUnlink.cend();
3254  ++it)
3255  unlink_edge_and_face(*it, face);
3256  }
3262  {
3263  typedef face_container_in_edge::const_iterator it_type;
3264  boost::iterator_range< it_type > faces_range = incident_faces(edge);
3265  std::vector< face_descriptor > facesToUnlink;
3266 
3267  std::copy(
3268  faces_range.begin(),
3269  faces_range.end(),
3270  std::back_inserter(facesToUnlink)); // the relations need to be copied
3271  // to keep iterator valid
3272 
3273  for(std::vector< face_descriptor >::const_iterator it =
3274  facesToUnlink.cbegin();
3275  it != facesToUnlink.cend();
3276  ++it)
3277  unlink_edge_and_face(edge, *it);
3278  }
3279 
3281 
3295  vertex_descriptor vertex,
3296  enum vertex_pos position)
3297  {
3298  if(vertex == null_vertex())
3299  throw std::invalid_argument(
3300  "AIFTopologyHelpers::add_vertex(e, v) -> vertex is a null vertex.");
3301 
3302  if(edge == null_edge())
3303  throw std::invalid_argument(
3304  "AIFTopologyHelpers::add_vertex(e, v) -> edge is a null edge.");
3305 
3306  if(!are_incident(edge, vertex))
3307  {
3308  add_vertex_to_edge(edge, vertex, position);
3309  }
3310  }
3322  {
3323  if(edge == null_edge())
3324  throw std::invalid_argument(
3325  "AIFTopologyHelpers::remove_vertex(e, v) -> edge is a null edge.");
3326 
3327  if(vertex == null_vertex())
3328  throw std::invalid_argument("AIFTopologyHelpers::remove_vertex(e, v) -> "
3329  "vertex is a null vertex.");
3330 
3331  if(are_incident(edge, vertex))
3332  {
3333  remove_vertex_from_edge(edge, vertex);
3334  }
3335  }
3347  {
3348  if(vertex == null_vertex())
3349  throw std::invalid_argument(
3350  "AIFTopologyHelpers::add_edge(v, e) -> vertex is a null vertex.");
3351 
3352  if(edge == null_edge())
3353  throw std::invalid_argument(
3354  "AIFTopologyHelpers::add_edge(v, e) -> edge is a null edge.");
3355 
3356  if(!are_incident(vertex, edge))
3357  {
3358  add_edge_to_vertex(vertex, edge);
3359  }
3360  }
3371  {
3372  if(vertex == null_vertex())
3373  throw std::invalid_argument(
3374  "AIFTopologyHelpers::remove_edge(v, e) -> vertex is a null vertex.");
3375  if(edge == null_edge())
3376  throw std::invalid_argument(
3377  "AIFTopologyHelpers::remove_edge(v, e) -> edge is a null edge.");
3378 
3379  if(are_incident(vertex, edge))
3380  {
3381  remove_edge_from_vertex(vertex, edge);
3382  }
3383  }
3393  {
3394  if(edge == null_edge())
3395  throw std::invalid_argument(
3396  "AIFTopologyHelpers::add_face(e, f) -> edge is a null edge.");
3397  if(face == null_face())
3398  throw std::invalid_argument(
3399  "AIFTopologyHelpers::add_face(e, f) -> face is a null face.");
3400 
3401  if(!are_incident(edge, face))
3402  {
3404  }
3405  }
3415  {
3416  if(edge == null_edge())
3417  throw std::invalid_argument(
3418  "AIFTopologyHelpers::remove_face(e, f) -> edge is a null edge.");
3419  if(face == null_face())
3420  throw std::invalid_argument(
3421  "AIFTopologyHelpers::remove_face(e, f) -> face is a null face.");
3422 
3423  if(are_incident(edge, face))
3424  {
3426  }
3427  }
3437  {
3438  if(edge == null_edge())
3439  throw std::invalid_argument(
3440  "AIFTopologyHelpers::add_edge(f, e) -> edge is a null edge.");
3441  if(face == null_face())
3442  throw std::invalid_argument(
3443  "AIFTopologyHelpers::add_edge(f, e) -> face is a null face.");
3444 
3445  if(!are_incident(face, edge))
3446  {
3448  }
3449  }
3459  {
3460  if(edge == null_edge())
3461  throw std::invalid_argument(
3462  "AIFTopologyHelpers::add_edge(f, e) -> edge is a null edge.");
3463  if(face == null_face())
3464  throw std::invalid_argument(
3465  "AIFTopologyHelpers::add_edge(f, e) -> face is a null face.");
3466 
3467  if(are_incident(face, edge))
3468  {
3470  }
3471  }
3472 
3473 public:
3474  // One-ring stuff
3480  static std::set< edge_descriptor >
3482  {
3483  std::set< edge_descriptor > edgesToRemove(incident_edges(v).begin(),
3484  incident_edges(v).end());
3485  std::set< edge_descriptor > edges;
3486  std::set< edge_descriptor > oldEdges;
3487  bool first = true;
3490  face_container_in_vertex::iterator nextFace = faces.begin();
3491  while(!faces.empty())
3492  {
3493  auto eRange = incident_edges(*nextFace);
3494  edges.insert(eRange.begin(), eRange.end());
3495 
3496  if(first)
3497  {
3498  first = false;
3500  oldEdges = edges;
3501  }
3502  else
3503  {
3504  std::set< edge_descriptor > edgesTmp(eRange.begin(), eRange.end());
3505  std::set< edge_descriptor > edgesInter;
3506  std::set_intersection(edgesTmp.begin(),
3507  edgesTmp.end(),
3508  oldEdges.begin(),
3509  oldEdges.end(),
3510  std::inserter(edgesInter, edgesInter.end()));
3511  oldEdges.clear();
3512  std::set_difference(edges.begin(),
3513  edges.end(),
3514  edgesInter.begin(),
3515  edgesInter.end(),
3516  std::inserter(oldEdges, oldEdges.end()));
3518  edges.swap(oldEdges); // edges = oldEdges;
3519  }
3521  faces.erase(nextFace); // each processed face is removed
3523  nextFace = faces.begin();
3524  }
3526  std::set< edge_descriptor > result;
3527  std::set< edge_descriptor >::iterator it(edges.begin()), ite(edges.end());
3528  for(; it != ite; ++it)
3529  {
3530  if(edgesToRemove.find(*it) ==
3531  edgesToRemove.end()) // *it is not an incident edge
3532  {
3533  result.insert(*it);
3534  }
3535  }
3536  return result;
3537  }
3538 
3545  template< typename T >
3546  static bool
3548  const T &container_of_edge_one_ring,
3549  bool allow_multiple_incident_edges = false,
3550  bool ensure_e_belongs_to_container = true)
3551  {
3552  // First ensure that e is an element of container_of_edge_one_ring
3553  if(ensure_e_belongs_to_container &&
3554  (std::find(container_of_edge_one_ring.begin(),
3555  container_of_edge_one_ring.end(),
3556  e) == container_of_edge_one_ring.end()))
3557  return false;
3558  // Then check if e is one-ring connected to its one ring
3559  bool another_edge_incident_to_e_v1 = false,
3560  another_edge_incident_to_e_v2 = false;
3561  for(auto element : container_of_edge_one_ring)
3562  {
3563  if((element != e) && are_incident(element, e->get_first_vertex()))
3564  {
3565  if(!allow_multiple_incident_edges)
3566  if(another_edge_incident_to_e_v1)
3567  return false; // found 2 one-ring edges incident to v1
3568  another_edge_incident_to_e_v1 = true;
3569  if(allow_multiple_incident_edges)
3570  if(another_edge_incident_to_e_v2)
3571  break;
3572  }
3573  else if((element != e) && are_incident(element, e->get_second_vertex()))
3574  {
3575  if(!allow_multiple_incident_edges)
3576  if(another_edge_incident_to_e_v2)
3577  return false; // found 2 one-ring edges incident to v2
3578  another_edge_incident_to_e_v2 = true;
3579  if(allow_multiple_incident_edges)
3580  if(another_edge_incident_to_e_v1)
3581  break;
3582  }
3583  }
3584 
3585  return another_edge_incident_to_e_v1 && another_edge_incident_to_e_v2;
3586  }
3587 
3593  template< typename T >
3594  static bool
3596  const T &container_of_edge_one_ring)
3597  {
3598  auto edge_range = adjacent_edges(e);
3599  auto iter = edge_range.begin();
3600  for(; iter != edge_range.end(); ++iter)
3601  {
3602  if((std::find(container_of_edge_one_ring.begin(),
3603  container_of_edge_one_ring.end(),
3604  *iter) != container_of_edge_one_ring.end()) &&
3605  !is_e_one_ring_connected(*iter, container_of_edge_one_ring))
3606  return false;
3607  }
3608  return true;
3609  }
3615  template< typename T >
3616  static edge_descriptor
3618  const T &container_of_edge_one_ring)
3619  {
3620  for(auto element : container_of_edge_one_ring)
3622  container_of_edge_one_ring))
3623  return element;
3624  // else return the first one_ring_connected edge (without multiple incident
3625  // edges)
3626  for(auto element : container_of_edge_one_ring)
3627  if(is_e_one_ring_connected(element, container_of_edge_one_ring, false))
3628  return element;
3629  // else return the first one_ring_connected edge (with multiple incident
3630  // edges)
3631  for(auto element : container_of_edge_one_ring)
3632  if(is_e_one_ring_connected(element, container_of_edge_one_ring, true))
3633  return element;
3634  // else return the first element of the container
3635  return *(container_of_edge_one_ring.begin());
3636  }
3645  {
3646  std::set< edge_descriptor > notSortedOneRing =
3648  std::set< edge_descriptor > notSortedOneRingSave(notSortedOneRing);
3649  edge_container_in_vertex result;
3650 
3651  if(notSortedOneRing.size() == 0)
3652  return result;
3653 
3654  result.reserve(notSortedOneRing.size());
3655 
3656  edge_descriptor nextEdge =
3658  notSortedOneRing); // this call is needed to ensure that the reverse
3659  // step works properly Indeed, this needs that
3660  // the first one-ring edge is "classical"
3661  // one-ring edge
3662  while(!notSortedOneRing.empty())
3663  {
3664  result.push_back(nextEdge);
3665  notSortedOneRing.erase(nextEdge);
3666  if(!notSortedOneRing.empty())
3667  {
3668  if(notSortedOneRing.size() == 1)
3669  {
3670  nextEdge = *notSortedOneRing.begin();
3671  }
3672  else
3673  {
3674  std::set< edge_descriptor >::iterator it(notSortedOneRing.begin()),
3675  ite(notSortedOneRing.end());
3676  for(; it != ite; ++it)
3677  if(are_adjacent(*it, nextEdge))
3678  {
3679  // next we check for a non-manifold configuration (e.g. a
3680  // complex edge or a dangling edge here)
3681  // 1) we search for another edge satisfying the condition
3682  // are_adjacent(*it, nextEdge) 2) if such another edge exists,
3683  // then
3684  // => among all these edge(>=2) we select the first which has
3685  // its second vertex not incident
3686  // to any of one-ring edges (remaining notSortedOneRing and
3687  // already used ones)
3688  // => If this fails, look for an edge adjacent to last edge
3689  // with lowest degree for common vertex
3690  // 3) if there are only edge(>=2) with second vertex incident to
3691  // one of remaining edge, then
3692  // select the first
3693  // Remark: for 2 edges in the same situation, selecting the first
3694  // is because without geometric information we cannot propose
3695  // something else.
3697  edge_descriptor nextEdgeTmp = nextEdge;
3698  nextEdge = *it;
3699  // 1)
3700  auto it2 = it;
3701  ++it2;
3702 
3703  bool neverEnter = true, atLeastOneAnotherAdjacent = false;
3704  for(; it2 != ite; ++it2)
3705  {
3706  if(are_adjacent(*it2, nextEdgeTmp))
3707  {
3708  atLeastOneAnotherAdjacent = true;
3709  if(are_adjacent(*it2, nextEdge))
3710  {
3711  neverEnter = false;
3712  // 2)
3713  vertex_descriptor common_v =
3714  common_vertex(nextEdgeTmp, *it2);
3715  vertex_descriptor other_v = opposite_vertex(*it2, common_v);
3716  auto it3 = it;
3717  ++it3;
3718  for(; it3 != ite; ++it3)
3719  if((it3 != it2) && are_incident(*it3, other_v))
3720  {
3721  break;
3722  }
3724  if((it3 == ite) &&
3726  *it2, notSortedOneRingSave, true, true) ||
3728  nextEdge, notSortedOneRingSave, true, true) &&
3729  is_e_one_ring_connected(*it2, result, true, false))))
3730  {
3731  nextEdge = *it2;
3732  break;
3733  }
3734  }
3735  }
3736  }
3738  if(atLeastOneAnotherAdjacent && neverEnter)
3739  {
3740  it2 = it;
3741  ++it2;
3742 
3743  for(; it2 != ite; ++it2)
3744  {
3745  if(are_adjacent(*it2, nextEdgeTmp) &&
3746  degree(common_vertex(nextEdgeTmp, nextEdge)) >
3747  degree(common_vertex(nextEdgeTmp, *it2)))
3748  {
3749  nextEdge = *it2;
3750  break;
3751  }
3752  }
3753  }
3755  break;
3756  }
3757 
3758  if(it == ite)
3759  {
3760  // try to go back at the beginning in the other direction
3761  std::set< edge_descriptor > notUsedEdgesCopy(notSortedOneRing);
3762 
3763  edge_descriptor nextTmpEdge =
3764  *result.begin(); // get the first used edge
3765  it = notUsedEdgesCopy.begin();
3766  ite = notUsedEdgesCopy.end();
3767  while(it != ite)
3768  {
3769  bool found = false;
3770  for(; it != ite; ++it)
3771  if(are_adjacent(*it, nextTmpEdge))
3772  {
3773  nextTmpEdge = *it;
3774  notUsedEdgesCopy.erase(*it);
3775  found = true;
3776  break;
3777  }
3778 
3779  if(!found)
3780  break;
3781  it = notUsedEdgesCopy.begin();
3782  ite = notUsedEdgesCopy.end();
3783  }
3784 
3785  // There are 2 cases to take into account: 1) an hole, while the
3786  // vertex this is still 2-manifold (border case); 2) several
3787  // components and the vertex this is a cut vertex
3788  if(is_cut_vertex(v) // non-manifold
3789  || notUsedEdgesCopy.size() > 0) // hole within the one-ring
3790  { // non-manifold case: not all cases managed => to do later
3791  if(notUsedEdgesCopy.size() == 0)
3792  {
3793  if(notSortedOneRing.size() == 2)
3794  {
3795  if(are_adjacent(*notSortedOneRing.begin(), result.front()))
3796  {
3797  auto it_tmp = notSortedOneRing.begin();
3798  ++it_tmp;
3799  nextEdge = *it_tmp;
3800  }
3801  else
3802  nextEdge = *notSortedOneRing.begin();
3803  }
3804  else
3805  nextEdge = *notSortedOneRing.begin();
3806  }
3807  else if(notUsedEdgesCopy.size() <= 2)
3808  nextEdge = *notUsedEdgesCopy.begin();
3809  else
3810  {
3811  nextTmpEdge = *notUsedEdgesCopy.begin();
3812  it = notUsedEdgesCopy.begin();
3813  ite = notUsedEdgesCopy.end();
3814  while(it != ite)
3815  {
3816  bool found = false;
3817  for(; it != ite; ++it)
3818  if(are_adjacent(*it, nextTmpEdge))
3819  {
3820  nextTmpEdge = *it;
3821  notUsedEdgesCopy.erase(*it);
3822  found = true;
3823  break;
3824  }
3825  if(!found)
3826  break;
3827  it = notUsedEdgesCopy.begin();
3828  ite = notUsedEdgesCopy.end();
3829  }
3830 
3831  nextEdge = nextTmpEdge;
3832  }
3833  }
3834  else
3835  nextEdge = nextTmpEdge;
3836  }
3837  }
3838  }
3839  }
3840  // Try to get a one-ring ordered into clockwise order when faces are
3841  // oriented into counter-clockwise order The code bellow is needed when the
3842  // first not ordered one-ring edge is followed by a hole in the clockwise
3843  // order
3844  size_t nbE = result.size();
3845  if(nbE > 2)
3846  {
3847  size_t i;
3849  for(i = 0; i < nbE; ++i)
3850  {
3851  if(are_adjacent(result[i], result[(i + 1) % nbE]))
3852  {
3853  auto fRange = incident_faces(result[i]); // face iterator range
3854  if(!fRange.empty())
3855  {
3856  faces = face_container_in_vertex(fRange.begin(), fRange.end());
3857  break;
3858  }
3859  }
3860  }
3861  if(i < nbE)
3862  {
3863  // try to find a face that has "this" vertex as incident vertex
3865  size_t nbF = faces.size();
3866  size_t k;
3867  for(k = 0; k < nbF; ++k)
3868  {
3869  if(are_incident(v, faces[k]))
3870  {
3871  auto vRange =
3872  incident_vertices(faces[k]); // vertices iterator range
3873  resV = vertex_container_in_vertex(vRange.begin(), vRange.end());
3874  break;
3875  }
3876  }
3877  if(k == nbF)
3878  {
3879  auto vRange = incident_vertices(faces[0]); // vertices iterator range
3880  resV = vertex_container_in_vertex(vRange.begin(), vRange.end());
3881  }
3883  // the order generally given for face in mesh files is the
3884  // counterclockwise order
3885  bool v1BeforeV2InFace = false;
3887  auto it = resV.begin(); // iterator over a container of pointers
3888  auto ite = resV.end();
3889  vertex_descriptor first_v, second_v;
3890  if(are_adjacent(result[i], result[(i + 1) % nbE]))
3891  second_v = common_vertex(result[i], result[(i + 1) % nbE]);
3892  else
3893  {
3894  assert(false); // should never be executed
3895  second_v = result[i]->get_second_vertex();
3896  }
3897  first_v = opposite_vertex(result[i], second_v);
3898  while(it != ite)
3899  {
3900  if(**it == *(first_v))
3901  {
3902  ++it;
3903  if(it == ite)
3904  it = resV.begin();
3905  if(**it == *(second_v))
3906  v1BeforeV2InFace =
3907  true; // if the following is V2 => true, else => false
3908 
3909  break;
3910  }
3911  else if(**it == *(second_v))
3912  {
3913  ++it;
3914  if(it == ite)
3915  it = resV.begin();
3916  if(**it != *(first_v))
3917  v1BeforeV2InFace = true; // if the following is different from V1
3918  // => true, else => false
3919 
3920  break;
3921  }
3922  ++it;
3923  }
3924  if(it != ite)
3925  { // ensure that face orientation (given by its vertex indices order) is
3926  // opposite to one-ring orientation
3927  if(are_incident(first_v, result[(i + 1) % nbE]))
3928  {
3929  if(!v1BeforeV2InFace) // in that case currently the one-ring is
3930  // clockwise oriented => change it to
3931  // counterclockwise!
3932  {
3933  std::reverse(result.begin(), result.end());
3934  }
3935  }
3936  else if(are_incident(second_v, result[(i + 1) % nbE]))
3937  {
3938  if(v1BeforeV2InFace) // in that case currently the one-ring is
3939  // counter clockwise oriented => change it to
3940  // clockwise!
3941  {
3942  std::reverse(result.begin(), result.end());
3943  }
3944  }
3945  }
3946  }
3947  }
3948  return result;
3949  }
3950 
3951 private:
3956  static void
3958  const edge_container_in_vertex &orderedOneRing,
3959  size_t index,
3961  {
3962 
3963  if(orderedOneRing[index]->get_first_vertex() ==
3964  orderedOneRing[index]->get_second_vertex())
3965  {
3966  oneR.push_back(orderedOneRing[index]->get_first_vertex());
3967  }
3968  else
3969  {
3970  auto edge_incident_faces = incident_faces(orderedOneRing[index]);
3971  auto iter_f = edge_incident_faces.begin(),
3972  iter_f_e = edge_incident_faces.end();
3973  for(; iter_f != iter_f_e; ++iter_f)
3974  {
3975  if(are_incident(*iter_f, v))
3976  {
3977  auto f_incident_vertices = incident_vertices(*iter_f);
3978  auto iter_v = f_incident_vertices.begin(),
3979  iter_v_e = f_incident_vertices.end();
3980 
3981  for(; iter_v != iter_v_e; ++iter_v)
3982  {
3983  if(*iter_v == orderedOneRing[index]->get_first_vertex())
3984  {
3985  ++iter_v;
3986  if(iter_v == iter_v_e)
3987  iter_v = f_incident_vertices.begin();
3988 
3989  if(*iter_v == orderedOneRing[index]->get_second_vertex())
3990  {
3991  oneR.push_back(orderedOneRing[index]->get_second_vertex());
3992  oneR.push_back(orderedOneRing[index]->get_first_vertex());
3993  }
3994  else
3995  {
3996  oneR.push_back(orderedOneRing[index]->get_first_vertex());
3997  oneR.push_back(orderedOneRing[index]->get_second_vertex());
3998  }
3999  break;
4000  }
4001  else if(*iter_v == orderedOneRing[index]->get_second_vertex())
4002  {
4003  ++iter_v;
4004  if(iter_v == iter_v_e)
4005  iter_v = f_incident_vertices.begin();
4006 
4007  if(*iter_v == orderedOneRing[index]->get_first_vertex())
4008  {
4009  oneR.push_back(orderedOneRing[index]->get_first_vertex());
4010  oneR.push_back(orderedOneRing[index]->get_second_vertex());
4011  }
4012  else
4013  {
4014  oneR.push_back(orderedOneRing[index]->get_second_vertex());
4015  oneR.push_back(orderedOneRing[index]->get_first_vertex());
4016  }
4017  break;
4018  }
4019  }
4020 
4021  break;
4022  }
4023  }
4024  }
4025  }
4026 
4027 public:
4036  {
4037  auto &m_One_Ring_Vertices = v->m_One_Ring_Vertices;
4039  // one-ring buffers are emptied for each local operation between an edge
4040  // and a vertex. If you still experience issues on adjacent vertex
4041  // computation you may look inside local operations between an edge and a
4042  // face.
4043  // if (v->m_Is_One_Ring_Vertices_Computed)
4044  //{
4045  // // check for indirect one-ring modification(s)
4046  // auto iter_v = m_One_Ring_Vertices.begin(), iter_v_e =
4047  // m_One_Ring_Vertices.end(); for (; iter_v != iter_v_e; ++iter_v)
4048  // if (is_isolated_vertex(*iter_v) ||
4049  // !are_adjacent(v, *iter_v) )
4050  // {
4051  // v->m_Is_One_Ring_Vertices_Computed = false;
4052  // break;
4053  // }
4054  //}
4056  if(v->m_Is_One_Ring_Vertices_Computed)
4057  {
4058  // DBG std::cout << "Use one-ring-vertices cache" << std::endl;
4059  return m_One_Ring_Vertices; // already in cache
4060  }
4062  // Currently compute the ordered one-ring of vertices
4063  // (not necessarily adjacent vertices if some incident faces are not
4064  // triangular)
4065  // DBG std::cout << "No valid one-ring-vertices cache, computing it" <<
4066  // std::endl;
4067  m_One_Ring_Vertices.clear();
4070  size_t nbE = orderedOneRing.size();
4071  if(nbE == 0)
4072  return m_One_Ring_Vertices;
4073  oneR.reserve(nbE);
4074  if(nbE == 1)
4075  {
4076  update_for_single_edge(v, orderedOneRing, 0, oneR);
4077  }
4078  else
4079  {
4080  vertex_descriptor lastVertex;
4081 
4082  if(are_incident(orderedOneRing[0]->get_second_vertex(),
4083  orderedOneRing[1]))
4084  {
4085  oneR.push_back(orderedOneRing[0]->get_first_vertex());
4086  if(orderedOneRing[0]->get_first_vertex() !=
4087  orderedOneRing[0]->get_second_vertex())
4088  oneR.push_back(orderedOneRing[0]->get_second_vertex());
4089  lastVertex = orderedOneRing[0]->get_second_vertex();
4090  }
4091  else if(are_incident(orderedOneRing[0]->get_first_vertex(),
4092  orderedOneRing[1]))
4093  {
4094  oneR.push_back(orderedOneRing[0]->get_second_vertex());
4095  if(orderedOneRing[0]->get_first_vertex() !=
4096  orderedOneRing[0]->get_second_vertex())
4097  oneR.push_back(orderedOneRing[0]->get_first_vertex());
4098  lastVertex = orderedOneRing[0]->get_first_vertex();
4099  }
4100  else
4101  {
4102  // the 2 one-ring edges are not connected
4103  if(nbE == 2)
4104  {
4105  update_for_single_edge(v, orderedOneRing, 0, oneR);
4106  lastVertex = oneR.back();
4107  }
4108  else
4109  {
4110  bool exist_2_connected_one_ring_edges = false;
4111  size_t i;
4112  for(i = 0; i < nbE - 1; ++i)
4113  {
4114  if(are_incident(orderedOneRing[i]->get_first_vertex(),
4115  orderedOneRing[i + 1]))
4116  {
4117  exist_2_connected_one_ring_edges = true;
4118  break;
4119  }
4120  else if(are_incident(orderedOneRing[i]->get_second_vertex(),
4121  orderedOneRing[i + 1]))
4122  {
4123  exist_2_connected_one_ring_edges = true;
4124  break;
4125  }
4126  }
4127  if(i == nbE - 1)
4128  {
4129  if(are_incident(orderedOneRing[nbE - 1]->get_first_vertex(),
4130  orderedOneRing[0]))
4131  {
4132  exist_2_connected_one_ring_edges = true;
4133  }
4134  else if(are_incident(orderedOneRing[nbE - 1]->get_second_vertex(),
4135  orderedOneRing[0]))
4136  {
4137  exist_2_connected_one_ring_edges = true;
4138  }
4139  }
4140 
4141  if(exist_2_connected_one_ring_edges)
4142  {
4144  for(size_t j = i; j < nbE; ++j)
4145  tmp.push_back(orderedOneRing[j]);
4146  for(size_t j = 0; j < i; ++j)
4147  tmp.push_back(orderedOneRing[j]);
4148 
4149  orderedOneRing.swap(tmp);
4150 
4151  if(are_incident(orderedOneRing[0]->get_second_vertex(),
4152  orderedOneRing[1]))
4153  {
4154  oneR.push_back(orderedOneRing[0]->get_first_vertex());
4155  if(orderedOneRing[0]->get_first_vertex() !=
4156  orderedOneRing[0]->get_second_vertex())
4157  oneR.push_back(orderedOneRing[0]->get_second_vertex());
4158  lastVertex = orderedOneRing[0]->get_second_vertex();
4159  }
4160  else if(are_incident(orderedOneRing[0]->get_first_vertex(),
4161  orderedOneRing[1]))
4162  {
4163  oneR.push_back(orderedOneRing[0]->get_second_vertex());
4164  if(orderedOneRing[0]->get_first_vertex() !=
4165  orderedOneRing[0]->get_second_vertex())
4166  oneR.push_back(orderedOneRing[0]->get_first_vertex());
4167  lastVertex = orderedOneRing[0]->get_first_vertex();
4168  }
4169  }
4170  else
4171  {
4172  update_for_single_edge(v, orderedOneRing, 0, oneR);
4173  lastVertex = oneR.back();
4174  }
4175  }
4176  }
4177 
4178  for(size_t i = 1; i < nbE; ++i)
4179  {
4180  if(are_incident(lastVertex, orderedOneRing[i]))
4181  {
4182  lastVertex = opposite_vertex(orderedOneRing[i], lastVertex);
4183  }
4184  else
4185  {
4186  if(i == nbE - 1)
4187  {
4188  if(are_incident(oneR[0], orderedOneRing[i]))
4189  {
4190  oneR.push_back(opposite_vertex(orderedOneRing[i], oneR[0]));
4191  }
4192  else if(are_incident(oneR[1], orderedOneRing[i]))
4193  {
4194  oneR.push_back(opposite_vertex(orderedOneRing[i], oneR[1]));
4195  }
4196  else
4197  {
4198  update_for_single_edge(v, orderedOneRing, i, oneR);
4199  }
4200 
4201  break;
4202  }
4203  else
4204  {
4205  if(are_incident(orderedOneRing[i]->get_second_vertex(),
4206  orderedOneRing[i + 1]))
4207  {
4208  if(std::find(oneR.begin(),
4209  oneR.end(),
4210  orderedOneRing[i]->get_second_vertex()) !=
4211  oneR.end())
4212  {
4213  if(orderedOneRing[i]->get_first_vertex() !=
4214  orderedOneRing[i]->get_second_vertex())
4215  {
4216  oneR.push_back(orderedOneRing[i]->get_second_vertex());
4217  }
4218  lastVertex = orderedOneRing[i]->get_first_vertex();
4219  }
4220  else
4221  {
4222  if(orderedOneRing[i]->get_first_vertex() !=
4223  orderedOneRing[i]->get_second_vertex())
4224  {
4225  oneR.push_back(orderedOneRing[i]->get_first_vertex());
4226  }
4227  lastVertex = orderedOneRing[i]->get_second_vertex();
4228  }
4229  }
4230  else if(are_incident(orderedOneRing[i]->get_first_vertex(),
4231  orderedOneRing[i + 1]))
4232  {
4233  if(std::find(oneR.begin(),
4234  oneR.end(),
4235  orderedOneRing[i]->get_first_vertex()) != oneR.end())
4236  {
4237  if(orderedOneRing[i]->get_first_vertex() !=
4238  orderedOneRing[i]->get_second_vertex())
4239  {
4240  oneR.push_back(orderedOneRing[i]->get_first_vertex());
4241  }
4242  lastVertex = orderedOneRing[i]->get_second_vertex();
4243  }
4244  else
4245  {
4246  if(orderedOneRing[i]->get_first_vertex() !=
4247  orderedOneRing[i]->get_second_vertex())
4248  {
4249  oneR.push_back(orderedOneRing[i]->get_second_vertex());
4250  }
4251  lastVertex = orderedOneRing[i]->get_first_vertex();
4252  }
4253  }
4254  else
4255  {
4256  // the 2 one-ring edges are not connected (thus edge
4257  // orderedOneRing[i] is isolated in the one-ring
4258  if(orderedOneRing[i]->get_first_vertex() !=
4259  orderedOneRing[i]->get_second_vertex())
4260  {
4261  update_for_single_edge(v, orderedOneRing, i, oneR);
4262  lastVertex = oneR.back();
4263  oneR.pop_back();
4264  }
4265  else
4266  lastVertex = orderedOneRing[i]->get_second_vertex();
4267  }
4268  }
4269  }
4270 
4271  if(std::find(oneR.begin(), oneR.end(), lastVertex) != oneR.end())
4272  {
4273  if((i + 1 == nbE) &&
4274  !is_e_one_ring_connected(orderedOneRing[0], orderedOneRing, true))
4275  {
4276  oneR.push_back(lastVertex);
4277  continue;
4278  }
4279  else if((i + 2 == nbE) &&
4281  orderedOneRing[i + 1], orderedOneRing, true))
4282  {
4283  oneR.push_back(lastVertex);
4284  continue;
4285  }
4286  break;
4287  }
4288 
4289  oneR.push_back(lastVertex);
4290  }
4291  }
4292 
4293  m_One_Ring_Vertices = vertex_container_in_vertex(oneR.begin(), oneR.end());
4294  v->m_Is_One_Ring_Vertices_Computed = true;
4295 
4296  return m_One_Ring_Vertices;
4297  }
4298 
4306  {
4308  v); // ring of vertices not necessarily adjacent
4310  size_t nbE = resFullRing.size();
4311  if(nbE == 0)
4312  return oneR;
4313 
4314  oneR.reserve(nbE);
4316  auto it(resFullRing.begin());
4317  auto ite(resFullRing.end());
4318  while(it != ite)
4319  {
4320  if(are_adjacent(*it, v))
4321  oneR.push_back(*it);
4322 
4323  ++it;
4324  }
4326  return vertex_container_in_vertex(oneR.begin(), oneR.end());
4327  }
4335  {
4336  if(!is_2_manifold_vertex(v))
4337  return false;
4338 
4339  std::set< edge_descriptor > starEdges = get_unordered_one_ring_edges(v);
4340  std::set< vertex_descriptor > starVertices;
4341  auto its = starEdges.begin();
4342  auto itse = starEdges.end();
4343  for (; its != itse; ++its)
4344  {
4345  starVertices.insert((*its)->get_first_vertex());
4346  starVertices.insert((*its)->get_second_vertex());
4347  }
4348 
4349  auto itvs = starVertices.begin();
4350  auto itvse = starVertices.end();
4351  for (; itvs != itvse; ++itvs)
4352  {
4353  if (!is_2_manifold_vertex(*itvs))
4354  return false;
4355  }
4356  return true;
4357  }
4358  // End of one-ring stuff
4360 
4367  edge_descriptor prev_edge)
4368  {
4369  std::vector< edge_descriptor >::iterator
4370  it = face->m_Incident_PtrEdges.begin(),
4371  ite = face->m_Incident_PtrEdges.end();
4372  for(; it != ite; ++it)
4373  {
4374  if((((*it)->get_first_vertex() == prev_edge->get_first_vertex()) &&
4375  ((*it)->get_second_vertex() == prev_edge->get_second_vertex())) ||
4376  (((*it)->get_first_vertex() == prev_edge->get_second_vertex()) &&
4377  ((*it)->get_second_vertex() == prev_edge->get_first_vertex())))
4378  {
4379  ++it;
4380  if(it == ite)
4381  it = face->m_Incident_PtrEdges.begin();
4382  break;
4383  }
4384  }
4385 
4386  if(it == ite)
4387  throw std::invalid_argument(
4388  "Helpers::get_edge_of_face_after_edge(f, pe) -> prev_edge does not "
4389  "belong to input face.");
4390 
4391  return *it;
4392  }
4400  edge_descriptor next_edge)
4401  {
4402  std::vector< edge_descriptor >::iterator
4403  it = face->m_Incident_PtrEdges.begin(),
4404  ite = face->m_Incident_PtrEdges.end();
4405  for(; it != ite; ++it)
4406  {
4407  if((((*it)->get_first_vertex() == next_edge->get_first_vertex()) &&
4408  ((*it)->get_second_vertex() == next_edge->get_second_vertex())) ||
4409  (((*it)->get_first_vertex() == next_edge->get_second_vertex()) &&
4410  ((*it)->get_second_vertex() == next_edge->get_first_vertex())))
4411  {
4412  if(it == face->m_Incident_PtrEdges.begin())
4413  {
4414  it = ite;
4415  }
4416  --it;
4417  break;
4418  }
4419  }
4420 
4421  if(it == ite)
4422  throw std::invalid_argument(
4423  "Helpers::get_edge_of_face_before_edge(f, ne) -> next_edge does not "
4424  "belong to input face.");
4425 
4426  return *it;
4427  }
4428 
4439  edge_descriptor prev_edge,
4441  {
4442  std::vector< edge_descriptor >::iterator
4443  it = face->m_Incident_PtrEdges.begin(),
4444  ite = face->m_Incident_PtrEdges.end();
4445  for(; it != ite; ++it)
4446  {
4447  if((((*it)->get_first_vertex() == prev_edge->get_first_vertex()) &&
4448  ((*it)->get_second_vertex() == prev_edge->get_second_vertex())) ||
4449  (((*it)->get_first_vertex() == prev_edge->get_second_vertex()) &&
4450  ((*it)->get_second_vertex() == prev_edge->get_first_vertex())))
4451  {
4452  ++it;
4453  break;
4454  }
4455  }
4456  face->m_Incident_PtrEdges.insert(it, edge);
4457 
4458  face->clear_vertex_incidency(); // clear the caching incidency relation with
4459  // vertices
4460 
4461  // invalidate one-ring-vertices cache
4462  auto vRange = incident_vertices(face);
4463  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
4464  {
4465  if((*vIt)->m_Is_One_Ring_Vertices_Computed)
4466  {
4467  (*vIt)->m_Is_One_Ring_Vertices_Computed = false;
4468  (*vIt)->m_One_Ring_Vertices.clear(); // free memory
4469  (*vIt)->m_Incident_PtrFaces_Computed = false;
4470  (*vIt)->m_Incident_PtrFaces.clear(); // free memory
4471  }
4472  }
4473  }
4474 
4475 private:
4494  static void add_vertex_to_edge(
4496  vertex_descriptor vertex,
4497  enum vertex_pos position) // without telling it to the vertex
4498  {
4499  vertex_descriptor opp_v;
4500  if(position == vertex_pos::FIRST)
4501  {
4502  edge->set_first_vertex(vertex);
4503  opp_v = edge->get_second_vertex();
4504  }
4505  else
4506  {
4507  edge->set_second_vertex(vertex);
4508  opp_v = edge->get_first_vertex();
4509  }
4510 
4511  vertex->m_Is_One_Ring_Vertices_Computed = false;
4512  vertex->m_One_Ring_Vertices.clear(); // free memory
4513 
4514  if(opp_v != null_vertex())
4515  {
4516  opp_v->m_Is_One_Ring_Vertices_Computed = false;
4517  opp_v->m_One_Ring_Vertices.clear(); // free memory
4518  }
4519  }
4531  static void add_edge_to_vertex(
4532  vertex_descriptor vertex,
4534  edge) // without telling it to the edge (and without verifying that
4535  // the same edge is already incident to "vertex")
4536  {
4537  FEVV::Container::insert(vertex->m_Incident_PtrEdges, edge);
4538 
4539  vertex->m_Is_One_Ring_Vertices_Computed = false;
4540  vertex->m_One_Ring_Vertices.clear(); // free memory
4541  }
4542 
4555  vertex_descriptor vertex)
4556  {
4557  vertex_descriptor opp_v;
4558  if(vertex_position(edge, vertex) == vertex_pos::FIRST)
4559  {
4560  edge->set_first_vertex(null_vertex());
4561  opp_v = edge->get_second_vertex();
4562  }
4563  else
4564  {
4565  edge->set_second_vertex(null_vertex());
4566  opp_v = edge->get_first_vertex();
4567  }
4568 
4569  vertex->m_Is_One_Ring_Vertices_Computed = false;
4570  vertex->m_One_Ring_Vertices.clear(); // free memory
4571 
4572  if(opp_v != null_vertex())
4573  {
4574  opp_v->m_Is_One_Ring_Vertices_Computed = false;
4575  opp_v->m_One_Ring_Vertices.clear(); // free memory
4576  }
4577  }
4591  {
4592  FEVV::Container::erase(vertex->m_Incident_PtrEdges, edge);
4593 
4594  vertex->m_Is_One_Ring_Vertices_Computed = false;
4595  vertex->m_One_Ring_Vertices.clear(); // free memory
4596  }
4607  {
4608  // DBG std::cout << "add edge " << edge << " to face " << face << std::endl;
4609 
4610  FEVV::Container::insert(face->m_Incident_PtrEdges, edge);
4611 
4612  face->clear_vertex_incidency(); // clear the caching incidency relation with
4613  // vertices
4614 
4615  // invalidate one-ring-vertices cache
4616  auto vRange = incident_vertices(face);
4617  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
4618  {
4619  if((*vIt)->m_Is_One_Ring_Vertices_Computed)
4620  {
4621  (*vIt)->m_Is_One_Ring_Vertices_Computed = false;
4622  (*vIt)->m_One_Ring_Vertices.clear(); // free memory
4623  (*vIt)->m_Incident_PtrFaces_Computed = false;
4624  (*vIt)->m_Incident_PtrFaces.clear(); // free memory
4625  }
4626  }
4627  }
4638  {
4639  // DBG std::cout << "add face " << face << " to edge " << edge << std::endl;
4640 
4641  FEVV::Container::insert(edge->m_incident_PtrFaces, face);
4642 
4643  // invalidate edge-vertices cache
4644  auto vRange = incident_vertices(edge);
4645  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
4646  {
4647  (*vIt)->m_Is_One_Ring_Vertices_Computed = false;
4648  (*vIt)->m_One_Ring_Vertices.clear(); // free memory
4649  (*vIt)->m_Incident_PtrFaces_Computed = false;
4650  (*vIt)->m_Incident_PtrFaces.clear(); // free memory
4651  }
4652 
4653  face->clear_vertex_incidency(); // clear the caching incidency relation with
4654  // vertices
4655  }
4666  {
4667  // DBG std::cout << "remove edge " << edge << " from face " << face <<
4668  // std::endl;
4669 
4670  // invalidate one-ring-vertices cache
4671  auto vRange = incident_vertices(face);
4672  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
4673  {
4674  (*vIt)->m_Is_One_Ring_Vertices_Computed = false;
4675  (*vIt)->m_One_Ring_Vertices.clear(); // free memory
4676  (*vIt)->m_Incident_PtrFaces_Computed = false;
4677  (*vIt)->m_Incident_PtrFaces.clear(); // free memory
4678  }
4679 
4680  FEVV::Container::erase(face->m_Incident_PtrEdges, edge);
4681 
4682  face->clear_vertex_incidency(); // clear the caching incidency relation with
4683  // vertices
4684  }
4695  {
4696  // DBG std::cout << "remove face " << face << " from edge " << edge <<
4697  // std::endl;
4698 
4699  // invalidate edge-vertices cache
4700  auto vRange = incident_vertices(edge);
4701  for(auto vIt = vRange.begin(); vIt != vRange.end(); ++vIt)
4702  {
4703  if(*vIt != null_vertex())
4704  {
4705  (*vIt)->m_Is_One_Ring_Vertices_Computed = false;
4706  (*vIt)->m_One_Ring_Vertices.clear(); // free memory
4707  (*vIt)->m_Incident_PtrFaces_Computed = false;
4708  (*vIt)->m_Incident_PtrFaces.clear(); // free memory
4709  }
4710  }
4711 
4712  FEVV::Container::erase(edge->m_incident_PtrFaces, face);
4713 
4714  face->clear_vertex_incidency(); // clear the caching incidency relation with
4715  // vertices
4716  }
4717 
4718 private:
4720 
4722  template< typename RandomIt, typename Compare >
4723  static void sort(RandomIt first, RandomIt last, Compare comp)
4724  {
4725  for(; first != last; ++first)
4726  {
4727  auto min_location = first;
4728  auto first2 = min_location;
4729  ++first2;
4730  for(; first2 != last; ++first2)
4731  {
4732  if(comp(*first2, *min_location))
4733  {
4734  min_location = first2;
4735  }
4736  }
4737  if(min_location != first)
4738  {
4739  std::swap(*first, *min_location);
4740  }
4741  }
4742  }
4745 public:
4746  // HALFEDGE STUFF
4748  {
4749  public:
4752  {
4753  m_source = null_vertex();
4754  m_target = null_vertex();
4755  m_face = null_face();
4756  m_edge = null_edge();
4757  }
4763  face_descriptor f,
4764  bool do_validity_check = true) // validity check must be discarded
4765  // during some topological modifications
4766  {
4767  // check that the halfedge is valid,
4768  // aka there is an edge between the 2 vertices...
4769  std::vector< edge_descriptor > edges = common_edges(s, t);
4770  if(edges.empty())
4771  throw std::runtime_error(
4772  "In AIFHalfEdge::AIFHalfEdge(s, t, f): invalid halfedge, no edge "
4773  "between the two vertices.");
4774 
4775  m_edge = edges[0];
4776 
4777  if(f == null_face())
4778  { // appends for for opposite operation on a border halfedge
4779  m_source =
4780  s; // we do not want a null m_source to ensure the halfedge exists
4781  m_target =
4782  t; // we do not want a null m_target to ensure the halfedge exists
4783  m_face = f;
4784  return;
4785  }
4786  if(do_validity_check)
4787  {
4788  // check that edge belongs to the face
4789  if(std::none_of(edges.cbegin(), edges.cend(), [f](edge_descriptor e) {
4790  return are_incident(e, f);
4791  }))
4792  {
4793  throw std::runtime_error(
4794  "In AIFHalfEdge::AIFHalfEdge(s, t, f): invalid halfedge, not "
4795  "incident to the face.");
4796  }
4797  }
4799 #if 0 // to ensure that the halfedge is inside the face (not needed if you make
4800  // sure of that one step before)
4801  auto edgesRange = incident_edges(f) ;
4802  auto iter = edgesRange.begin() ;
4803  edge_descriptor e = *iter;
4804  ++iter;
4805  edge_descriptor enext = *iter;
4806  while( !( ((e->get_first_vertex() == s) && (e->get_second_vertex()==t)) || ((e->get_first_vertex() == t) && (e->get_second_vertex()==s))) )
4807  {
4808  e = *iter;
4809  ++iter;
4810  if( iter == edgesRange.end() )
4811  iter = edgesRange.begin();
4812  enext = *iter;
4813  }
4814  if( e->get_first_vertex() == enext->get_first_vertex()
4815  || e->get_first_vertex() == enext->get_second_vertex() )
4816  {
4817  m_target = e->get_first_vertex();
4818  m_source = e->get_second_vertex();
4819  }
4820  else if( e->get_second_vertex() == enext->get_first_vertex()
4821  || e->get_second_vertex() == enext->get_second_vertex() )
4822  {
4823  m_target = e->get_second_vertex();
4824  m_source = e->get_first_vertex();
4825  }
4826  else
4827  throw std::runtime_error("In AIFHalfEdge::AIFHalfEdge(s, t, f): unkown case.");
4828 #else
4829  // the halfedge is not always inside the face (except if you make sure of
4830  // it one step before)
4831  m_target = t;
4832  m_source = s;
4833 #endif
4834  m_face = f;
4835  }
4841  face_descriptor f,
4842  edge_descriptor e,
4843  bool do_validity_check = true) // validity check must be discarded
4844  // during some topological modifications
4845  {
4846  m_edge = e;
4847 
4848  if(f == null_face())
4849  { // appends for for opposite operation on a border halfedge
4850  m_source =
4851  s; // we do not want a null m_source to ensure the halfedge exists
4852  m_target =
4853  t; // we do not want a null m_target to ensure the halfedge exists
4854  m_face = f;
4855  return;
4856  }
4857  if(do_validity_check)
4858  {
4859  std::vector< edge_descriptor > edges = common_edges(s, t);
4860  if(edges.empty())
4861  throw std::runtime_error(
4862  "In AIFHalfEdge::AIFHalfEdge(s, t, f): invalid halfedge, no edge "
4863  "between the two vertices.");
4864  // check that edge belongs to the face
4865  if(std::none_of(edges.cbegin(), edges.cend(), [f](edge_descriptor e) {
4866  return are_incident(e, f);
4867  }))
4868  {
4869  throw std::runtime_error(
4870  "In AIFHalfEdge::AIFHalfEdge(s, t, f): invalid halfedge, not "
4871  "incident to the face.");
4872  }
4873  }
4875 #if 0 // to ensure that the halfedge is inside the face (not needed if you make
4876  // sure of that one step before)
4877  auto edgesRange = incident_edges(f);
4878  auto iter = edgesRange.begin();
4879  edge_descriptor edge = *iter;
4880  ++iter;
4881  edge_descriptor enext = *iter;
4882  while (!(((edge->get_first_vertex() == s) && (edge->get_second_vertex() == t)) || ((edge->get_first_vertex() == t) && (edge->get_second_vertex() == s))))
4883  {
4884  edge = *iter;
4885  ++iter;
4886  if (iter == edgesRange.end())
4887  iter = edgesRange.begin();
4888  enext = *iter;
4889  }
4890  if (edge->get_first_vertex() == enext->get_first_vertex()
4891  || edge->get_first_vertex() == enext->get_second_vertex())
4892  {
4893  m_target = edge->get_first_vertex();
4894  m_source = edge->get_second_vertex();
4895  }
4896  else if (edge->get_second_vertex() == enext->get_first_vertex()
4897  || edge->get_second_vertex() == enext->get_second_vertex())
4898  {
4899  m_target = edge->get_second_vertex();
4900  m_source = edge->get_first_vertex();
4901  }
4902  else
4903  throw std::runtime_error("In AIFHalfEdge::AIFHalfEdge(s, t, f): unkown case.");
4904 #else
4905  // the halfedge is not always inside the face (except if you make sure of
4906  // it one step before)
4907  m_target = t;
4908  m_source = s;
4909 #endif
4910  m_face = f;
4911  }
4912 
4914  bool operator==(const AIFHalfEdge &other) const
4915  {
4916  // cannot use the incident face, because of some CGAL topological
4917  // algorithms (the ending condition may be based on an halfedge whose
4918  // incident face has changed)
4919  if(m_edge != other.m_edge)
4920  return false;
4921 
4922  return (
4923  (m_source == other.m_source) ||
4924  (m_target == other.m_target)); // sometimes the source is the same,
4925  // sometimes the target is the same
4926  }
4927 
4928  // SGI (STL) allows != operator based on == operator:
4929  // https://www.sgi.com/tech/stl/EqualityComparable.html cppreference.com:
4930  // "For operator!=, the type shall be EqualityComparable."
4931  bool operator!=(const AIFHalfEdge &other) const
4932  {
4933  return !(*this == other);
4934  }
4935 
4937  bool operator<(const AIFHalfEdge &other) const
4938  {
4939  if(m_edge != other.m_edge)
4940  return m_edge < other.m_edge;
4941  else
4942  return m_face < other.m_face;
4943  }
4944 
4947  {
4948  // parse edges around the face
4949  // look for the edge whose source is current halfedge target
4950  bool found = false;
4951  bool isBorderHalfedge = (m_face == null_face());
4952  if(degree(m_edge) == 0)
4953  {
4954  auto edgesRange = get_target()->GetIncidentEdges();
4955  auto itE = edgesRange.begin();
4956  for(; itE != edgesRange.end(); ++itE)
4957  {
4958  if(are_incident(m_face, *itE))
4959  {
4960  return AIFHalfEdge(get_target(),
4961  opposite_vertex(*itE, get_target()),
4962  m_face,
4963  *itE,
4964  false);
4965  }
4966  }
4967  }
4968  edge_descriptor edge /*, edgeAmb*/;
4969  vertex_type::ptr ptrVn;
4970  if(isBorderHalfedge)
4971  {
4972  // if (is_isolated_vertex(get_target())) // when a modification is in
4973  // progress (e.g. during the collapse of a border edge) [this approach
4974  // does not work] set_target(opposite_vertex(m_edge,
4975  // get_source()));
4976 
4977  // Check if target vertex is a 2-manifold vertex
4979  { // in that case, we know there is only one border edge among
4980  // all edges incident to m_target
4981  auto edgesRange = get_target()->GetIncidentEdges();
4982  auto itE = edgesRange.begin();
4983  for(; itE != edgesRange.end(); ++itE)
4984  {
4985  if(!is_surface_border_edge(*itE))
4986  continue;
4987 
4988  auto verticesPair = (*itE)->GetIncidentVertices();
4989  vertex_type::ptr ptrV1 = verticesPair[0];
4990  vertex_type::ptr ptrV2 = verticesPair[1];
4991 
4992  // we don't know in which order are the vertices in the AIF edge
4993  if(ptrV1 == get_target() && ptrV2 != get_source())
4994  {
4995  found = true;
4996  ptrVn = ptrV2;
4997  edge = *itE;
4998  break;
4999  }
5000 
5001  if(ptrV2 == get_target() && ptrV1 != get_source())
5002  {
5003  found = true;
5004  ptrVn = ptrV1;
5005  edge = *itE;
5006  break;
5007  }
5008  }
5009 
5010  if(!found)
5011  { // particular case due to CGAL low-level topological operations
5012  itE = edgesRange.begin();
5013  for(; itE != edgesRange.end(); ++itE)
5014  {
5015  auto verticesPair = (*itE)->GetIncidentVertices();
5016  vertex_type::ptr ptrV1 = verticesPair[0];
5017  vertex_type::ptr ptrV2 = verticesPair[1];
5018 
5019  // we don't know in which order are the vertices in the AIF edge
5020  if(*itE == m_edge)
5021  {
5022  ++itE; // we take the edge following the edge
5023  if(itE == edgesRange.end())
5024  itE = edgesRange.begin();
5025  found = true;
5026  edge = *itE;
5027  ptrV1 = common_vertex(edge, m_edge);
5028 
5029  return AIFHalfEdge(ptrV1,
5030  opposite_vertex(edge, ptrV1),
5031  incident_faces(edge)[0],
5032  edge,
5033  false);
5034  }
5035  else if(ptrV1 == ptrV2)
5036  {
5037  found = true;
5038  edge = *itE;
5039  return AIFHalfEdge(get_target(),
5040  opposite_vertex(edge, ptrV1),
5041  incident_faces(edge)[0],
5042  edge,
5043  false);
5044  }
5045  }
5046  }
5047  }
5048  else {
5049 #if 1
5050  // We know that the previous edge belongs to another face if the
5051  // vertex is a cut-vertex
5052  if(is_cut_vertex(get_target()))
5053  {
5054  auto currentFaces = incident_faces(m_edge);
5055  auto facesRange = incident_faces(get_target());
5056  auto itF = facesRange.begin();
5057  int cpt = 0;
5058  face_descriptor rightFaceContainingNextHalfEdge;
5059  for(; itF != facesRange.end(); ++itF)
5060  {
5061  if(*itF == currentFaces[0])
5062  break;
5063  }
5064  ++itF;
5065  if(itF == facesRange.end())
5066  itF = facesRange.begin();
5067  rightFaceContainingNextHalfEdge = *itF;
5068  // make sure the selected face is a border face with the right orientation
5069  while (!is_surface_border_face_through_vertex(rightFaceContainingNextHalfEdge, get_target(), true)
5070  || are_locally_edge_connected(currentFaces[0], rightFaceContainingNextHalfEdge)) {
5071  ++itF;
5072  if (itF == facesRange.end())
5073  itF = facesRange.begin();
5074  rightFaceContainingNextHalfEdge = *itF;
5075  }
5076  ++cpt;
5077  if(cpt == 1)
5078  {
5079  auto edgesRange = incident_edges(rightFaceContainingNextHalfEdge);
5080  auto itE = edgesRange.begin();
5081  edge_descriptor candidate1, candidate2;
5082  for(; itE != edgesRange.end(); ++itE)
5083  {
5084  if(((*itE)->get_first_vertex() == get_target()) ||
5085  ((*itE)->get_second_vertex() == get_target()))
5086  {
5087  if(candidate1 == null_edge())
5088  candidate1 = *itE;
5089  else if(candidate2 == null_edge())
5090  candidate2 = *itE;
5091  else
5092  throw std::runtime_error(
5093  "Error in AIFHalfEdge::next(): next halfedge cannot be "
5094  "found in a non-manifold context. Get unkown case "
5095  "while processing a cut-vertex.");
5096  }
5097  }
5098  found = true;
5099  if(is_surface_border_edge(candidate1))
5100  {
5101  if(is_surface_border_edge(candidate2))
5102  {
5103  bool same_orientation = true;
5104  auto vertices_range1 = incident_vertices(rightFaceContainingNextHalfEdge);
5105  auto it1 = vertices_range1.begin();
5106  for (; it1 != vertices_range1.end(); ++it1) {
5107  if (*it1 == get_target()) {
5108  auto it2 = it1;
5109  ++it2;
5110  if (it2 == vertices_range1.end())
5111  it2 = vertices_range1.begin();
5112  if (*it2 == opposite_vertex(candidate1, get_target()))
5113  same_orientation = false;
5114  break;
5115  }
5116  }
5117 
5118  AIFHalfEdge h(opposite_vertex(((same_orientation)?candidate1:candidate2), get_target()),
5119  get_target(),
5120  rightFaceContainingNextHalfEdge,
5121  true);
5122  if(h.prev(m).get_edge() == ((same_orientation)?candidate2:candidate1))
5123  {
5124  ptrVn = opposite_vertex(((same_orientation) ? candidate2 : candidate1), get_target());
5125  edge = ((same_orientation) ? candidate2 : candidate1);
5126  }
5127  else if(h.next(m).get_edge() == ((same_orientation) ? candidate2 : candidate1))
5128  {
5129  ptrVn = opposite_vertex(((same_orientation) ? candidate1 : candidate2), get_target());
5130  edge = ((same_orientation) ? candidate1 : candidate2);
5131  }
5132  }
5133  else
5134  {
5135  ptrVn = opposite_vertex(candidate1, get_target());
5136  edge = candidate1;
5137  }
5138  }
5139  else if(is_surface_border_edge(candidate2))
5140  {
5141  ptrVn = opposite_vertex(candidate2, get_target());
5142  edge = candidate2;
5143  }
5144  else
5145  {
5146  found = false;
5147  throw std::runtime_error(
5148  "Error in AIFHalfEdge::next(): next halfedge cannot be "
5149  "found in a non-manifold context. Get unkown case while "
5150  "processing a cut-vertex.");
5151  }
5152  }
5153  else
5154  throw std::runtime_error(
5155  "Error in AIFHalfEdge::next(): next halfedge cannot be found "
5156  "in a non-manifold context. Current vertex is a cut-vertex.");
5157  }
5158 
5160  throw std::runtime_error(
5161  "Error in AIFHalfEdge::next(): next halfedge cannot be found "
5162  "in a non-manifold context. Current vertex is degenerated.");
5163 
5165  throw std::runtime_error(
5166  "Error in AIFHalfEdge::next(): next halfedge cannot be found "
5167  "in a non-manifold context. Current vertex is isolated.");
5168 #else
5169 
5171  { // we try to get the next halfedge by going though
5172  // the border in the other direction using prev
5173  AIFHalfEdge h(get_source(), get_target(), m_face, false);
5174  do
5175  {
5176  h = h.prev(m);
5177  } while(get_target() != h.get_source());
5178  ptrVn = h.get_target();
5179  edge = h.m_edge;
5180  found = true;
5181  }
5182  else
5183  throw std::runtime_error(
5184  "Error in AIFHalfEdge::next(): next halfedge cannot be found in "
5185  "a non-manifold context.");
5186 #endif
5187  }
5188  }
5189  else
5190  {
5191  auto edgesRange = m_face->GetIncidentEdges();
5192  if((edgesRange.size() == 0) && !are_incident(m_edge, m_face))
5193  {
5194  m_face = null_face();
5195  // need to update face
5196  auto facesRange = incident_faces(m_edge);
5197  auto itF = facesRange.begin();
5198 
5199  for(; itF != facesRange.end(); ++itF)
5200  {
5201  edgesRange = (*itF)->GetIncidentEdges();
5202  auto itE = edgesRange.begin();
5203 
5204  for(; itE != edgesRange.end(); ++itE)
5205  {
5206  // we don't know in which order are the vertices in the AIF edge
5207  if(*itE == m_edge)
5208  {
5209  ++itE;
5210  if(itE == edgesRange.end())
5211  itE = edgesRange.begin();
5212 
5213  if(common_vertex(m_edge, *itE) == get_target())
5214  m_face = *itF;
5215  break;
5216  }
5217  }
5218  }
5219  if(m_face != null_face())
5220  edgesRange = m_face->GetIncidentEdges();
5221  }
5222  auto itE = edgesRange.begin();
5223 
5224  if(edgesRange.size() == 1)
5225  {
5226  if(*itE != m_edge)
5227  {
5228  found = true;
5229  edge = *itE;
5230 
5231  return AIFHalfEdge(get_target(),
5233  m_face,
5234  edge,
5235  false);
5236  }
5237  }
5238  else if(edgesRange.size() == 2)
5239  {
5240  if(*itE == m_edge)
5241  ++itE;
5242 
5243  found = true;
5244  edge = *itE;
5245 
5246  return AIFHalfEdge(get_target(),
5248  m_face,
5249  edge,
5250  false);
5251  }
5252  else
5253  {
5254  bool is_current_Edge_present = false;
5255  for(; itE != edgesRange.end(); ++itE)
5256  {
5257  if(*itE == m_edge)
5258  {
5259  is_current_Edge_present = true;
5260  continue;
5261  }
5262  auto verticesPair = (*itE)->GetIncidentVertices();
5263  vertex_type::ptr ptrV1 = verticesPair[0];
5264  vertex_type::ptr ptrV2 = verticesPair[1];
5265 
5266  // we don't know in which order are the vertices in the AIF edge
5267  if(ptrV1 == get_target() && ptrV2 != get_source())
5268  {
5269  if(found)
5270  {
5271  // edgeAmb = *itE;
5272  if(is_current_Edge_present)
5273  found = false; // ambiguity detected
5274  }
5275  else
5276  {
5277  found = true;
5278  ptrVn = ptrV2;
5279  edge = *itE;
5280  // break;
5281  }
5282  }
5283  else if(ptrV2 == get_target() && ptrV1 != get_source())
5284  {
5285  if(found)
5286  {
5287  // edgeAmb = *itE;
5288  if(is_current_Edge_present)
5289  found = false; // ambiguity detected
5290  }
5291  else
5292  {
5293  found = true;
5294  ptrVn = ptrV1;
5295  edge = *itE;
5296  // break;
5297  }
5298  }
5299  }
5300 
5301  if(!found)
5302  { // particular case due to CGAL low-level topological operations
5303  itE = edgesRange.begin();
5304  for(; itE != edgesRange.end(); ++itE)
5305  {
5306  auto verticesPair = (*itE)->GetIncidentVertices();
5307  vertex_type::ptr ptrV1 = verticesPair[0];
5308  vertex_type::ptr ptrV2 = verticesPair[1];
5309 
5310  // we don't know in which order are the vertices in the AIF edge
5311  if(*itE == m_edge)
5312  {
5313  ++itE; // we take the edge following the edge
5314  if(itE == edgesRange.end())
5315  itE = edgesRange.begin();
5316  found = true;
5317  edge = *itE;
5318  ptrV1 = common_vertex(edge, m_edge);
5319 
5320  return AIFHalfEdge(
5321  ptrV1, opposite_vertex(edge, ptrV1), m_face, edge, false);
5322  }
5323  else if(ptrV1 == ptrV2)
5324  {
5325  found = true;
5326  edge = *itE;
5327  return AIFHalfEdge(get_target(),
5328  opposite_vertex(edge, ptrV1),
5329  m_face,
5330  edge,
5331  false);
5332  }
5333  }
5334  }
5335  }
5336  }
5337 
5338  // abort if no edge with the right source is found
5339  if(!found)
5340  throw std::runtime_error(
5341  "Error in AIFHalfEdge::next(): next halfedge not found in face! "
5342  "Maybe the input halfedge is invalid (face/vertices mismatch).");
5343 
5344  // next edge found, return a halfedge
5345  return AIFHalfEdge(get_target(), ptrVn, m_face, edge, false);
5346  }
5347 
5350  {
5351  // parse edges around the face
5352  // look for the edge whose target is current halfedge source
5353  bool found = false;
5354  bool isBorderHalfedge = (m_face == null_face());
5356  vertex_type::ptr ptrVn;
5357  if(isBorderHalfedge)
5358  {
5359  // Check if target vertex is a 2-manifold vertex
5361  { // in that case, we know there is only one border edge among
5362  // all edges incident to get_source()
5363  auto edgesRange = get_source()->GetIncidentEdges();
5364  auto itE = edgesRange.begin();
5365  for(; itE != edgesRange.end(); ++itE)
5366  {
5367  if(!is_surface_border_edge(*itE))
5368  continue;
5369 
5370  auto verticesPair = (*itE)->GetIncidentVertices();
5371  vertex_type::ptr ptrV1 = verticesPair[0];
5372  vertex_type::ptr ptrV2 = verticesPair[1];
5373 
5374  // we don't know in which order are the vertices in the AIF edge
5375  if(ptrV1 == get_source() && ptrV2 != get_target())
5376  {
5377  found = true;
5378  ptrVn = ptrV2;
5379  edge = *itE;
5380  break;
5381  }
5382 
5383  if(ptrV2 == get_source() && ptrV1 != get_target())
5384  {
5385  found = true;
5386  ptrVn = ptrV1;
5387  edge = *itE;
5388  break;
5389  }
5390  }
5391  }
5392  else
5393  {
5394  // We know that the previous edge belongs to another face if the
5395  // vertex is a cut-vertex
5396  if(is_cut_vertex(get_source()))
5397  {
5398  auto currentFaces = incident_faces(m_edge);
5399  auto facesRange = incident_faces(get_source());
5400  auto itF = facesRange.begin();
5401  int cpt = 0;
5402  face_descriptor rightFaceContainingPrevHalfEdge;
5403  for(; itF != facesRange.end(); ++itF)
5404  {
5405  if(*itF == currentFaces[0])
5406  break;
5407  }
5408  if(itF == facesRange.begin())
5409  itF = facesRange.end();
5410  --itF;
5411  rightFaceContainingPrevHalfEdge = *itF;
5412  // make sure the selected face is a border face with the right orientation
5413  while (!is_surface_border_face_through_vertex(rightFaceContainingPrevHalfEdge, get_source(), false)
5414  || are_locally_edge_connected(currentFaces[0], rightFaceContainingPrevHalfEdge)){
5415  if (itF == facesRange.begin())
5416  itF = facesRange.end();
5417  --itF;
5418  rightFaceContainingPrevHalfEdge = *itF;
5419  }
5420  ++cpt;
5421  if(cpt == 1)
5422  {
5423  auto edgesRange = incident_edges(rightFaceContainingPrevHalfEdge);
5424  auto itE = edgesRange.begin();
5425  edge_descriptor candidate1, candidate2;
5426  for(; itE != edgesRange.end(); ++itE)
5427  {
5428  if(((*itE)->get_first_vertex() == get_source()) ||
5429  ((*itE)->get_second_vertex() == get_source()))
5430  {
5431  if(candidate1 == null_edge())
5432  candidate1 = *itE;
5433  else if(candidate2 == null_edge())
5434  candidate2 = *itE;
5435  else
5436  throw std::runtime_error(
5437  "Error in AIFHalfEdge::prev(): prev halfedge cannot be "
5438  "found in a non-manifold context. Get unkown case "
5439  "while processing a cut-vertex.");
5440  }
5441  }
5442  found = true;
5443  if(is_surface_border_edge(candidate1))
5444  {
5445  if(is_surface_border_edge(candidate2))
5446  {
5447  bool same_orientation = true;
5448  auto vertices_range1 = incident_vertices(rightFaceContainingPrevHalfEdge);
5449  auto it1 = vertices_range1.begin();
5450  for (; it1 != vertices_range1.end(); ++it1) {
5451  if (*it1 == get_source()) {
5452  auto it2 = it1;
5453  ++it2;
5454  if (it2 == vertices_range1.end())
5455  it2 = vertices_range1.begin();
5456  if (*it2 == opposite_vertex(candidate1, get_source()))
5457  same_orientation = false;
5458  break;
5459  }
5460  }
5461 
5462  AIFHalfEdge h(opposite_vertex(((same_orientation) ? candidate1 : candidate2), get_source()),
5463  get_source(),
5464  rightFaceContainingPrevHalfEdge,
5465  true);
5466  if(h.prev(m).get_edge() == candidate2)
5467  {
5468  ptrVn = opposite_vertex(candidate1, get_source());
5469  edge = candidate1;
5470  }
5471  else if(h.next(m).get_edge() == candidate2)
5472  {
5473  ptrVn = opposite_vertex(candidate2, get_source());
5474  edge = candidate2;
5475  }
5476  }
5477  else
5478  {
5479  ptrVn = opposite_vertex(candidate1, get_source());
5480  edge = candidate1;
5481  }
5482  }
5483  else if(is_surface_border_edge(candidate2))
5484  {
5485  ptrVn = opposite_vertex(candidate2, get_source());
5486  edge = candidate2;
5487  }
5488  else
5489  {
5490  found = false;
5491  throw std::runtime_error(
5492  "Error in AIFHalfEdge::prev(): prev halfedge cannot be "
5493  "found in a non-manifold context. Get unkown case while "
5494  "processing a cut-vertex.");
5495  }
5496  }
5497  else
5498  throw std::runtime_error(
5499  "Error in AIFHalfEdge::prev(): prev halfedge cannot be found "
5500  "in a non-manifold context. Current vertex is a cut-vertex.");
5501  }
5502 
5504  throw std::runtime_error(
5505  "Error in AIFHalfEdge::prev(): prev halfedge cannot be found "
5506  "in a non-manifold context. Current vertex is degenerated.");
5507 
5509  throw std::runtime_error(
5510  "Error in AIFHalfEdge::prev(): prev halfedge cannot be found "
5511  "in a non-manifold context. Current vertex is isolated.");
5512  }
5513  }
5514  else
5515  {
5516  auto edgesRange = m_face->GetIncidentEdges();
5517 
5518  if((edgesRange.size() == 0) && !are_incident(m_edge, m_face))
5519  {
5520  m_face = null_face();
5521  // need to update face
5522  auto facesRange = incident_faces(m_edge);
5523  auto itF = facesRange.begin();
5524 
5525  for(; itF != facesRange.end(); ++itF)
5526  {
5527  edgesRange = (*itF)->GetIncidentEdges();
5528  auto itE = edgesRange.begin();
5529 
5530  for(; itE != edgesRange.end(); ++itE)
5531  {
5532  // we don't know in which order are the vertices in the AIF edge
5533  if(*itE == m_edge)
5534  {
5535  ++itE;
5536  if(itE == edgesRange.end())
5537  itE = edgesRange.begin();
5538 
5539  if(common_vertex(m_edge, *itE) == get_target())
5540  m_face = *itF;
5541  break;
5542  }
5543  }
5544  }
5545  if(m_face != null_face())
5546  edgesRange = m_face->GetIncidentEdges();
5547  }
5548 
5549  auto itE = edgesRange.begin();
5550 
5551  if(edgesRange.size() == 1)
5552  {
5553  if(*itE != m_edge)
5554  {
5555  found = true;
5556  edge = *itE;
5557 
5558  return AIFHalfEdge(
5560  }
5561  }
5562  else if(edgesRange.size() == 2)
5563  {
5564  if(*itE == m_edge)
5565  ++itE;
5566 
5567  found = true;
5568  edge = *itE;
5569 
5570  return AIFHalfEdge(
5572  }
5573  else
5574  {
5575  bool is_current_Edge_present = false;
5576  for(; itE != edgesRange.end(); ++itE)
5577  {
5578  if(*itE == m_edge)
5579  {
5580  is_current_Edge_present = true;
5581  continue;
5582  }
5583  auto verticesPair = (*itE)->GetIncidentVertices();
5584  vertex_type::ptr ptrV1 = verticesPair[0];
5585  vertex_type::ptr ptrV2 = verticesPair[1];
5586 
5587  // we don't know in which order are the vertices in the AIF edge
5588  if(ptrV1 == get_source() && ptrV2 != get_target())
5589  {
5590  if(found)
5591  {
5592  if(is_current_Edge_present)
5593  found = false; // ambiguity detected
5594  }
5595  else
5596  {
5597  found = true;
5598  ptrVn = ptrV2;
5599  edge = *itE;
5600  // break;
5601  }
5602  }
5603  else if(ptrV2 == get_source() && ptrV1 != get_target())
5604  {
5605  if(found)
5606  {
5607  if(is_current_Edge_present)
5608  found = false; // ambiguity detected
5609  }
5610  else
5611  {
5612  found = true;
5613  ptrVn = ptrV1;
5614  edge = *itE;
5615  // break;
5616  }
5617  }
5618  }
5619  if(!found)
5620  { // particular case due to CGAL low-level topological operations
5621  itE = edgesRange.begin();
5622  for(; itE != edgesRange.end(); ++itE)
5623  {
5624  auto verticesPair = (*itE)->GetIncidentVertices();
5625  vertex_type::ptr ptrV1 = verticesPair[0];
5626  vertex_type::ptr ptrV2 = verticesPair[1];
5627 
5628  // we don't know in which order are the vertices in the AIF edge
5629  if(*itE == m_edge)
5630  {
5631  if(itE == edgesRange.begin())
5632  itE = edgesRange.end();
5633  --itE; // we take the edge preceding the edge
5634 
5635  found = true;
5636  edge = *itE;
5637  ptrV1 = common_vertex(edge, m_edge);
5638  return AIFHalfEdge(
5639  opposite_vertex(edge, ptrV1), ptrV1, m_face, edge, false);
5640  }
5641  else if(ptrV1 == ptrV2)
5642  {
5643  found = true;
5644  edge = *itE;
5645  return AIFHalfEdge(get_target(),
5646  opposite_vertex(edge, ptrV1),
5647  m_face,
5648  edge,
5649  false);
5650  }
5651  }
5652  }
5653  }
5654  }
5655 
5656  // abort if no edge with the right source is found
5657  if(!found)
5658  throw std::runtime_error(
5659  "Error in AIFHalfEdge::prev(): prev halfedge not found in face! "
5660  "Maybe the input halfedge is invalid (face/vertices mismatch).");
5661 
5662  // prev edge found, return a halfedge
5663  return AIFHalfEdge(ptrVn, get_source(), m_face, edge, false);
5664  }
5665 
5668  {
5669  edge_descriptor good_e = m_edge;
5670  face_descriptor op_f; // op_f can be null for border edge (not an issue)
5671  int cpt = 0;
5672  // parse edges around the face
5673  if(m_face == null_face())
5674  {
5675  auto facesRange = incident_faces(good_e);
5676  auto itF = facesRange.begin();
5677 
5678  for(; itF != facesRange.end(); ++itF, ++cpt)
5679  {
5680  op_f = *itF;
5681  }
5682  if(cpt != 1)
5683  {
5684  return AIFHalfEdge(
5685  get_target(),
5686  get_source(),
5687  null_face(),
5688  good_e,
5689  false); // for some Euler operations, we can handle non-valid
5690  // halfedge at a time (e.g. split_vertex)
5691  }
5692  return AIFHalfEdge(get_target(), get_source(), op_f, good_e, false);
5693  }
5694 
5695  auto facesRange = incident_faces(good_e);
5696  auto itF = facesRange.begin();
5697 
5698  for(; itF != facesRange.end(); ++itF, ++cpt)
5699  {
5700  if(*itF != m_face)
5701  op_f = *itF;
5702  }
5703  if(cpt > 2)
5704  {
5705  throw std::invalid_argument(
5706  "AIFTopologyHelpers::opposite(h, m) -> several opposite edges "
5707  "exist, cannot proceed.");
5708  }
5709 
5710  return AIFHalfEdge(get_target(), get_source(), op_f, good_e, false);
5711  }
5712 
5714  inline vertex_descriptor get_source(void) const { return m_source; }
5716  inline vertex_descriptor get_target(void) const { return m_target; }
5718  inline face_descriptor get_face(void) const { return m_face; }
5720  inline edge_descriptor get_edge(void) const { return m_edge; }
5721 
5723  void set_source(vertex_descriptor new_source) { m_source = new_source; }
5725  void set_target(vertex_descriptor new_target) { m_target = new_target; }
5727  void set_face(face_descriptor new_face) { m_face = new_face; }
5729  void set_edge(edge_descriptor new_edge) { m_edge = new_edge; }
5730 
5732  friend std::ostream &operator<<(std::ostream &stream, const AIFHalfEdge &h)
5733  {
5734  stream << "he(source=" << h.get_source() << ", target=" << h.get_target()
5735  << ", face=" << h.get_face() << ")";
5736  return stream;
5737  }
5738 
5739  // member attributes
5740  protected:
5743  m_target; // redundant information, but needed for some topological
5744  // operations due to non persistency of halfedge
5745 
5748  m_edge; // needed to handle modifications (the current
5749  // halfedge_descriptor is not a pointer or smart pointer, thus
5750  // all functions working on halfedge_descriptor works on copy
5751  // and not on original data). however the edge_descriptor is a
5752  // smart point, so we can work on original data.
5753  };
5754 
5756 
5762 
5770  {
5771  auto edgesRange = incident_edges(face);
5772  if(edgesRange.begin() == edgesRange.end())
5773  throw std::invalid_argument(
5774  "AIFTopologyHelpers::halfedge(f, m) -> no edge incident to face.");
5775 
5776  edge_descriptor e = *(edgesRange.begin());
5777 
5778  // the vertex that is common with the next edge in face-incident-edges
5779  // container must be the halfedge target
5780  edge_descriptor enext = *(edgesRange.begin() + 1);
5782  if(e->get_first_vertex() == enext->get_first_vertex() ||
5783  e->get_first_vertex() == enext->get_second_vertex())
5784  {
5785  target = e->get_first_vertex();
5786  source = e->get_second_vertex();
5787  }
5788  else if(e->get_second_vertex() == enext->get_first_vertex() ||
5789  e->get_second_vertex() == enext->get_second_vertex())
5790  {
5791  target = e->get_second_vertex();
5792  source = e->get_first_vertex();
5793  }
5794  else
5795  throw std::runtime_error(
5796  "AIFTopologyHelpers::halfedge(f, m) -> the second edge in "
5797  "face-incident-edges container don't share any vertex with the first "
5798  "edge in container.");
5799 
5800  // DBG*/ std::cout << __FILE__ << ":" << __LINE__ << " halfedge(face=" <<
5801  // face << ", mesh=" << &mesh << ")] = " << AIFHalfEdge(source, target,
5802  // face)
5803  // << " first_face_edge = " << e << " second_face_edge = " << enext
5804  // << std::endl;
5805 
5806  return AIFHalfEdge(source, target, face, e, false);
5807  }
5808 
5816  {
5817  auto edgesRange = incident_edges(v);
5818  if(edgesRange.begin() == edgesRange.end())
5819  return null_halfedge(); // throw
5820  // std::invalid_argument("AIFTopologyHelpers::halfedge(v,
5821  // m) -> no edge incident to vertex.");
5822 
5823  auto itE = edgesRange.begin();
5824  edge_descriptor e = *itE;
5825  auto facesRange = incident_faces(e);
5826  while(itE != edgesRange.end())
5827  {
5828  if((facesRange.size() > 0) && (facesRange.size() < 3))
5829  break;
5830  ++itE;
5831  if(itE != edgesRange.end())
5832  {
5833  e = *itE;
5834  facesRange = incident_faces(e);
5835  }
5836  }
5837  if(itE == edgesRange.end())
5838  throw std::invalid_argument(
5839  "AIFTopologyHelpers::halfedge(v, m) -> cannot find a manifold edge.");
5840 
5841  if(facesRange.begin() == facesRange.end())
5842  throw std::invalid_argument("AIFTopologyHelpers::halfedge(v, m) -> no "
5843  "face incident to selected edge.");
5844 
5845  face_descriptor f = *(facesRange.begin());
5846 
5847  // select the right face
5848  auto edgesRangeF = incident_edges(f);
5849  auto iter = edgesRangeF.begin();
5850  edge_descriptor eF = *iter;
5851  ++iter;
5852  edge_descriptor eFnext = *iter;
5853  while(!(((eF->get_first_vertex() == v) &&
5854  (eF->get_second_vertex() == opposite_vertex(e, v))) ||
5855  ((eF->get_first_vertex() == opposite_vertex(e, v)) &&
5856  (eF->get_second_vertex() == v))))
5857  {
5858  eF = *iter;
5859  ++iter;
5860  if(iter == edgesRangeF.end())
5861  iter = edgesRangeF.begin();
5862  eFnext = *iter;
5863  }
5864  if(eF->get_first_vertex() == eFnext->get_first_vertex() ||
5865  eF->get_first_vertex() == eFnext->get_second_vertex())
5866  {
5867  if(eF->get_first_vertex() != v)
5868  {
5869  if(facesRange.size() == 1)
5870  f = null_face();
5871  else
5872  f = *(facesRange.begin() + 1);
5873  }
5874  }
5875  else if(eF->get_second_vertex() == eFnext->get_first_vertex() ||
5876  eF->get_second_vertex() == eFnext->get_second_vertex())
5877  {
5878  if(eF->get_second_vertex() != v)
5879  {
5880  if(facesRange.size() == 1)
5881  f = null_face();
5882  else
5883  f = *(facesRange.begin() + 1);
5884  }
5885  }
5887  return AIFHalfEdge(
5888  opposite_vertex(e, v),
5889  v,
5890  f,
5891  e,
5892  false); // here we cannot propose an halfedge outside the face!!
5893  }
5894 
5906  static halfedge_descriptor
5908  {
5909  edge_descriptor good_e = common_edge(src, target);
5910  if(good_e == null_edge())
5911  return halfedge_descriptor();
5913  face_descriptor op_f =
5914  null_face(); // op_f can be null for border edge (not an issue)
5916  int cpt = 0;
5917  auto facesRange = incident_faces(good_e);
5918  auto itF = facesRange.begin();
5919 
5920  for(; itF != facesRange.end(); ++itF, ++cpt)
5921  {
5922  if (is_degenerated_face(*itF))
5923  {
5924  throw std::invalid_argument("AIFTopologyHelpers::halfedge(src, target, "
5925  "m) -> an incident face is degenerated.");
5926  }
5927 
5928  edge_descriptor next_good_e;
5929 
5930  auto edgesRange = (*itF)->GetIncidentEdges();
5931  auto itE = edgesRange.begin();
5932 
5933  for(; itE != edgesRange.end(); ++itE)
5934  {
5935  if((((*itE)->get_first_vertex() == src) &&
5936  ((*itE)->get_second_vertex() == target)) ||
5937  (((*itE)->get_first_vertex() == target) &&
5938  ((*itE)->get_second_vertex() == src)))
5939  {
5940  good_e = *itE;
5941  ++itE;
5942  if(itE == edgesRange.end())
5943  itE = edgesRange.begin();
5944  next_good_e = *itE;
5945  // if the common vertex between good_e and next_good_e is src then,
5946  // the halfedge to return has no incident face. else, if the common
5947  // vertex between good_e and next_good_e is target, then the current
5948  // face is incident to halfedge.
5949  if(common_vertex(good_e, next_good_e) == target)
5950  {
5951  op_f = *itF;
5952  }
5953  break;
5954  }
5955  }
5956  }
5957  if(cpt == 0 || cpt > 2)
5958  {
5959  throw std::invalid_argument("AIFTopologyHelpers::halfedge(src, target, "
5960  "m) -> current halfedge is not manifold.");
5961  }
5963  return halfedge_descriptor(src, target, op_f, good_e, false);
5964  }
5975  {
5976  if((edge->get_first_vertex() == null_vertex()) ||
5977  (edge->get_second_vertex() == null_vertex()))
5978  {
5980  h.set_source(edge->get_first_vertex());
5981  h.set_target(edge->get_second_vertex());
5982  h.set_edge(edge);
5983  return h;
5984  }
5985  else
5986  return halfedge(
5987  edge->get_first_vertex(), edge->get_second_vertex(), mesh);
5988  }
5999  {
6000  return h.get_edge();
6001  }
6003 
6013  static void
6015  {
6016  edge_descriptor good_e = h.get_edge();
6017  if(good_e == null_edge())
6018  throw std::invalid_argument("AIFTopologyHelpers::set_target(h, v, m) -> "
6019  "halfedge does not belong to input mesh.");
6020 
6022  good_e,
6023  target,
6025  good_e,
6026  opposite_vertex(good_e,
6027  h.get_source()))); // h.get_source() is consistent,
6028  // not necesseraly h.get_target()
6029  h.set_target(
6030  target); // to update the halfedge (needed for following operations)
6031  }
6040  static void
6042  {
6043  edge_descriptor good_e = h.get_edge();
6044  if(good_e == null_edge())
6045  throw std::invalid_argument("AIFTopologyHelpers::set_halfedge(v, h, m) "
6046  "-> halfedge does not belong to input mesh.");
6047 
6048  if(std::find(target->GetIncidentEdges().begin(),
6049  target->GetIncidentEdges().end(),
6050  good_e) == target->GetIncidentEdges().end())
6051  add_edge_to_vertex(target, good_e);
6052  }
6066  static void
6068  {
6069  assert(h1 != h2);
6070  assert(h1 != h2.opposite(mesh));
6071  face_descriptor face = h1.get_face();
6072  if(face == null_face())
6073  {
6074  face = h2.get_face(); // some CGAL functions assume that a call to
6075  // set_next can be done with h1 having a null face
6076  // and h2 having a null face too
6077  }
6078  edge_descriptor prev_edge = h1.get_edge();
6079  if(prev_edge == null_edge())
6080  throw std::invalid_argument("AIFTopologyHelpers::set_next(h1, h2, m) -> "
6081  "halfedge h1 does not belong to input mesh.");
6082 
6083  edge_descriptor edge_to_insert = h2.get_edge();
6084  if(edge_to_insert == null_edge())
6085  throw std::invalid_argument("AIFTopologyHelpers::set_next(h1, h2, m) -> "
6086  "halfedge h2 does not belong to input mesh.");
6087  halfedge_descriptor current_next_h1 = h1.next(mesh),
6088  current_next_h1_op = current_next_h1.opposite(mesh);
6089  if(current_next_h1 != h2)
6090  {
6091  if(face != null_face())
6092  remove_edge_from_face(face, current_next_h1.get_edge());
6093  if(are_incident(common_vertex(h1.get_edge(), current_next_h1.get_edge()),
6094  current_next_h1.get_edge()))
6096  common_vertex(h1.get_edge(), current_next_h1.get_edge()),
6097  current_next_h1.get_edge());
6098  if(face != h2.get_face())
6099  {
6100  std::vector< edge_descriptor > edges_to_insert_in_face;
6101  if(face->GetDegree() > 0)
6102  {
6103  halfedge_descriptor tmp = h2;
6104  while(tmp != current_next_h1_op)
6105  {
6106  edges_to_insert_in_face.push_back(tmp.get_edge());
6107  tmp = tmp.next(mesh);
6108  }
6109 
6110  if(!are_incident(edge_to_insert, face))
6111  {
6113  edges_to_insert_in_face, face, prev_edge);
6115  edges_to_insert_in_face,
6116  current_next_h1_op.get_face()); // to ensure 2-manifoldness
6117  }
6118  h2.set_face(
6119  face); // to update the halfedge (needed for following operations)
6120  }
6121  else
6122  {
6123  if(is_dangling_edge(current_next_h1.get_edge()))
6124  {
6125  if(std::find(current_next_h1.get_edge()
6126  ->get_first_vertex()
6127  ->GetIncidentEdges()
6128  .begin(),
6129  current_next_h1.get_edge()
6130  ->get_first_vertex()
6131  ->GetIncidentEdges()
6132  .end(),
6133  current_next_h1.get_edge()) !=
6134  current_next_h1.get_edge()
6135  ->get_first_vertex()
6136  ->GetIncidentEdges()
6137  .end())
6139  current_next_h1.get_edge()->get_first_vertex(),
6140  current_next_h1.get_edge());
6141 
6142  if(std::find(current_next_h1.get_edge()
6143  ->get_second_vertex()
6144  ->GetIncidentEdges()
6145  .begin(),
6146  current_next_h1.get_edge()
6147  ->get_second_vertex()
6148  ->GetIncidentEdges()
6149  .end(),
6150  current_next_h1.get_edge()) !=
6151  current_next_h1.get_edge()
6152  ->get_second_vertex()
6153  ->GetIncidentEdges()
6154  .end())
6156  current_next_h1.get_edge()->get_second_vertex(),
6157  current_next_h1.get_edge());
6158  }
6160  auto h1FaceRange = incident_faces(h1.get_edge());
6161  auto h2FaceRange = incident_faces(h2.get_edge());
6162  auto h1itF = h1FaceRange.begin();
6163  while(h1itF != h1FaceRange.end())
6164  {
6165  auto h2itF = h2FaceRange.begin();
6166  while(h2itF != h2FaceRange.end())
6167  {
6168  if(*h1itF == *h2itF)
6169  common_face = *h1itF;
6170  ++h2itF;
6171  }
6172  ++h1itF;
6173  }
6174 
6175  h1.set_face(common_face);
6176  h2.set_face(common_face);
6177  }
6178  }
6179  // else
6180  // throw std::runtime_error("AIFTopologyHelpers::set_next(h1, h2, m) ->
6181  // case next(h1,m)!=h2 and face(h1,m)==face(h2,m) not yet managed.");
6182  }
6183  assert(h1.next(mesh) == h2);
6184  assert(h2.prev(mesh) == h1);
6185  }
6186 
6198  static void
6200  {
6202  if(edge == null_edge())
6203  throw std::invalid_argument("AIFTopologyHelpers::set_face(h, f, m) -> "
6204  "halfedge does not belong to input mesh.");
6205 
6206  if((face != null_face()) && !are_incident(edge, face))
6207  {
6209  }
6210  else if((face == null_face()) && (h.get_face() != null_face()))
6211  {
6212  if(are_incident(edge, h.get_face()))
6214  }
6215  if(h.get_face() != face)
6216  h.set_face(
6217  face); // to update the halfedge (needed for following operations)
6218  }
6232  static void
6234  {
6235  if(face == null_face())
6236  throw std::invalid_argument(
6237  "AIFTopologyHelpers::set_halfedge(f, h, m) -> face is a null face.");
6239  if(edge == null_edge())
6240  throw std::invalid_argument("AIFTopologyHelpers::set_halfedge(f, h, m) "
6241  "-> halfedge does not belong to input mesh.");
6242  if(!are_incident(face, edge))
6243  {
6245  }
6246  }
6247  // END OF HALFEDGE STUFF
6250 };
6251 
6252 } // namespace AIF
6253 } // namespace DataStructures
6254 } // namespace FEVV
FEVV::DataStructures::AIF::AIFTopologyHelpers::degree
static size_type degree(face_descriptor face)
Definition: AIFTopologyHelpers.h:1501
FEVV::DataStructures::AIF::AIFTopologyHelpers::set_target
static void set_target(halfedge_descriptor h, vertex_descriptor target, AIFMesh &)
Definition: AIFTopologyHelpers.h:6014
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_face
static void remove_face(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:3414
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_interior_edge
static bool is_surface_interior_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:971
FEVV::DataStructures::AIF::AIFTopologyHelpers::check_mesh_validity
static bool check_mesh_validity(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2681
FEVV::DataStructures::AIF::AIFMesh::GetNumberOfEdges
unsigned int GetNumberOfEdges() const
Definition: AIFMesh.hpp:214
FEVV::DataStructures::AIF::AIFTopologyHelpers::edges
static boost::iterator_range< edge_container::const_iterator > edges(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2272
FEVV::DataStructures::AIF::AIFEdge::VertexContainerType
std::array< ptr_vertex, 2 > VertexContainerType
Definition: AIFEdge.hpp:64
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_all_faces
static void unlink_all_faces(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3261
FEVV::DataStructures::AIF::AIFTopologyHelpers::halfedge_descriptor
AIFHalfEdge halfedge_descriptor
Definition: AIFTopologyHelpers.h:5755
FEVV::DataStructures::AIF::AIFTopologyHelpers::mesh_type
AIFMesh mesh_type
Definition: AIFTopologyHelpers.h:59
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edge
static edge_descriptor common_edge(vertex_descriptor vertex1, vertex_descriptor vertex2)
Definition: AIFTopologyHelpers.h:458
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_vertices
static boost::iterator_range< vertex_container_in_edge::const_iterator > incident_vertices(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1189
FEVV::DataStructures::AIF::AIFVertex::ptr
boost::shared_ptr< self > ptr
Definition: AIFVertex.hpp:47
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_faces
static void remove_faces(InputIt first, InputIt last, MeshType &mesh)
Definition: AIFTopologyHelpers.h:3193
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static void add_edge(vertex_descriptor vertex, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3346
FEVV::DataStructures::AIF::AIFTopologyHelpers::faces
static boost::iterator_range< face_container::const_iterator > faces(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2628
FEVV::DataStructures::AIF::next
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor next(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the next halfedge around its face.
Definition: Graph_traits_aif.h:599
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_border_face
static bool is_surface_border_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1652
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::operator==
bool operator==(const AIFHalfEdge &other) const
fulfill the EqualityComparable concept
Definition: AIFTopologyHelpers.h:4914
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_vertex
static bool is_2_manifold_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:237
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::m_edge
edge_descriptor m_edge
Definition: AIFTopologyHelpers.h:5748
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_faces
static size_type num_faces(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2200
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_edges_and_face
static void unlink_edges_and_face(std::vector< edge_descriptor > edges, face_descriptor face)
Definition: AIFTopologyHelpers.h:1423
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_container_in_vertex
vertex_type::EdgeContainerType edge_container_in_vertex
Definition: AIFTopologyHelpers.h:75
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static face_descriptor add_face(ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2887
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_container
mesh_type::EdgeContainerType edge_container
Definition: AIFTopologyHelpers.h:84
FEVV::DataStructures::AIF::AIFTopologyHelpers::opposite_vertex
static vertex_descriptor opposite_vertex(edge_descriptor edge, vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1270
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_isolated_edge
static bool is_isolated_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:995
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(vertex_descriptor v, vertex_descriptor u, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3096
FEVV::DataStructures::AIF::AIFMesh::GetEdges
boost::iterator_range< EdgeContainerType::const_iterator > GetEdges() const
Definition: AIFMesh.hpp:171
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_mesh
static bool is_2_manifold_mesh(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2317
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_edge
static bool is_2_manifold_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1441
FEVV::DataStructures::AIF::AIFTopologyHelpers::border_edges
static boost::iterator_range< edge_container::const_iterator > border_edges(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2594
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge
Definition: AIFTopologyHelpers.h:4748
FEVV::DataStructures::AIF::AIFTopologyHelpers::ref_cmesh
std::add_lvalue_reference< const mesh_type >::type ref_cmesh
Definition: AIFTopologyHelpers.h:69
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(vertex_descriptor vertex, vertex_descriptor u, vertex_descriptor v)
Function determining if the arguments share an incidence relation.
Definition: AIFTopologyHelpers.h:327
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_adjacent
static bool are_adjacent(face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:1815
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_edges
static boost::iterator_range< edge_container::const_iterator > sort_edges(ref_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:1490
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge_to_vertex
static void add_edge_to_vertex(vertex_descriptor vertex, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:4531
FEVV::DataStructures::AIF::AIFTopologyHelpers::ptr_cmesh
const mesh_type * ptr_cmesh
Definition: AIFTopologyHelpers.h:67
FEVV::DataStructures::AIF::AIFTopologyHelpers::link_edge_and_face
static void link_edge_and_face(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:1305
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_descriptor
vertex_type::ptr vertex_descriptor
Definition: AIFTopologyHelpers.h:70
FEVV::DataStructures::AIF::AIFVertex
This class represents a vertex used by AIFMesh objects. An AIFVertex natively saves relations with it...
Definition: AIFVertex.hpp:41
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_ordered_one_ring_edges
static edge_container_in_vertex get_ordered_one_ring_edges(vertex_descriptor v)
Definition: AIFTopologyHelpers.h:3644
FEVV::DataStructures::AIF::AIFVertex::VertexContainerType
std::vector< ptr_vertex > VertexContainerType
Definition: AIFVertex.hpp:55
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(face_descriptor face, edge_descriptor edge)
Function determining if the argument face shares an incidence relation with the argument edge.
Definition: AIFTopologyHelpers.h:1792
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_isolated_face
static bool is_isolated_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1511
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static void add_face(face_descriptor face, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2924
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static edge_descriptor add_edge(smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2783
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident_to_vertex_and_edge_connected
static bool are_incident_to_vertex_and_edge_connected(vertex_descriptor vertex, face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:875
FEVV::DataStructures::AIF::AIFTopologyHelpers::link_edge_and_face_around_face_after_edge
static void link_edge_and_face_around_face_after_edge(edge_descriptor edge, face_descriptor face, edge_descriptor prev_edge)
Definition: AIFTopologyHelpers.h:1339
FEVV::Container::insert
void insert(ContainerType &container, const ContainedType &element)
Definition: Helpers.hxx:26
FEVV::DataStructures::AIF::AIFMesh::ptr
boost::shared_ptr< Self > ptr
Definition: AIFMesh.hpp:50
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_degenerated_face
static bool is_degenerated_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1530
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_edges
static size_type num_edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2174
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_face
static bool is_2_manifold_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1561
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edges
static void remove_edges(InputIt first, InputIt last, MeshType &mesh)
Definition: AIFTopologyHelpers.h:3067
FEVV::DataStructures::AIF::AIFMesh::GetFaces
boost::iterator_range< FaceContainerType::const_iterator > GetFaces() const
Definition: AIFMesh.hpp:189
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_2_adjacent_faces_with_non_consistent_orientation
static bool contains_2_adjacent_faces_with_non_consistent_orientation(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2346
FEVV::DataStructures::AIF::AIFTopologyHelpers::FIRST
@ FIRST
Definition: AIFTopologyHelpers.h:104
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(face_descriptor face, vertex_descriptor vertex)
Function determining if the argument face shares an incidence relation with the argument vertex.
Definition: AIFTopologyHelpers.h:1721
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_faces
static boost::iterator_range< incident_face_iterator > incident_faces(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1237
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::m_target
vertex_descriptor m_target
Definition: AIFTopologyHelpers.h:5743
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::m_face
face_descriptor m_face
Definition: AIFTopologyHelpers.h:5746
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static edge_descriptor add_edge(ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2792
FEVV::DataStructures::AIF::AIFTopologyHelpers::out_edge_iterator
edge_container_in_vertex::const_iterator out_edge_iterator
Definition: AIFTopologyHelpers.h:89
FEVV::DataStructures::AIF::AIFTopologyHelpers::adjacency_iterator
vertex_container_in_vertex::const_iterator adjacency_iterator
Definition: AIFTopologyHelpers.h:92
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_a_cut_vertex
static bool contains_a_cut_vertex(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2396
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_container
mesh_type::FaceContainerType face_container
Definition: AIFTopologyHelpers.h:85
FEVV::DataStructures::AIF::AIFMesh::InsertIsolatedFace
void InsertIsolatedFace(face_type::ptr face)
Definition: AIFMesh.hpp:247
FEVV::DataStructures::AIF::AIFFace
This class represents a face used by AIFMesh objects. An AIFFace natively saves relations with its in...
Definition: AIFFace.hpp:46
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_face
static void remove_face(face_descriptor face, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3120
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertex
static void remove_vertex(vertex_descriptor vertex, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2987
FEVV::DataStructures::AIF::AIFTopologyHelpers::SECOND
@ SECOND
Definition: AIFTopologyHelpers.h:104
FEVV::DataStructures::AIF::AIFFace::ptr
boost::shared_ptr< self > ptr
Definition: AIFFace.hpp:52
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static void add_edge(edge_descriptor edge, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2822
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_edge_and_face
static void unlink_edge_and_face(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:1398
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_not_incident_to_complex_edge
static bool is_not_incident_to_complex_edge(face_descriptor face)
Definition: AIFTopologyHelpers.h:2057
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_edge_iterator
edge_container_in_face::iterator incident_edge_iterator
Definition: AIFTopologyHelpers.h:94
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_container_in_edge
edge_type::EdgeContainerType edge_container_in_edge
Definition: AIFTopologyHelpers.h:78
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_2_adjacent_faces_with_non_consistent_orientation
static bool contains_2_adjacent_faces_with_non_consistent_orientation(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2368
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::next
AIFHalfEdge next(const AIFMesh &m)
next of current halfedge
Definition: AIFTopologyHelpers.h:4946
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_adjacent
static bool are_adjacent(vertex_descriptor vertex1, vertex_descriptor vertex2)
Definition: AIFTopologyHelpers.h:358
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge_from_face
static void remove_edge_from_face(face_descriptor face, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:4665
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertices
static boost::iterator_range< vertex_container::const_iterator > vertices(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2249
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_type
mesh_type::edge_type edge_type
Definition: AIFTopologyHelpers.h:61
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_incident_dangling_edge
static size_type num_incident_dangling_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1079
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_descriptor
edge_type::ptr edge_descriptor
Definition: AIFTopologyHelpers.h:71
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static void add_vertex(vertex_descriptor vertex, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2740
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_container_in_edge
edge_type::VertexContainerType vertex_container_in_edge
Definition: AIFTopologyHelpers.h:77
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static vertex_descriptor add_vertex(ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2729
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort
static void sort(RandomIt first, RandomIt last, Compare comp)
Definition: AIFTopologyHelpers.h:4723
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge
static edge_descriptor edge(halfedge_descriptor h, const AIFMesh &)
Definition: AIFTopologyHelpers.h:5998
FEVV::DataStructures::AIF::AIFTopologyHelpers::smart_ptr_cmesh
mesh_type::ptr_cmesh smart_ptr_cmesh
Definition: AIFTopologyHelpers.h:65
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_dangling_face
static bool is_dangling_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1582
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_descriptor
face_type::ptr face_descriptor
Definition: AIFTopologyHelpers.h:72
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_position
static vertex_pos vertex_position(edge_descriptor edge, vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1252
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_border_vertex
static bool is_surface_border_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:264
FEVV::DataStructures::AIF::AIFTopologyHelpers::null_edge
static edge_descriptor null_edge()
Definition: AIFTopologyHelpers.h:113
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_face
static void remove_face(face_descriptor face, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:3180
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static edge_descriptor add_edge(ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2772
FEVV::DataStructures::AIF::AIFFace::EdgeContainerType
std::vector< ptr_edge > EdgeContainerType
Definition: AIFFace.hpp:61
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_faces
static boost::iterator_range< face_container_in_vertex::const_iterator > incident_faces(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:415
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge_from_vertex
static void remove_edge_from_vertex(vertex_descriptor vertex, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:4589
FEVV::DataStructures::AIF::AIFTopologyHelpers::const_incident_edge_iterator
edge_container_in_face::const_iterator const_incident_edge_iterator
Definition: AIFTopologyHelpers.h:97
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalize_border
static void normalize_border(ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2553
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_vertices
static boost::iterator_range< vertex_container::const_iterator > sort_vertices(smart_ptr_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:594
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static void add_vertex(vertex_descriptor vertex, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2751
FEVV::DataStructures::AIF::AIFTopologyHelpers::null_face
static face_descriptor null_face()
Definition: AIFTopologyHelpers.h:114
FEVV::DataStructures::AIF::AIFFace::VertexContainerType
std::vector< ptr_vertex > VertexContainerType
Definition: AIFFace.hpp:60
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static void add_face(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:3392
FEVV::DataStructures::AIF::source
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor source(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the source vertex of e.
Definition: Graph_traits_aif.h:387
FEVV::DataStructures::AIF::AIFEdge::New
static ptr_edge New()
Definition: AIFEdge.inl:22
FEVV::DataStructures::AIF::AIFTopologyHelpers::set_halfedge
static void set_halfedge(vertex_descriptor target, halfedge_descriptor h, AIFMesh &)
Definition: AIFTopologyHelpers.h:6041
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_degree
face_degree
Compliant enumeration for face degree comparison.
Definition: AIFTopologyHelpers.h:109
FEVV::DataStructures::AIF::AIFTopologyHelpers::swap_vertices
static void swap_vertices(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1286
FEVV::DataStructures::AIF::AIFTopologyHelpers::link_edges_and_face_around_face_after_edge
static void link_edges_and_face_around_face_after_edge(std::vector< edge_descriptor > &edges, face_descriptor face, edge_descriptor prev_edge)
Definition: AIFTopologyHelpers.h:1376
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_edge_of_face_before_edge
static edge_descriptor get_edge_of_face_before_edge(face_descriptor face, edge_descriptor next_edge)
Definition: AIFTopologyHelpers.h:4399
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_faces_container
static face_container_in_vertex incident_faces_container(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:446
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_container_in_face
face_type::VertexContainerType vertex_container_in_face
Definition: AIFTopologyHelpers.h:80
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_type
mesh_type::face_type face_type
Definition: AIFTopologyHelpers.h:62
FEVV::DataStructures::AIF::AIFMesh::ptr_cmesh
boost::shared_ptr< const Self > ptr_cmesh
Definition: AIFMesh.hpp:52
FEVV::DataStructures::AIF::AIFTopologyHelpers::faces
static boost::iterator_range< face_container::const_iterator > faces(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2606
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_edges
static boost::iterator_range< incident_edge_iterator > incident_edges(face_descriptor face)
Definition: AIFTopologyHelpers.h:1854
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_dangling_edge
static bool is_dangling_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1009
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_vertices
static size_type num_vertices(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2157
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_adjacent
static bool are_adjacent(edge_descriptor edge1, edge_descriptor edge2)
Definition: AIFTopologyHelpers.h:1174
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_incident_to_dangling_edge
static bool is_incident_to_dangling_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1098
FEVV::DataStructures::AIF::AIFTopologyHelpers::const_incident_face_iterator
face_container_in_edge::const_iterator const_incident_face_iterator
Definition: AIFTopologyHelpers.h:98
FEVV::DataStructures::AIF::AIFTopologyHelpers::degree
static size_type degree(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:148
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_has_only_that_edge_with_degree_greater_than_1
static bool face_has_only_that_edge_with_degree_greater_than_1(face_descriptor face, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1627
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_cut_vertex
static bool is_cut_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:173
FEVV::DataStructures::AIF::AIFTopologyHelpers::link_vertex_and_edge
static void link_vertex_and_edge(vertex_descriptor vertex, edge_descriptor edge, vertex_pos position)
Definition: AIFTopologyHelpers.h:515
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static face_descriptor add_face(ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2907
FEVV::DataStructures::AIF::AIFTopologyHelpers::QUADRANGULAR
@ QUADRANGULAR
Definition: AIFTopologyHelpers.h:109
FEVV::DataStructures::AIF::AIFMesh::GetNumberOfVertices
unsigned int GetNumberOfVertices() const
Definition: AIFMesh.hpp:206
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_faces
static size_type num_faces(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2209
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::opposite
AIFHalfEdge opposite(const AIFMesh &)
opposite of current halfedge (may not be defined when edge is complex)
Definition: AIFTopologyHelpers.h:5667
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_vertices
static boost::iterator_range< vertex_container_in_face::const_iterator > incident_vertices(face_descriptor face)
Definition: AIFTopologyHelpers.h:1839
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::set_edge
void set_edge(edge_descriptor new_edge)
edge setter
Definition: AIFTopologyHelpers.h:5729
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static void add_edge(face_descriptor face, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3436
FEVV::DataStructures::AIF::AIFTopologyHelpers::adjacent_edges
static std::vector< edge_descriptor > adjacent_edges(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1203
FEVV::DataStructures::AIF::AIFMesh::EraseIsolatedFace
void EraseIsolatedFace(face_type::ptr face)
Definition: AIFMesh.hpp:321
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_mesh
static bool is_2_manifold_mesh(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2297
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::get_source
vertex_descriptor get_source(void) const
source vertex getter
Definition: AIFTopologyHelpers.h:5714
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_vertices
static size_type num_vertices(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2167
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_faces
static size_type num_faces(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2218
FEVV::DataStructures::AIF::AIFTopologyHelpers::null_halfedge
static halfedge_descriptor null_halfedge()
Definition: AIFTopologyHelpers.h:5761
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(edge_descriptor edge, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3012
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::DataStructures::AIF::AIFTopologyHelpers::ref_mesh
mesh_type & ref_mesh
Definition: AIFTopologyHelpers.h:68
FEVV::DataStructures::AIF::AIFMesh::InsertIsolatedEdge
void InsertIsolatedEdge(edge_type::ptr edge)
Definition: AIFMesh.hpp:240
FEVV::DataStructures::AIF::AIFMesh::InsertIsolatedVertex
void InsertIsolatedVertex(vertex_type::ptr vertex)
Definition: AIFMesh.hpp:233
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_incident_edges
static boost::iterator_range< edge_container_in_vertex::const_iterator > sort_incident_edges(vertex_descriptor vertex, const ComparatorType &cmp, bool do_full_incident_edge_sorting)
Definition: AIFTopologyHelpers.h:686
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(edge_descriptor edge, face_descriptor face)
Function determining if the argument edge share an incidence relation with the argument face.
Definition: AIFTopologyHelpers.h:1151
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_border_edge
static bool is_surface_border_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:949
AIFMesh.hpp
FEVV::DataStructures::AIF::AIFTopologyHelpers::halfedge
static halfedge_descriptor halfedge(vertex_descriptor src, vertex_descriptor target, const AIFMesh &)
Definition: AIFTopologyHelpers.h:5907
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_degenerated_edge
static bool is_degenerated_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1034
FEVV::Container::erase
void erase(ContainerType &container, const ContainedType &element)
Definition: Helpers.hxx:33
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalized_border_is_valid
static bool normalized_border_is_valid(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2473
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_isolated_vertex
static bool is_isolated_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:159
FEVV::DataStructures::AIF::AIFTopologyHelpers::update_for_single_edge
static void update_for_single_edge(vertex_descriptor v, const edge_container_in_vertex &orderedOneRing, size_t index, vertex_container_in_vertex &oneR)
Definition: AIFTopologyHelpers.h:3957
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_pos
vertex_pos
The vertex position in an edge.
Definition: AIFTopologyHelpers.h:104
FEVV::DataStructures::AIF::AIFTopologyHelpers::degree
static size_type degree(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:942
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::m_source
vertex_descriptor m_source
Definition: AIFTopologyHelpers.h:5741
FEVV::DataStructures::AIF::AIFTopologyHelpers::edges
static boost::iterator_range< edge_container::const_iterator > edges(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2283
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_incident_hole_border_edges_except_one_edge
static std::vector< edge_descriptor > get_incident_hole_border_edges_except_one_edge(vertex_descriptor vertex, edge_descriptor edge_to_remove)
Definition: AIFTopologyHelpers.h:805
FEVV::DataStructures::AIF::AIFTopologyHelpers::set_halfedge
static void set_halfedge(face_descriptor face, halfedge_descriptor h, AIFMesh &)
Definition: AIFTopologyHelpers.h:6233
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_incident_dangling_edge
static edge_descriptor get_incident_dangling_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1109
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static face_descriptor add_face(smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2898
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_face_iterator
face_container_in_edge::iterator incident_face_iterator
Definition: AIFTopologyHelpers.h:95
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_one_ring_incident_edges
static void sort_one_ring_incident_edges(edge_descriptor edge, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:730
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edges
static std::vector< edge_descriptor > common_edges(face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:2121
FEVV::DataStructures::AIF::AIFTopologyHelpers::set_face
static void set_face(halfedge_descriptor h, face_descriptor face, AIFMesh &)
Definition: AIFTopologyHelpers.h:6199
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(edge_descriptor edge, vertex_descriptor vertex)
Function determining if the argument edge shares an incidence relation with the argument vertex.
Definition: AIFTopologyHelpers.h:1134
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_degenerated_vertex
static bool is_degenerated_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:127
FEVV::DataStructures::AIF::target
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor target(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the target vertex of e.
Definition: Graph_traits_aif.h:400
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static void add_face(face_descriptor face, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2934
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_vertices
static boost::iterator_range< vertex_container::const_iterator > sort_vertices(ref_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:609
FEVV::DataStructures::AIF::AIFTopologyHelpers::size_type
unsigned int size_type
Definition: AIFTopologyHelpers.h:87
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::get_face
face_descriptor get_face(void) const
face getter
Definition: AIFTopologyHelpers.h:5718
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_one_ring_2_manifold
static bool is_one_ring_2_manifold(vertex_descriptor v)
Definition: AIFTopologyHelpers.h:4334
FEVV::DataStructures::AIF::AIFTopologyHelpers::halfedge
static halfedge_descriptor halfedge(face_descriptor face, const AIFMesh &)
Definition: AIFTopologyHelpers.h:5769
FEVV::DataStructures::AIF::AIFTopologyHelpers::set_next
static void set_next(halfedge_descriptor h1, halfedge_descriptor h2, AIFMesh &mesh)
Definition: AIFTopologyHelpers.h:6067
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::AIFHalfEdge
AIFHalfEdge(void)
fullfill the DefaultConstructible concept
Definition: AIFTopologyHelpers.h:4751
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertex
static void remove_vertex(vertex_descriptor vertex, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2960
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::AIFHalfEdge
AIFHalfEdge(vertex_descriptor s, vertex_descriptor t, face_descriptor f, bool do_validity_check=true)
Definition: AIFTopologyHelpers.h:4760
FEVV::DataStructures::AIF::AIFTopologyHelpers::border_edges
static boost::iterator_range< edge_container::const_iterator > border_edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2562
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_locally_edge_connected
static bool are_locally_edge_connected(face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:1917
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::set_target
void set_target(vertex_descriptor new_target)
target vertex setter
Definition: AIFTopologyHelpers.h:5725
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::operator!=
bool operator!=(const AIFHalfEdge &other) const
Definition: AIFTopologyHelpers.h:4931
FEVV::DataStructures::AIF::AIFMesh::GetVertices
boost::iterator_range< VertexContainerType::const_iterator > GetVertices() const
Definition: AIFMesh.hpp:134
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::operator<<
friend std::ostream & operator<<(std::ostream &stream, const AIFHalfEdge &h)
ostream operator for debugging
Definition: AIFTopologyHelpers.h:5732
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge_to_face_after_edge
static void add_edge_to_face_after_edge(face_descriptor face, edge_descriptor prev_edge, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:4438
FEVV::DataStructures::AIF::AIFTopologyHelpers::edges
static boost::iterator_range< edge_container::const_iterator > edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2261
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_vertices
static size_type num_vertices(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2148
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static void add_edge(edge_descriptor edge, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2800
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertex_from_edge
static void remove_vertex_from_edge(edge_descriptor edge, vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:4554
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_edge_of_face_after_edge
static edge_descriptor get_edge_of_face_after_edge(face_descriptor face, edge_descriptor prev_edge)
Definition: AIFTopologyHelpers.h:4366
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_unordered_one_ring_edges
static std::set< edge_descriptor > get_unordered_one_ring_edges(vertex_descriptor v)
Definition: AIFTopologyHelpers.h:3481
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_complex_edge
static bool is_complex_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1022
FEVV::DataStructures::AIF::AIFEdge::ptr
boost::shared_ptr< self > ptr
Definition: AIFEdge.hpp:56
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face
static void add_face(face_descriptor face, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2914
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_face
static face_descriptor common_face(edge_descriptor edge1, edge_descriptor edge2)
Definition: AIFTopologyHelpers.h:2074
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_ordered_one_ring_vertices
static vertex_container_in_vertex get_ordered_one_ring_vertices(vertex_descriptor v)
Definition: AIFTopologyHelpers.h:4035
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_vertex
static vertex_descriptor common_vertex(edge_descriptor edge1, edge_descriptor edge2)
Definition: AIFTopologyHelpers.h:1055
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edge
static edge_descriptor common_edge(face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:2095
FEVV::DataStructures::AIF::AIFTopologyHelpers::check_mesh_validity
static bool check_mesh_validity(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2641
FEVV::DataStructures::AIF::AIFMesh::GetNumberOfFaces
unsigned int GetNumberOfFaces() const
Definition: AIFMesh.hpp:222
FEVV::DataStructures::AIF::AIFTopologyHelpers::size_of_border_edges
static size_type size_of_border_edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2481
FEVV::DataStructures::AIF::AIFTopologyHelpers::border_edges
static boost::iterator_range< edge_container::const_iterator > border_edges(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2583
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_container_in_vertex
vertex_type::FaceContainerType face_container_in_vertex
Definition: AIFTopologyHelpers.h:76
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_all_edges
static void unlink_all_edges(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:3217
FEVV::DataStructures::AIF::AIFFace::FaceContainerType
std::vector< ptr_face > FaceContainerType
Definition: AIFFace.hpp:62
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_edges
static size_type num_edges(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2183
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static void add_vertex(vertex_descriptor vertex, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2762
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_edges
static boost::iterator_range< edge_container::const_iterator > sort_edges(smart_ptr_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:1476
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::prev
AIFHalfEdge prev(const AIFMesh &m)
prev of current halfedge
Definition: AIFTopologyHelpers.h:5349
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_incident_edges_starting_with_edge
static boost::iterator_range< edge_container_in_vertex::const_iterator > sort_incident_edges_starting_with_edge(vertex_descriptor vertex, const ComparatorType &cmp, edge_descriptor edge, bool do_full_incident_edge_sorting)
Definition: AIFTopologyHelpers.h:630
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_regular_edge
static bool is_surface_regular_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:960
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_all_vertices
static void unlink_all_vertices(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3204
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(vertex_descriptor vertex, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3370
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edges
static std::vector< edge_descriptor > common_edges(vertex_descriptor vertex1, vertex_descriptor vertex2)
Definition: AIFTopologyHelpers.h:482
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::AIFHalfEdge
AIFHalfEdge(vertex_descriptor s, vertex_descriptor t, face_descriptor f, edge_descriptor e, bool do_validity_check=true)
Definition: AIFTopologyHelpers.h:4838
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_e_one_ring_connected
static bool is_e_one_ring_connected(edge_descriptor e, const T &container_of_edge_one_ring, bool allow_multiple_incident_edges=false, bool ensure_e_belongs_to_container=true)
Definition: AIFTopologyHelpers.h:3547
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_incident_to_consistently_oriented_faces
static bool is_incident_to_consistently_oriented_faces(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:2025
FEVV::DataStructures::AIF::AIFVertex::New
static ptr_vertex New()
Definition: AIFVertex.inl:17
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_incident_edges
static void sort_incident_edges(edge_descriptor edge, const ComparatorType &cmp, bool do_full_incident_edge_sorting)
Definition: AIFTopologyHelpers.h:711
FEVV::DataStructures::AIF::AIFMesh::EraseIsolatedVertex
void EraseIsolatedVertex(vertex_type::ptr vertex)
Definition: AIFMesh.hpp:290
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_container_in_vertex
vertex_type::VertexContainerType vertex_container_in_vertex
Definition: AIFTopologyHelpers.h:74
FEVV::DataStructures::AIF::AIFTopologyHelpers::ptr_mesh
mesh_type * ptr_mesh
Definition: AIFTopologyHelpers.h:66
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_incident_to_dangling_or_complex_edge
static bool is_incident_to_dangling_or_complex_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:199
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(vertex_descriptor vertex, face_descriptor face)
Function determining if the argument vertex shares an incidence relation with the argument face.
Definition: AIFTopologyHelpers.h:1755
FEVV::DataStructures::AIF::AIFCellContainer< vertex_type::ptr >
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_face_from_edge
static void remove_face_from_edge(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:4694
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertex
static void remove_vertex(vertex_descriptor vertex, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2977
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edge
static edge_descriptor common_edge(vertex_descriptor vertex, face_descriptor face)
Definition: AIFTopologyHelpers.h:823
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_regular_edge
static bool is_regular_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:982
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalized_border_is_valid
static bool normalized_border_is_valid(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2464
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_edges
static boost::iterator_range< edge_container_in_vertex::const_iterator > incident_edges(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:399
FEVV::DataStructures::AIF::AIFEdge::FaceContainerType
std::vector< ptr_face > FaceContainerType
Definition: AIFEdge.hpp:66
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(edge_descriptor edge, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:3054
FEVV::DataStructures::AIF::AIFTopologyHelpers::smart_ptr_mesh
mesh_type::ptr smart_ptr_mesh
Definition: AIFTopologyHelpers.h:64
FEVV::DataStructures::AIF::AIFTopologyHelpers
This class is an helper class associated to the AIFMesh structure. AIFTopologyHelpers implements all ...
Definition: AIFTopologyHelpers.h:57
FEVV::DataStructures::AIF::AIFTopologyHelpers::clear_vertex
static void clear_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:2946
FEVV::DataStructures::AIF::AIFTopologyHelpers::TRIANGULAR
@ TRIANGULAR
Definition: AIFTopologyHelpers.h:109
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_all_edges
static void unlink_all_edges(face_descriptor face)
Definition: AIFTopologyHelpers.h:3239
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertex
static void remove_vertex(edge_descriptor edge, vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:3321
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertices
static boost::iterator_range< vertex_container::const_iterator > vertices(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2227
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_edges
static size_type num_edges(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2192
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_container_in_face
face_type::FaceContainerType face_container_in_face
Definition: AIFTopologyHelpers.h:82
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(vertex_descriptor v, vertex_descriptor u, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3081
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_container_in_edge
edge_type::FaceContainerType face_container_in_edge
Definition: AIFTopologyHelpers.h:79
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_interior_face
static bool is_surface_interior_face(face_descriptor face)
Definition: AIFTopologyHelpers.h:1706
FEVV::DataStructures::AIF::AIFMesh
This class represents an AIF structure. AIF structure can deal with both manifold and non-manifold su...
Definition: AIFMesh.hpp:47
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertices
static boost::iterator_range< vertex_container::const_iterator > vertices(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2238
FEVV::DataStructures::AIF::face
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor face(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the face incident to halfedge h.
Definition: Graph_traits_aif.h:664
FEVV::DataStructures::AIF::AIFTopologyHelpers::reverse_face_orientation
static void reverse_face_orientation(face_descriptor face)
Definition: AIFTopologyHelpers.h:2045
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_type
mesh_type::vertex_type vertex_type
Definition: AIFTopologyHelpers.h:60
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_vertices
static boost::iterator_range< vertex_container::const_iterator > sort_vertices(ptr_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:576
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static void add_edge(edge_descriptor edge, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2811
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::set_source
void set_source(vertex_descriptor new_source)
source vertex setter
Definition: AIFTopologyHelpers.h:5723
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalize_border
static void normalize_border(ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2516
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::set_face
void set_face(face_descriptor new_face)
face setter
Definition: AIFTopologyHelpers.h:5727
FEVV::DataStructures::AIF::AIFTopologyHelpers::halfedge
static halfedge_descriptor halfedge(vertex_descriptor v, const AIFMesh &)
Definition: AIFTopologyHelpers.h:5815
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_border_face_through_vertex
static bool is_surface_border_face_through_vertex(face_descriptor face, vertex_descriptor v, bool border_edge_before_v)
Definition: AIFTopologyHelpers.h:1676
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static vertex_descriptor add_vertex(ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2709
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_a_cut_vertex
static bool contains_a_cut_vertex(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2429
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::get_target
vertex_descriptor get_target(void) const
target vertex getter
Definition: AIFTopologyHelpers.h:5716
FEVV::DataStructures::AIF::AIFTopologyHelpers::unlink_vertex_and_edge
static void unlink_vertex_and_edge(vertex_descriptor vertex, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:544
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_first_edge_whose_adjacent_edges_are_one_ring_connected
static edge_descriptor get_first_edge_whose_adjacent_edges_are_one_ring_connected(const T &container_of_edge_one_ring)
Definition: AIFTopologyHelpers.h:3617
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_surface_interior_vertex
static bool is_surface_interior_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:288
FEVV::DataStructures::AIF::AIFTopologyHelpers::null_vertex
static vertex_descriptor null_vertex()
Definition: AIFTopologyHelpers.h:112
FEVV::DataStructures::AIF::AIFEdge
This class represents an edge used by AIFMesh objects. An AIFEdge natively saves relations with its i...
Definition: AIFEdge.hpp:49
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex_to_edge
static void add_vertex_to_edge(edge_descriptor edge, vertex_descriptor vertex, enum vertex_pos position)
Definition: AIFTopologyHelpers.h:4494
FEVV::DataStructures::AIF::AIFFace::New
static ptr_face New()
Definition: AIFFace.inl:19
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static vertex_descriptor add_vertex(smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2720
FEVV::DataStructures::AIF::AIFVertex::FaceContainerType
std::vector< ptr_face > FaceContainerType
Definition: AIFVertex.hpp:57
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::operator<
bool operator<(const AIFHalfEdge &other) const
fulfill the LessThanComparable concept
Definition: AIFTopologyHelpers.h:4937
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static std::pair< edge_descriptor, bool > add_edge(vertex_descriptor v, vertex_descriptor u, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:2877
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalize_border
static void normalize_border(smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2543
FEVV::DataStructures::AIF::AIFTopologyHelpers::adjacent_vertices
static std::vector< vertex_descriptor > adjacent_vertices(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:377
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_face_to_edge
static void add_face_to_edge(edge_descriptor edge, face_descriptor face)
Definition: AIFTopologyHelpers.h:4637
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_incident
static bool are_incident(vertex_descriptor vertex, edge_descriptor edge)
Function determining if the arguments share an incidence relation.
Definition: AIFTopologyHelpers.h:303
FEVV::DataStructures::AIF::AIFTopologyHelpers::are_adjacent_edges_one_ring_connected
static bool are_adjacent_edges_one_ring_connected(edge_descriptor e, const T &container_of_edge_one_ring)
Definition: AIFTopologyHelpers.h:3595
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_incident_hole_border_edges
static std::vector< edge_descriptor > get_incident_hole_border_edges(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:755
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(edge_descriptor edge, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3043
FEVV::DataStructures::AIF::AIFTopologyHelpers::normalized_border_is_valid
static bool normalized_border_is_valid(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2439
FEVV::DataStructures::AIF::AIFTopologyHelpers::check_mesh_validity
static bool check_mesh_validity(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2669
FEVV::DataStructures::AIF::AIFMesh::EraseIsolatedEdge
void EraseIsolatedEdge(edge_type::ptr edge)
Definition: AIFMesh.hpp:299
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_a_cut_vertex
static bool contains_a_cut_vertex(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2416
FEVV::DataStructures::AIF::AIFTopologyHelpers::degree_size_type
edge_container_in_vertex::size_type degree_size_type
Definition: AIFTopologyHelpers.h:90
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge_to_face
static void add_edge_to_face(face_descriptor face, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:4606
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static std::pair< edge_descriptor, bool > add_edge(vertex_descriptor v, vertex_descriptor u, ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2837
FEVV::DataStructures::AIF::AIFTopologyHelpers::adjacent_faces
static std::vector< face_descriptor > adjacent_faces(face_descriptor face, bool one_neighborhood_sharing_edge=true)
Definition: AIFTopologyHelpers.h:1871
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_vertex
static void add_vertex(edge_descriptor edge, vertex_descriptor vertex, enum vertex_pos position)
Definition: AIFTopologyHelpers.h:3294
FEVV::DataStructures::AIF::AIFTopologyHelpers::faces
static boost::iterator_range< face_container::const_iterator > faces(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2617
FEVV::DataStructures::AIF::AIFTopologyHelpers::face_has_only_incident_edges_with_degree_1
static bool face_has_only_incident_edges_with_degree_1(face_descriptor face)
Definition: AIFTopologyHelpers.h:1606
FEVV::DataStructures::AIF::AIFVertex::EdgeContainerType
std::vector< ptr_edge > EdgeContainerType
Definition: AIFVertex.hpp:56
FEVV::DataStructures::AIF::AIFTopologyHelpers::add_edge
static std::pair< edge_descriptor, bool > add_edge(vertex_descriptor v, vertex_descriptor u, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:2862
FEVV::DataStructures::AIF::AIFTopologyHelpers::common_edge
static edge_descriptor common_edge(vertex_descriptor vertex, face_descriptor face, edge_descriptor not_that_edge)
Definition: AIFTopologyHelpers.h:847
FEVV::DataStructures::AIF::AIFEdge::EdgeContainerType
std::vector< ptr_edge > EdgeContainerType
Definition: AIFEdge.hpp:65
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_2_manifold_mesh
static bool is_2_manifold_mesh(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2331
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_face
static void remove_face(face_descriptor face, smart_ptr_mesh mesh)
Definition: AIFTopologyHelpers.h:3169
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_ordered_one_ring_of_adjacent_vertices
static vertex_container_in_vertex get_ordered_one_ring_of_adjacent_vertices(vertex_descriptor v)
Definition: AIFTopologyHelpers.h:4305
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_regular_vertex
static bool is_regular_vertex(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:220
FEVV::DataStructures::AIF::AIFTopologyHelpers::size_of_border_edges
static size_type size_of_border_edges(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2505
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_a_degenerated_face
static bool contains_a_degenerated_face(InputIt first, InputIt last)
Definition: AIFTopologyHelpers.h:2695
FEVV::DataStructures::AIF::AIFTopologyHelpers::have_consistent_orientation
static bool have_consistent_orientation(face_descriptor face1, face_descriptor face2)
Definition: AIFTopologyHelpers.h:1972
FEVV::DataStructures::AIF::AIFTopologyHelpers::sort_edges
static boost::iterator_range< edge_container::const_iterator > sort_edges(ptr_mesh mesh, const ComparatorType &cmp)
Definition: AIFTopologyHelpers.h:1459
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(face_descriptor face, edge_descriptor edge)
Definition: AIFTopologyHelpers.h:3458
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_vertices
static void remove_vertices(InputIt first, InputIt last, MeshType &mesh)
Definition: AIFTopologyHelpers.h:3000
FEVV::DataStructures::AIF::AIFTopologyHelpers::halfedge
static halfedge_descriptor halfedge(edge_descriptor edge, const AIFMesh &mesh)
Definition: AIFTopologyHelpers.h:5974
FEVV::DataStructures::AIF::AIFTopologyHelpers::edge_container_in_face
face_type::EdgeContainerType edge_container_in_face
Definition: AIFTopologyHelpers.h:81
FEVV::DataStructures::AIF::AIFTopologyHelpers::remove_edge
static void remove_edge(vertex_descriptor v, vertex_descriptor u, ref_mesh mesh)
Definition: AIFTopologyHelpers.h:3109
FEVV::DataStructures::AIF::AIFTopologyHelpers::size_of_border_edges
static size_type size_of_border_edges(smart_ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2498
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertex_container
mesh_type::VertexContainerType vertex_container
Definition: AIFTopologyHelpers.h:83
FEVV::DataStructures::AIF::AIFTopologyHelpers::contains_2_adjacent_faces_with_non_consistent_orientation
static bool contains_2_adjacent_faces_with_non_consistent_orientation(ref_cmesh mesh)
Definition: AIFTopologyHelpers.h:2383
FEVV::DataStructures::AIF::AIFTopologyHelpers::AIFHalfEdge::get_edge
edge_descriptor get_edge(void) const
corresponding edge getter
Definition: AIFTopologyHelpers.h:5720