Developer Documentation
TopologyKernel.hh
1 /*===========================================================================*\
2  * *
3  * OpenVolumeMesh *
4  * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
5  * www.openvolumemesh.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenVolumeMesh. *
9  * *
10  * OpenVolumeMesh is free software: you can redistribute it and/or modify *
11  * it under the terms of the GNU Lesser General Public License as *
12  * published by the Free Software Foundation, either version 3 of *
13  * the License, or (at your option) any later version with the *
14  * following exceptions: *
15  * *
16  * If other files instantiate templates or use macros *
17  * or inline functions from this file, or you compile this file and *
18  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenVolumeMesh is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenVolumeMesh. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision$ *
38  * $Date$ *
39  * $LastChangedBy$ *
40  * *
41 \*===========================================================================*/
42 
43 #ifndef TOPOLOGYKERNEL_HH_
44 #define TOPOLOGYKERNEL_HH_
45 
46 #include <cassert>
47 #include <set>
48 #include <vector>
49 
50 #include "BaseEntities.hh"
51 #include "OpenVolumeMeshHandle.hh"
52 #include "ResourceManager.hh"
53 #include "Iterators.hh"
54 
55 namespace OpenVolumeMesh {
56 
58 public:
59 
61  virtual ~TopologyKernel();
62 
63  /*
64  * Defines and constants
65  */
66 
67  static const VertexHandle InvalidVertexHandle;
68  static const EdgeHandle InvalidEdgeHandle;
69  static const FaceHandle InvalidFaceHandle;
70  static const CellHandle InvalidCellHandle;
71  static const HalfEdgeHandle InvalidHalfEdgeHandle;
72  static const HalfFaceHandle InvalidHalfFaceHandle;
73 
74  typedef OpenVolumeMeshEdge Edge;
75  typedef OpenVolumeMeshFace Face;
76  typedef OpenVolumeMeshCell Cell;
77 
78  // Add StatusAttrib to list of friend classes
79  // since it provides a garbage collection
80  // that needs access to some protected methods
81  friend class StatusAttrib;
82 
83  //=====================================================================
84  // Iterators
85  //=====================================================================
86 
87  friend class VertexOHalfEdgeIter;
88  friend class VertexVertexIter;
89  friend class HalfEdgeHalfFaceIter;
90  friend class VertexFaceIter;
91  friend class VertexCellIter;
92  friend class HalfEdgeCellIter;
93  friend class CellVertexIter;
94  friend class CellCellIter;
95  friend class HalfFaceVertexIter;
96  friend class BoundaryHalfFaceHalfFaceIter;
97  friend class BoundaryFaceIter;
98  friend class VertexIter;
99  friend class EdgeIter;
100  friend class HalfEdgeIter;
101  friend class FaceIter;
102  friend class HalfFaceIter;
103  friend class CellIter;
104 
105  /*
106  * Circulators
107  */
108 
109 protected:
110  template <class Circulator>
111  static Circulator make_end_circulator(const Circulator& _circ)
112  {
113  Circulator end = _circ;
114  if (end.valid()) {
115  end.lap(_circ.max_laps());
116  end.valid(false);
117  }
118  return end;
119  }
120 
121 public:
122 
123  VertexOHalfEdgeIter voh_iter(const VertexHandle& _h, int _max_laps = 1) const {
124  return VertexOHalfEdgeIter(_h, this, _max_laps);
125  }
126 
127  std::pair<VertexOHalfEdgeIter, VertexOHalfEdgeIter> outgoing_halfedges(const VertexHandle& _h, int _max_laps = 1) const {
128  VertexOHalfEdgeIter begin = voh_iter(_h, _max_laps);
129  return std::make_pair(begin, make_end_circulator(begin));
130  }
131 
132  VertexVertexIter vv_iter(const VertexHandle& _h, int _max_laps = 1) const {
133  return VertexVertexIter(_h, this, _max_laps);
134  }
135 
136  std::pair<VertexVertexIter, VertexVertexIter> vertex_vertices(const VertexHandle& _h, int _max_laps = 1) const {
137  VertexVertexIter begin = vv_iter(_h, _max_laps);
138  return std::make_pair(begin, make_end_circulator(begin));
139  }
140 
141  HalfEdgeHalfFaceIter hehf_iter(const HalfEdgeHandle& _h, int _max_laps = 1) const {
142  return HalfEdgeHalfFaceIter(_h, this, _max_laps);
143  }
144 
145  std::pair<HalfEdgeHalfFaceIter, HalfEdgeHalfFaceIter> halfedge_halffaces(const HalfEdgeHandle& _h, int _max_laps = 1) const {
146  HalfEdgeHalfFaceIter begin = hehf_iter(_h, _max_laps);
147  return std::make_pair(begin, make_end_circulator(begin));
148  }
149 
150  VertexFaceIter vf_iter(const VertexHandle& _h, int _max_laps = 1) const {
151  return VertexFaceIter(_h, this, _max_laps);
152  }
153 
154  std::pair<VertexFaceIter, VertexFaceIter> vertex_faces(const VertexHandle& _h, int _max_laps = 1) const {
155  VertexFaceIter begin = vf_iter(_h, _max_laps);
156  return std::make_pair(begin, make_end_circulator(begin));
157  }
158 
159  VertexCellIter vc_iter(const VertexHandle& _h, int _max_laps = 1) const {
160  return VertexCellIter(_h, this, _max_laps);
161  }
162 
163  std::pair<VertexCellIter, VertexCellIter> vertex_cells(const VertexHandle& _h, int _max_laps = 1) const {
164  VertexCellIter begin = vc_iter(_h, _max_laps);
165  return std::make_pair(begin, make_end_circulator(begin));
166  }
167 
168  HalfEdgeCellIter hec_iter(const HalfEdgeHandle& _h, int _max_laps = 1) const {
169  return HalfEdgeCellIter(_h, this, _max_laps);
170  }
171 
172  std::pair<HalfEdgeCellIter, HalfEdgeCellIter> halfedge_cells(const HalfEdgeHandle& _h, int _max_laps = 1) const {
173  HalfEdgeCellIter begin = hec_iter(_h, _max_laps);
174  return std::make_pair(begin, make_end_circulator(begin));
175  }
176 
177  CellVertexIter cv_iter(const CellHandle& _h, int _max_laps = 1) const {
178  return CellVertexIter(_h, this, _max_laps);
179  }
180 
181  std::pair<CellVertexIter, CellVertexIter> cell_vertices(const CellHandle& _h, int _max_laps = 1) const {
182  CellVertexIter begin = cv_iter(_h, _max_laps);
183  return std::make_pair(begin, make_end_circulator(begin));
184  }
185 
186  CellCellIter cc_iter(const CellHandle& _h, int _max_laps = 1) const {
187  return CellCellIter(_h, this, _max_laps);
188  }
189 
190  std::pair<CellCellIter, CellCellIter> cell_cells(const CellHandle& _h, int _max_laps = 1) const {
191  CellCellIter begin = cc_iter(_h, _max_laps);
192  return std::make_pair(begin, make_end_circulator(begin));
193  }
194 
195  HalfFaceVertexIter hfv_iter(const HalfFaceHandle& _h, int _max_laps = 1) const {
196  return HalfFaceVertexIter(_h, this, _max_laps);
197  }
198 
199  std::pair<HalfFaceVertexIter, HalfFaceVertexIter> halfface_vertices(const HalfFaceHandle& _h, int _max_laps = 1) const {
200  HalfFaceVertexIter begin = hfv_iter(_h, _max_laps);
201  return std::make_pair(begin, make_end_circulator(begin));
202  }
203 
204  BoundaryHalfFaceHalfFaceIter bhfhf_iter(const HalfFaceHandle& _ref_h, int _max_laps = 1) const {
205  return BoundaryHalfFaceHalfFaceIter(_ref_h, this, _max_laps);
206  }
207 
208  std::pair<BoundaryHalfFaceHalfFaceIter, BoundaryHalfFaceHalfFaceIter> boundary_halfface_halffaces(const HalfFaceHandle& _h, int _max_laps = 1) const {
209  BoundaryHalfFaceHalfFaceIter begin = bhfhf_iter(_h, _max_laps);
210  return std::make_pair(begin, make_end_circulator(begin));
211  }
212 
213  /*
214  * Iterators
215  */
216 
217  BoundaryFaceIter bf_iter() const {
218  return BoundaryFaceIter(this);
219  }
220 
221  VertexIter v_iter() const {
222  return VertexIter(this);
223  }
224 
225  VertexIter vertices_begin() const {
226  return VertexIter(this, VertexHandle(0));
227  }
228 
229  VertexIter vertices_end() const {
230  return VertexIter(this, VertexHandle((int)n_vertices()));
231  }
232 
233  std::pair<VertexIter, VertexIter> vertices() const {
234  return std::make_pair(vertices_begin(), vertices_end());
235  }
236 
237  EdgeIter e_iter() const {
238  return EdgeIter(this);
239  }
240 
241  EdgeIter edges_begin() const {
242  return EdgeIter(this, EdgeHandle(0));
243  }
244 
245  EdgeIter edges_end() const {
246  return EdgeIter(this, EdgeHandle((int)edges_.size()));
247  }
248 
249  std::pair<EdgeIter, EdgeIter> edges() const {
250  return std::make_pair(edges_begin(), edges_end());
251  }
252 
253  HalfEdgeIter he_iter() const {
254  return HalfEdgeIter(this);
255  }
256 
257  HalfEdgeIter halfedges_begin() const {
258  return HalfEdgeIter(this, HalfEdgeHandle(0));
259  }
260 
261  HalfEdgeIter halfedges_end() const {
262  return HalfEdgeIter(this, HalfEdgeHandle((int)edges_.size() * 2));
263  }
264 
265  std::pair<HalfEdgeIter, HalfEdgeIter> halfedges() const {
266  return std::make_pair(halfedges_begin(), halfedges_end());
267  }
268 
269  FaceIter f_iter() const {
270  return FaceIter(this);
271  }
272 
273  FaceIter faces_begin() const {
274  return FaceIter(this, FaceHandle(0));
275  }
276 
277  FaceIter faces_end() const {
278  return FaceIter(this, FaceHandle((int)faces_.size()));
279  }
280 
281  std::pair<FaceIter, FaceIter> faces() const {
282  return std::make_pair(faces_begin(), faces_end());
283  }
284 
285  HalfFaceIter hf_iter() const {
286  return HalfFaceIter(this);
287  }
288 
289  HalfFaceIter halffaces_begin() const {
290  return HalfFaceIter(this, HalfFaceHandle(0));
291  }
292 
293  HalfFaceIter halffaces_end() const {
294  return HalfFaceIter(this, HalfFaceHandle((int)faces_.size() * 2));
295  }
296 
297  std::pair<HalfFaceIter, HalfFaceIter> halffaces() const {
298  return std::make_pair(halffaces_begin(), halffaces_end());
299  }
300 
301  CellIter c_iter() const {
302  return CellIter(this);
303  }
304 
305  CellIter cells_begin() const {
306  return CellIter(this, CellHandle(0));
307  }
308 
309  CellIter cells_end() const {
310  return CellIter(this, CellHandle((int)cells_.size()));
311  }
312 
313  std::pair<CellIter, CellIter> cells() const {
314  return std::make_pair(cells_begin(), cells_end());
315  }
316 
317  /*
318  * Virtual functions with implementation
319  */
320 
322  virtual size_t n_vertices() const { return n_vertices_; }
324  virtual size_t n_edges() const { return edges_.size(); }
326  virtual size_t n_halfedges() const { return edges_.size() * 2u; }
328  virtual size_t n_faces() const { return faces_.size(); }
330  virtual size_t n_halffaces() const { return faces_.size() * 2u; }
332  virtual size_t n_cells() const { return cells_.size(); }
333 
335  size_t n_logical_vertices() const { return n_vertices_ - n_deleted_vertices_; }
337  size_t n_logical_edges() const { return edges_.size() - n_deleted_edges_; }
339  size_t n_logical_halfedges() const { return n_logical_edges() * 2u; }
341  size_t n_logical_faces() const { return faces_.size() - n_deleted_faces_; }
343  size_t n_logical_halffaces() const { return n_faces() * 2u; }
345  size_t n_logical_cells() const { return cells_.size() - n_deleted_cells_; }
346 
347  int genus() const {
348 
349  int g = (1 - (int)(n_vertices() -
350  n_edges() +
351  n_faces() -
352  n_cells()));
353 
354  if(g % 2 == 0) return (g / 2);
355 
356  // An error occured
357  // The mesh might not be manifold
358  return -1;
359  }
360 
361 private:
362 
363  // Cache total vertex number
364  size_t n_vertices_;
365 
366 public:
367 
369  virtual VertexHandle add_vertex();
370 
371  //=======================================================================
372 
374  virtual EdgeHandle add_edge(const VertexHandle& _fromVertex, const VertexHandle& _toHandle, bool _allowDuplicates = false);
375 
383  virtual FaceHandle add_face(const std::vector<HalfEdgeHandle>& _halfedges, bool _topologyCheck = false);
384 
386  virtual FaceHandle add_face(const std::vector<VertexHandle>& _vertices);
387 
395  virtual CellHandle add_cell(const std::vector<HalfFaceHandle>& _halffaces, bool _topologyCheck = false);
396 
398  void set_edge(const EdgeHandle& _eh, const VertexHandle& _fromVertex, const VertexHandle& _toVertex);
399 
401  void set_face(const FaceHandle& _fh, const std::vector<HalfEdgeHandle>& _hes);
402 
404  void set_cell(const CellHandle& _ch, const std::vector<HalfFaceHandle>& _hfs);
405 
406  /*
407  * Non-virtual functions
408  */
409 
411  const Edge& edge(const EdgeHandle& _edgeHandle) const;
412 
414  const Face& face(const FaceHandle& _faceHandle) const;
415 
417  const Cell& cell(const CellHandle& _cellHandle) const;
418 
420  Edge& edge(const EdgeHandle& _edgeHandle);
421 
423  Face& face(const FaceHandle& _faceHandle);
424 
426  Cell& cell(const CellHandle& _cellHandle);
427 
429  Edge halfedge(const HalfEdgeHandle& _halfEdgeHandle) const;
430 
432  Face halfface(const HalfFaceHandle& _halfFaceHandle) const;
433 
435  Edge opposite_halfedge(const HalfEdgeHandle& _halfEdgeHandle) const;
436 
438  Face opposite_halfface(const HalfFaceHandle& _halfFaceHandle) const;
439 
441  HalfEdgeHandle halfedge(const VertexHandle& _vh1, const VertexHandle& _vh2) const;
442 
446  HalfFaceHandle halfface(const std::vector<VertexHandle>& _vs) const;
447 
451  HalfFaceHandle halfface_extensive(const std::vector<VertexHandle>& _vs) const;
452 
456  HalfFaceHandle halfface(const std::vector<HalfEdgeHandle>& _hes) const;
457 
460 
463 
465  inline size_t valence(const VertexHandle& _vh) const {
466  assert(has_vertex_bottom_up_incidences());
467  assert(_vh.is_valid() && (size_t)_vh.idx() < outgoing_hes_per_vertex_.size());
468 
469  return outgoing_hes_per_vertex_[_vh.idx()].size();
470  }
471 
473  inline size_t valence(const EdgeHandle& _eh) const {
474  assert(has_edge_bottom_up_incidences());
475  assert(_eh.is_valid() && (size_t)_eh.idx() < edges_.size());
476  assert((size_t)halfedge_handle(_eh, 0).idx() < incident_hfs_per_he_.size());
477 
478  return incident_hfs_per_he_[halfedge_handle(_eh, 0).idx()].size();
479  }
480 
482  inline size_t valence(const FaceHandle& _fh) const {
483  assert(_fh.is_valid() && (size_t)_fh.idx() < faces_.size());
484 
485  return face(_fh).halfedges().size();
486  }
487 
489  inline size_t valence(const CellHandle& _ch) const {
490  assert(_ch.is_valid() && (size_t)_ch.idx() < cells_.size());
491 
492  return cell(_ch).halffaces().size();
493  }
494 
495  //=====================================================================
496  // Delete entities
497  //=====================================================================
498 
499 public:
500 
501  virtual VertexIter delete_vertex(const VertexHandle& _h);
502 
503  virtual EdgeIter delete_edge(const EdgeHandle& _h);
504 
505  virtual FaceIter delete_face(const FaceHandle& _h);
506 
507  virtual CellIter delete_cell(const CellHandle& _h);
508 
509  virtual void collect_garbage();
510 
511 
512  virtual bool is_deleted(const VertexHandle& _h) const { return vertex_deleted_[_h.idx()]; }
513  virtual bool is_deleted(const EdgeHandle& _h) const { return edge_deleted_[_h.idx()]; }
514  virtual bool is_deleted(const HalfEdgeHandle& _h) const { return edge_deleted_[_h.idx()/2]; }
515  virtual bool is_deleted(const FaceHandle& _h) const { return face_deleted_[_h.idx()]; }
516  virtual bool is_deleted(const HalfFaceHandle& _h) const { return face_deleted_[_h.idx()/2]; }
517  virtual bool is_deleted(const CellHandle& _h) const { return cell_deleted_[_h.idx()]; }
518 
519 private:
520 
521  template <class ContainerT>
522  void get_incident_edges(const ContainerT& _vs, std::set<EdgeHandle>& _es) const;
523 
524  template <class ContainerT>
525  void get_incident_faces(const ContainerT& _es, std::set<FaceHandle>& _fs) const;
526 
527  template <class ContainerT>
528  void get_incident_cells(const ContainerT& _fs, std::set<CellHandle>& _cs) const;
529 
531 
533 
535 
537 
538 public:
539 
541  virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2);
542 
544  virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2);
545 
547  virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2);
548 
550  virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2);
551 
552 protected:
553 
554  virtual void delete_multiple_vertices(const std::vector<bool>& _tag);
555 
556  virtual void delete_multiple_edges(const std::vector<bool>& _tag);
557 
558  virtual void delete_multiple_faces(const std::vector<bool>& _tag);
559 
560  virtual void delete_multiple_cells(const std::vector<bool>& _tag);
561 
563  public:
564  explicit EdgeCorrector(const std::vector<int>& _newIndices) :
565  newIndices_(_newIndices) {}
566 
567  void operator()(Edge& _edge) {
568  _edge.set_from_vertex(VertexHandle(newIndices_[_edge.from_vertex().idx()]));
569  _edge.set_to_vertex(VertexHandle(newIndices_[_edge.to_vertex().idx()]));
570  }
571  private:
572  const std::vector<int>& newIndices_;
573  };
574 
576  public:
577  explicit FaceCorrector(const std::vector<int>& _newIndices) :
578  newIndices_(_newIndices) {}
579 
580  void operator()(Face& _face) {
581  std::vector<HalfEdgeHandle> hes = _face.halfedges();
582  for(std::vector<HalfEdgeHandle>::iterator he_it = hes.begin(),
583  he_end = hes.end(); he_it != he_end; ++he_it) {
584 
585  EdgeHandle eh = edge_handle(*he_it);
586  unsigned char opp = (he_it->idx() - halfedge_handle(eh, 0).idx());
587  *he_it = halfedge_handle(EdgeHandle(newIndices_[eh.idx()]), opp);
588  }
589  _face.set_halfedges(hes);
590  }
591  private:
592  const std::vector<int>& newIndices_;
593  };
594 
596  public:
597  explicit CellCorrector(const std::vector<int>& _newIndices) :
598  newIndices_(_newIndices) {}
599 
600  void operator()(Cell& _cell) {
601  std::vector<HalfFaceHandle> hfs = _cell.halffaces();
602  for(std::vector<HalfFaceHandle>::iterator hf_it = hfs.begin(),
603  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
604 
605  FaceHandle fh = face_handle(*hf_it);
606  unsigned char opp = (hf_it->idx() - halfface_handle(fh, 0).idx());
607  *hf_it = halfface_handle(FaceHandle(newIndices_[fh.idx()]), opp);
608  }
609  _cell.set_halffaces(hfs);
610  }
611  private:
612  const std::vector<int>& newIndices_;
613  };
614 
615 public:
616 
625  CellIter delete_cell_range(const CellIter& _first, const CellIter& _last);
626 
627 public:
628 
630  virtual void clear(bool _clearProps = true) {
631 
632  edges_.clear();
633  faces_.clear();
634  cells_.clear();
635  vertex_deleted_.clear();
636  edge_deleted_.clear();
637  face_deleted_.clear();
638  cell_deleted_.clear();
639  n_deleted_vertices_ = 0;
640  n_deleted_edges_ = 0;
641  n_deleted_faces_ = 0;
642  n_deleted_cells_ = 0;
643  outgoing_hes_per_vertex_.clear();
644  incident_hfs_per_he_.clear();
645  incident_cell_per_hf_.clear();
646  n_vertices_ = 0;
647 
648  if(_clearProps) {
649 
650  // Delete all property data
651  clear_vertex_props();
652  clear_edge_props();
653  clear_halfedge_props();
654  clear_face_props();
655  clear_halfface_props();
656  clear_cell_props();
657  clear_mesh_props();
658 
659  } else {
660  // Resize props
661  resize_vprops(0u);
662  resize_eprops(0u);
663  resize_fprops(0u);
664  resize_cprops(0u);
665  }
666  }
667 
668  //=====================================================================
669  // Bottom-up Incidences
670  //=====================================================================
671 
672 public:
673 
674  void enable_bottom_up_incidences(bool _enable = true) {
675 
676  enable_vertex_bottom_up_incidences(_enable);
677  enable_edge_bottom_up_incidences(_enable);
678  enable_face_bottom_up_incidences(_enable);
679  }
680 
681  void enable_vertex_bottom_up_incidences(bool _enable = true) {
682 
683  if(_enable && !v_bottom_up_) {
684  // Vertex bottom-up incidences have to be
685  // recomputed for the whole mesh
686  compute_vertex_bottom_up_incidences();
687  }
688 
689  if(!_enable) {
690  outgoing_hes_per_vertex_.clear();
691  }
692 
693  v_bottom_up_ = _enable;
694  }
695 
696  void enable_edge_bottom_up_incidences(bool _enable = true) {
697 
698  if(_enable && !e_bottom_up_) {
699  // Edge bottom-up incidences have to be
700  // recomputed for the whole mesh
701  compute_edge_bottom_up_incidences();
702 
703  if(f_bottom_up_) {
704 #if defined(__clang_major__) && (__clang_major__ >= 5)
705  for(EdgeIter e_it = edges_begin(), e_end = edges_end();
706  e_it != e_end; ++e_it) {
707  reorder_incident_halffaces(*e_it);
708  }
709 #else
710  std::for_each(edges_begin(), edges_end(),
711  fun::bind(&TopologyKernel::reorder_incident_halffaces, this, fun::placeholders::_1));
712 #endif
713  }
714  }
715 
716  if(!_enable) {
717  incident_hfs_per_he_.clear();
718  }
719 
720  e_bottom_up_ = _enable;
721  }
722 
723  void enable_face_bottom_up_incidences(bool _enable = true) {
724 
725  bool updateOrder = false;
726  if(_enable && !f_bottom_up_) {
727  // Face bottom-up incidences have to be
728  // recomputed for the whole mesh
729  compute_face_bottom_up_incidences();
730 
731  updateOrder = true;
732  }
733 
734  if(!_enable) {
735  incident_cell_per_hf_.clear();
736  }
737 
738  f_bottom_up_ = _enable;
739 
740  if(updateOrder) {
741  if(e_bottom_up_) {
742 #if defined(__clang_major__) && (__clang_major__ >= 5)
743  for(EdgeIter e_it = edges_begin(), e_end = edges_end();
744  e_it != e_end; ++e_it) {
745  reorder_incident_halffaces(*e_it);
746  }
747 #else
748  std::for_each(edges_begin(), edges_end(),
749  fun::bind(&TopologyKernel::reorder_incident_halffaces, this, fun::placeholders::_1));
750 #endif
751  }
752  }
753  }
754 
755  bool has_full_bottom_up_incidences() const {
756  return (has_vertex_bottom_up_incidences() &&
757  has_edge_bottom_up_incidences() &&
758  has_face_bottom_up_incidences());
759  }
760 
761  bool has_vertex_bottom_up_incidences() const { return v_bottom_up_; }
762 
763  bool has_edge_bottom_up_incidences() const { return e_bottom_up_; }
764 
765  bool has_face_bottom_up_incidences() const { return f_bottom_up_; }
766 
767 
768  void enable_deferred_deletion(bool _enable = true);
769  bool deferred_deletion_enabled() const { return deferred_deletion; }
770 
771 
772  void enable_fast_deletion(bool _enable = true) { fast_deletion = _enable; }
773  bool fast_deletion_enabled() const { return fast_deletion; }
774 
775 
776 protected:
777 
778  void compute_vertex_bottom_up_incidences();
779 
780  void compute_edge_bottom_up_incidences();
781 
782  void compute_face_bottom_up_incidences();
783 
784  void reorder_incident_halffaces(const EdgeHandle& _eh);
785 
786  // Outgoing halfedges per vertex
787  std::vector<std::vector<HalfEdgeHandle> > outgoing_hes_per_vertex_;
788 
789  // Incident halffaces per (directed) halfedge
790  std::vector<std::vector<HalfFaceHandle> > incident_hfs_per_he_;
791 
792  // Incident cell (at most one) per halfface
793  std::vector<CellHandle> incident_cell_per_hf_;
794 
795 private:
796  bool v_bottom_up_;
797 
798  bool e_bottom_up_;
799 
800  bool f_bottom_up_;
801 
802  bool deferred_deletion;
803 
804  bool fast_deletion;
805 
806  //=====================================================================
807  // Connectivity
808  //=====================================================================
809 
810 public:
811 
818  HalfFaceHandle adjacent_halfface_in_cell(const HalfFaceHandle& _halfFaceHandle, const HalfEdgeHandle& _halfEdgeHandle) const;
819 
821  CellHandle incident_cell(const HalfFaceHandle& _halfFaceHandle) const;
822 
823  bool is_boundary(const HalfFaceHandle& _halfFaceHandle) const {
824 
825  assert(_halfFaceHandle.is_valid() && (size_t)_halfFaceHandle.idx() < faces_.size() * 2u);
826  assert(has_face_bottom_up_incidences());
827  assert((size_t)_halfFaceHandle.idx() < incident_cell_per_hf_.size());
828  return incident_cell_per_hf_[_halfFaceHandle.idx()] == InvalidCellHandle;
829  }
830 
831  bool is_boundary(const FaceHandle& _faceHandle) const {
832  assert(_faceHandle.is_valid() && (size_t)_faceHandle.idx() < faces_.size());
833  assert(has_face_bottom_up_incidences());
834  return is_boundary(halfface_handle(_faceHandle, 0)) ||
835  is_boundary(halfface_handle(_faceHandle, 1));
836  }
837 
838  bool is_boundary(const EdgeHandle& _edgeHandle) const {
839  assert(has_edge_bottom_up_incidences());
840  assert(_edgeHandle.is_valid() && (size_t)_edgeHandle.idx() < edges_.size());
841 
842  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(halfedge_handle(_edgeHandle, 0));
843  hehf_it.valid(); ++hehf_it) {
844  if(is_boundary(face_handle(*hehf_it))) {
845  return true;
846  }
847  }
848  return false;
849  }
850 
851  bool is_boundary(const HalfEdgeHandle& _halfedgeHandle) const {
852  assert(has_edge_bottom_up_incidences());
853  assert(_halfedgeHandle.is_valid() && (size_t)_halfedgeHandle.idx() < edges_.size() * 2u);
854 
855  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(_halfedgeHandle);
856  hehf_it.valid(); ++hehf_it) {
857  if(is_boundary(face_handle(*hehf_it))) {
858  return true;
859  }
860  }
861  return false;
862  }
863 
864  bool is_boundary(const VertexHandle& _vertexHandle) const {
865  assert(has_vertex_bottom_up_incidences());
866  assert(_vertexHandle.is_valid() && (size_t)_vertexHandle.idx() < n_vertices());
867 
868  for(VertexOHalfEdgeIter voh_it = voh_iter(_vertexHandle); voh_it.valid(); ++voh_it) {
869  if(is_boundary(*voh_it)) return true;
870  }
871  return false;
872  }
873 
874  size_t n_vertices_in_cell(const CellHandle& _ch) const {
875  assert(_ch.is_valid() && (size_t)_ch.idx() < cells_.size());
876 
877  std::set<VertexHandle> vertices;
878  std::vector<HalfFaceHandle> hfs = cell(_ch).halffaces();
879  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin();
880  hf_it != hfs.end(); ++hf_it) {
881  std::vector<HalfEdgeHandle> hes = halfface(*hf_it).halfedges();
882  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin();
883  he_it != hes.end(); ++he_it) {
884  vertices.insert(halfedge(*he_it).to_vertex());
885  }
886  }
887  return vertices.size();
888  }
889 
890  //=========================================================================
891 
892  /*
893  * Non-virtual functions
894  */
895 
896  Edge opposite_halfedge(const Edge& _edge) const {
897  return Edge(_edge.to_vertex(), _edge.from_vertex());
898  }
899 
900  Face opposite_halfface(const Face& _face) const {
901  std::vector<HalfEdgeHandle> opp_halfedges;
902  for(std::vector<HalfEdgeHandle>::const_iterator it = _face.halfedges().begin(); it
903  != _face.halfedges().end(); ++it) {
904  opp_halfedges.insert(opp_halfedges.begin(), opposite_halfedge_handle(*it));
905  }
906 
907  return Face(opp_halfedges);
908  }
909 
910  /*
911  * Static functions
912  */
913 
915  static inline HalfEdgeHandle halfedge_handle(const EdgeHandle& _h, const unsigned char _subIdx) {
916  // Is handle in range?
917  assert(_h.is_valid());
918  assert(_subIdx < 2);
919  // if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfEdgeHandle;
920  return HalfEdgeHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
921  }
922 
924  static inline HalfFaceHandle halfface_handle(const FaceHandle& _h, const unsigned char _subIdx) {
925  // Is handle in range?
926  assert(_h.is_valid());
927  assert(_subIdx < 2);
928  // if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfFaceHandle;
929  return HalfFaceHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
930  }
931 
933  static inline EdgeHandle edge_handle(const HalfEdgeHandle& _h) {
934  // Is handle in range?
935  assert(_h.is_valid());
936  // if(_h.idx() < 0) return InvalidEdgeHandle;
937  return EdgeHandle((int)(_h.idx() / 2));
938  }
939 
940  static inline FaceHandle face_handle(const HalfFaceHandle& _h) {
941  // Is handle in range?
942  assert(_h.is_valid());
943  // if(_h.idx() < 0) return InvalidFaceHandle;
944  return FaceHandle((int)(_h.idx() / 2));
945  }
946 
947  static inline HalfEdgeHandle opposite_halfedge_handle(const HalfEdgeHandle& _h) {
948  // Is handle in range?
949  assert(_h.is_valid());
950  // if(_h.idx() < 0) return InvalidHalfEdgeHandle;
951 
952  // Is handle even?
953  if(_h.idx() % 2 == 0) {
954  return HalfEdgeHandle(_h.idx() + 1);
955  }
956  return HalfEdgeHandle(_h.idx() - 1);
957  }
958 
959  static inline HalfFaceHandle opposite_halfface_handle(const HalfFaceHandle& _h) {
960  // Is handle in range?
961  assert(_h.is_valid());
962  // if(_h.idx() < 0) return InvalidHalfFaceHandle;
963 
964  // Is handle even?
965  if(_h.idx() % 2 == 0) {
966  return HalfFaceHandle(_h.idx() + 1);
967  }
968  return HalfFaceHandle(_h.idx() - 1);
969  }
970 
971  bool inline needs_garbage_collection() const {
972  return n_deleted_vertices_ > 0 || n_deleted_edges_ > 0 || n_deleted_faces_ > 0 || n_deleted_cells_ > 0;
973  }
974 
975 protected:
976 
977  // List of edges
978  std::vector<Edge> edges_;
979 
980  // List of faces
981  std::vector<Face> faces_;
982 
983  // List of cells
984  std::vector<Cell> cells_;
985 
986  std::vector<bool> vertex_deleted_;
987  std::vector<bool> edge_deleted_;
988  std::vector<bool> face_deleted_;
989  std::vector<bool> cell_deleted_;
990 
991  // number of elements deleted, but not yet garbage collected
992  size_t n_deleted_vertices_ = 0;
993  size_t n_deleted_edges_ = 0;
994  size_t n_deleted_faces_ = 0;
995  size_t n_deleted_cells_ = 0;
996 
997 };
998 
999 }
1000 
1001 #endif /* TOPOLOGYKERNEL_HH_ */
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:101
virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2)
Exchanges the indices of two vertices while keeping the mesh otherwise unaffected.
const Edge & edge(const EdgeHandle &_edgeHandle) const
Get edge with handle _edgeHandle.
virtual size_t n_halfedges() const
Get number of halfedges in mesh.
CellIter delete_cell_range(const CellIter &_first, const CellIter &_last)
Delete range of cells.
FaceIter delete_face_core(const FaceHandle &_h)
Delete face from mesh.
virtual VertexIter delete_vertex(const VertexHandle &_h)
Delete vertex from mesh.
static HalfEdgeHandle halfedge_handle(const EdgeHandle &_h, const unsigned char _subIdx)
Conversion function.
size_t valence(const VertexHandle &_vh) const
Get valence of vertex (number of incident edges)
void resize_cprops(size_t _nc)
Change size of stored cell properties.
size_t n_logical_cells() const
Get number of undeleted cells in mesh.
size_t n_logical_halffaces() const
Get number of undeleted halffaces in mesh.
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.
Edge opposite_halfedge(const HalfEdgeHandle &_halfEdgeHandle) const
Get opposite halfedge that corresponds to halfedge with handle _halfEdgeHandle.
void resize_eprops(size_t _ne)
Change size of stored edge properties.
void resize_vprops(size_t _nv)
Change size of stored vertex properties.
VertexIter delete_vertex_core(const VertexHandle &_h)
Delete vertex from mesh.
virtual size_t n_halffaces() const
Get number of halffaces in mesh.
virtual FaceHandle add_face(const std::vector< HalfEdgeHandle > &_halfedges, bool _topologyCheck=false)
Add face via incident edges.
virtual EdgeHandle add_edge(const VertexHandle &_fromVertex, const VertexHandle &_toHandle, bool _allowDuplicates=false)
Add edge.
virtual FaceIter delete_face(const FaceHandle &_h)
Delete face from mesh.
virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2)
Exchanges the indices of two cells while keeping the mesh otherwise unaffected.
Face opposite_halfface(const HalfFaceHandle &_halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
size_t valence(const CellHandle &_ch) const
Get valence of cell (number of incident faces)
EdgeIter delete_edge_core(const EdgeHandle &_h)
Delete edge from mesh.
static EdgeHandle edge_handle(const HalfEdgeHandle &_h)
Handle conversion.
size_t valence(const FaceHandle &_fh) const
Get valence of face (number of incident edges)
Face halfface(const HalfFaceHandle &_halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
HalfFaceHandle adjacent_halfface_in_cell(const HalfFaceHandle &_halfFaceHandle, const HalfEdgeHandle &_halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell.
virtual size_t n_faces() const
Get number of faces in mesh.
virtual CellHandle add_cell(const std::vector< HalfFaceHandle > &_halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
void set_cell(const CellHandle &_ch, const std::vector< HalfFaceHandle > &_hfs)
Set the half-faces of a cell.
virtual void collect_garbage()
Delete all entities that are marked as deleted.
HalfEdgeHandle prev_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get previous halfedge within a halfface.
const Face & face(const FaceHandle &_faceHandle) const
Get face with handle _faceHandle.
void resize_fprops(size_t _nf)
Change size of stored face properties.
void set_face(const FaceHandle &_fh, const std::vector< HalfEdgeHandle > &_hes)
Set the half-edges of a face.
virtual void clear(bool _clearProps=true)
Clear whole mesh.
size_t n_logical_edges() const
Get number of undeleted edges in mesh.
size_t n_logical_vertices() const
Get number of undeleted vertices in mesh.
virtual size_t n_cells() const
Get number of cells in mesh.
void set_edge(const EdgeHandle &_eh, const VertexHandle &_fromVertex, const VertexHandle &_toVertex)
Set the vertices of an edge.
size_t valence(const EdgeHandle &_eh) const
Get valence of edge (number of incident faces)
virtual size_t n_edges() const
Get number of edges in mesh.
CellHandle incident_cell(const HalfFaceHandle &_halfFaceHandle) const
Get cell that is incident to the given halfface.
size_t n_logical_faces() const
Get number of undeleted faces in mesh.
Edge halfedge(const HalfEdgeHandle &_halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
static HalfFaceHandle halfface_handle(const FaceHandle &_h, const unsigned char _subIdx)
Conversion function.
virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2)
Exchanges the indices of two edges while keeping the mesh otherwise unaffected.
CellIter delete_cell_core(const CellHandle &_h)
Delete cell from mesh.
HalfEdgeHandle next_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get next halfedge within a halfface.
virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2)
Exchanges the indices of two faces while keeping the mesh otherwise unaffected.
virtual size_t n_vertices() const
Get number of vertices in mesh.
virtual CellIter delete_cell(const CellHandle &_h)
Delete cell from mesh.
size_t n_logical_halfedges() const
Get number of undeleted halfedges in mesh.
HalfFaceHandle halfface_extensive(const std::vector< VertexHandle > &_vs) const
virtual EdgeIter delete_edge(const EdgeHandle &_h)
Delete edge from mesh.
virtual VertexHandle add_vertex()
Add abstract vertex.