OpenVolumeMesh
 All Classes Functions Variables Typedefs Pages
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: 223 $ *
38  * $Date: 2012-08-02 13:42:58 +0200 (Thu, 02 Aug 2012) $ *
39  * $LastChangedBy: kremer $ *
40  * *
41 \*===========================================================================*/
42 
43 #ifndef TOPOLOGYKERNEL_HH_
44 #define TOPOLOGYKERNEL_HH_
45 
46 #include <set>
47 #include <vector>
48 #include <iostream>
49 #include <cassert>
50 
51 #include "BaseEntities.hh"
52 #include "OpenVolumeMeshHandle.hh"
53 #include "ResourceManager.hh"
54 #include "Iterators.hh"
55 
56 namespace OpenVolumeMesh {
57 
59 public:
60 
62  virtual ~TopologyKernel();
63 
64  /*
65  * Defines and constants
66  */
67 
68  static const VertexHandle InvalidVertexHandle;
69  static const EdgeHandle InvalidEdgeHandle;
70  static const FaceHandle InvalidFaceHandle;
71  static const CellHandle InvalidCellHandle;
72  static const HalfEdgeHandle InvalidHalfEdgeHandle;
73  static const HalfFaceHandle InvalidHalfFaceHandle;
74 
75  typedef OpenVolumeMeshEdge Edge;
76  typedef OpenVolumeMeshFace Face;
77  typedef OpenVolumeMeshCell Cell;
78 
79  // Add StatusAttrib to list of friend classes
80  // since it provides a garbage collection
81  // that needs access to some protected methods
82  friend class StatusAttrib;
83 
84  //=====================================================================
85  // Iterators
86  //=====================================================================
87 
88  friend class VertexOHalfEdgeIter;
89  friend class HalfEdgeHalfFaceIter;
90  friend class VertexCellIter;
91  friend class HalfEdgeCellIter;
92  friend class CellVertexIter;
93  friend class CellCellIter;
94  friend class HalfFaceVertexIter;
95  friend class BoundaryHalfFaceHalfFaceIter;
96  friend class BoundaryFaceIter;
97  friend class VertexIter;
98  friend class EdgeIter;
99  friend class HalfEdgeIter;
100  friend class FaceIter;
101  friend class HalfFaceIter;
102  friend class CellIter;
103 
104  VertexOHalfEdgeIter voh_iter(const VertexHandle& _h) const {
105  return VertexOHalfEdgeIter(_h, this);
106  }
107 
108  HalfEdgeHalfFaceIter hehf_iter(const HalfEdgeHandle& _h) const {
109  return HalfEdgeHalfFaceIter(_h, this);
110  }
111 
112  VertexCellIter vc_iter(const VertexHandle& _h) const {
113  return VertexCellIter(_h, this);
114  }
115 
116  HalfEdgeCellIter hec_iter(const HalfEdgeHandle& _h) const {
117  return HalfEdgeCellIter(_h, this);
118  }
119 
120  CellVertexIter cv_iter(const CellHandle& _h) const {
121  return CellVertexIter(_h, this);
122  }
123 
124  CellCellIter cc_iter(const CellHandle& _h) const {
125  return CellCellIter(_h, this);
126  }
127 
128  HalfFaceVertexIter hfv_iter(const HalfFaceHandle& _h) const {
129  return HalfFaceVertexIter(_h, this);
130  }
131 
132  BoundaryHalfFaceHalfFaceIter bhfhf_iter(const HalfFaceHandle& _ref_h) const {
133  return BoundaryHalfFaceHalfFaceIter(_ref_h, this);
134  }
135 
136  BoundaryFaceIter bf_iter() const {
137  return BoundaryFaceIter(this);
138  }
139 
140  VertexIter v_iter() const {
141  return VertexIter(this);
142  }
143 
144  VertexIter vertices_begin() const {
145  return VertexIter(this, VertexHandle(0));
146  }
147 
148  VertexIter vertices_end() const {
149  return VertexIter(this, VertexHandle(n_vertices()));
150  }
151 
152  EdgeIter e_iter() const {
153  return EdgeIter(this);
154  }
155 
156  EdgeIter edges_begin() const {
157  return EdgeIter(this, EdgeHandle(0));
158  }
159 
160  EdgeIter edges_end() const {
161  return EdgeIter(this, EdgeHandle(edges_.size()));
162  }
163 
164  HalfEdgeIter he_iter() const {
165  return HalfEdgeIter(this);
166  }
167 
168  HalfEdgeIter halfedges_begin() const {
169  return HalfEdgeIter(this, HalfEdgeHandle(0));
170  }
171 
172  HalfEdgeIter halfedges_end() const {
173  return HalfEdgeIter(this, HalfEdgeHandle(edges_.size() * 2));
174  }
175 
176  FaceIter f_iter() const {
177  return FaceIter(this);
178  }
179 
180  FaceIter faces_begin() const {
181  return FaceIter(this, FaceHandle(0));
182  }
183 
184  FaceIter faces_end() const {
185  return FaceIter(this, FaceHandle(faces_.size()));
186  }
187 
188  HalfFaceIter hf_iter() const {
189  return HalfFaceIter(this);
190  }
191 
192  HalfFaceIter halffaces_begin() const {
193  return HalfFaceIter(this, HalfFaceHandle(0));
194  }
195 
196  HalfFaceIter halffaces_end() const {
197  return HalfFaceIter(this, HalfFaceHandle(faces_.size() * 2));
198  }
199 
200  CellIter c_iter() const {
201  return CellIter(this);
202  }
203 
204  CellIter cells_begin() const {
205  return CellIter(this, CellHandle(0));
206  }
207 
208  CellIter cells_end() const {
209  return CellIter(this, CellHandle(cells_.size()));
210  }
211 
212  /*
213  * Virtual functions with implementation
214  */
215 
217  virtual unsigned int n_vertices() const { return n_vertices_; }
219  virtual unsigned int n_edges() const { return edges_.size(); }
221  virtual unsigned int n_halfedges() const { return edges_.size() * 2u; }
223  virtual unsigned int n_faces() const { return faces_.size(); }
225  virtual unsigned int n_halffaces() const { return faces_.size() * 2u; }
227  virtual unsigned int n_cells() const { return cells_.size(); }
228 
229 private:
230 
231  // Cache total vertex number
232  unsigned int n_vertices_;
233 
234 public:
235 
237  virtual VertexHandle add_vertex();
238 
239  //=======================================================================
240 
242  virtual EdgeHandle add_edge(const VertexHandle& _fromVertex, const VertexHandle& _toHandle, bool _allowDuplicates = false);
243 
245  virtual FaceHandle add_face(const std::vector<HalfEdgeHandle>& _halfedges, bool _topologyCheck = false);
246 
248  virtual FaceHandle add_face(const std::vector<VertexHandle>& _vertices);
249 
251  virtual CellHandle add_cell(const std::vector<HalfFaceHandle>& _halffaces, bool _topologyCheck = false);
252 
254  void set_edge(const EdgeHandle& _eh, const VertexHandle& _fromVertex, const VertexHandle& _toVertex);
255 
257  void set_face(const FaceHandle& _fh, const std::vector<HalfEdgeHandle>& _hes);
258 
260  void set_cell(const CellHandle& _ch, const std::vector<HalfFaceHandle>& _hfs);
261 
262  /*
263  * Non-virtual functions
264  */
265 
267  const Edge& edge(const EdgeHandle& _edgeHandle) const;
268 
270  const Face& face(const FaceHandle& _faceHandle) const;
271 
273  const Cell& cell(const CellHandle& _cellHandle) const;
274 
276  Edge& edge(const EdgeHandle& _edgeHandle);
277 
279  Face& face(const FaceHandle& _faceHandle);
280 
282  Cell& cell(const CellHandle& _cellHandle);
283 
285  const Edge halfedge(const HalfEdgeHandle& _halfEdgeHandle) const;
286 
288  const Face halfface(const HalfFaceHandle& _halfFaceHandle) const;
289 
291  const Edge opposite_halfedge(const HalfEdgeHandle& _halfEdgeHandle) const;
292 
294  const Face opposite_halfface(const HalfFaceHandle& _halfFaceHandle) const;
295 
296  // Get halfedge from vertex _vh1 to _vh2
297  const HalfEdgeHandle halfedge(const VertexHandle& _vh1, const VertexHandle& _vh2) const;
298 
299  // Get half-face from list of incident vertices (in connected order)
300  // Note: Only the first three vertices are checked
301  const HalfFaceHandle halfface(const std::vector<VertexHandle>& _vs) const;
302 
303  // Get half-face from list of incident half-edges
304  // Note: Only the first two half-edges are checked
305  const HalfFaceHandle halfface(const std::vector<HalfEdgeHandle>& _hes) const;
306 
308  const HalfEdgeHandle next_halfedge_in_halfface(const HalfEdgeHandle& _heh, const HalfFaceHandle& _hfh) const;
309 
311  const HalfEdgeHandle prev_halfedge_in_halfface(const HalfEdgeHandle& _heh, const HalfFaceHandle& _hfh) const;
312 
314  inline unsigned int valence(const VertexHandle& _vh) const {
315  if(!v_bottom_up_) {
316  std::cerr << "Could not get vertex valence: No bottom-up incidences for vertices available!" << std::endl;
317  return 0u;
318  }
319  assert((unsigned int)_vh.idx() < outgoing_hes_per_vertex_.size());
320  return outgoing_hes_per_vertex_[_vh.idx()].size();
321  }
322 
324  inline unsigned int valence(const EdgeHandle& _eh) const {
325  if(!e_bottom_up_) {
326  std::cerr << "Could not get edge valence: No bottom-up incidences for edges available!" << std::endl;
327  return 0u;
328  }
329  assert((unsigned int)halfedge_handle(_eh, 0).idx() < incident_hfs_per_he_.size());
330  return incident_hfs_per_he_[halfedge_handle(_eh, 0).idx()].size();
331  }
332 
334  inline unsigned int valence(const FaceHandle& _fh) const {
335 
336  assert((unsigned int)_fh.idx() < faces_.size());
337  return face(_fh).halfedges().size();
338  }
339 
341  inline unsigned int valence(const CellHandle& _ch) const {
342 
343  assert((unsigned int)_ch.idx() < cells_.size());
344  return cell(_ch).halffaces().size();
345  }
346 
347  //=====================================================================
348  // Delete entities
349  //=====================================================================
350 
351 public:
352 
353  virtual VertexIter delete_vertex(const VertexHandle& _h);
354 
355  virtual EdgeIter delete_edge(const EdgeHandle& _h);
356 
357  virtual FaceIter delete_face(const FaceHandle& _h);
358 
359  virtual CellIter delete_cell(const CellHandle& _h);
360 
361 protected:
362 
363  virtual void delete_multiple_vertices(const std::vector<bool>& _tag);
364 
365  virtual void delete_multiple_edges(const std::vector<bool>& _tag);
366 
367  virtual void delete_multiple_faces(const std::vector<bool>& _tag);
368 
369  virtual void delete_multiple_cells(const std::vector<bool>& _tag);
370 
372  public:
373  EdgeCorrector(const std::vector<int>& _newIndices) :
374  newIndices_(_newIndices) {}
375 
376  void operator()(Edge& _edge) {
377  _edge.set_from_vertex(VertexHandle(newIndices_[_edge.from_vertex().idx()]));
378  _edge.set_to_vertex(VertexHandle(newIndices_[_edge.to_vertex().idx()]));
379  }
380  private:
381  const std::vector<int>& newIndices_;
382  };
383 
385  public:
386  FaceCorrector(const std::vector<int>& _newIndices) :
387  newIndices_(_newIndices) {}
388 
389  void operator()(Face& _face) {
390  std::vector<HalfEdgeHandle> hes = _face.halfedges();
391  for(std::vector<HalfEdgeHandle>::iterator he_it = hes.begin(),
392  he_end = hes.end(); he_it != he_end; ++he_it) {
393 
394  EdgeHandle eh = edge_handle(*he_it);
395  unsigned char opp = (he_it->idx() - halfedge_handle(eh, 0).idx());
396  *he_it = halfedge_handle(newIndices_[eh.idx()], opp);
397  }
398  _face.set_halfedges(hes);
399  }
400  private:
401  const std::vector<int>& newIndices_;
402  };
403 
405  public:
406  CellCorrector(const std::vector<int>& _newIndices) :
407  newIndices_(_newIndices) {}
408 
409  void operator()(Cell& _cell) {
410  std::vector<HalfFaceHandle> hfs = _cell.halffaces();
411  for(std::vector<HalfFaceHandle>::iterator hf_it = hfs.begin(),
412  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
413 
414  FaceHandle fh = face_handle(*hf_it);
415  unsigned char opp = (hf_it->idx() - halfface_handle(fh, 0).idx());
416  *hf_it = halfface_handle(newIndices_[fh.idx()], opp);
417  }
418  _cell.set_halffaces(hfs);
419  }
420  private:
421  const std::vector<int>& newIndices_;
422  };
423 
424 public:
425 
434  CellIter delete_cell_range(const CellIter& _first, const CellIter& _last);
435 
436 public:
437 
439  virtual void clear(bool _clearProps = true) {
440 
441  edges_.clear();
442  faces_.clear();
443  cells_.clear();
444  outgoing_hes_per_vertex_.clear();
445  incident_hfs_per_he_.clear();
446  incident_cell_per_hf_.clear();
447  n_vertices_ = 0;
448 
449  if(_clearProps) {
450 
451  // Delete all property data
452  clear_vertex_props();
453  clear_edge_props();
454  clear_halfedge_props();
455  clear_face_props();
456  clear_halfface_props();
457  clear_cell_props();
458  clear_mesh_props();
459 
460  } else {
461  // Resize props
462  resize_vprops(0u);
463  resize_eprops(0u);
464  resize_fprops(0u);
465  resize_cprops(0u);
466  }
467  }
468 
469  //=====================================================================
470  // Bottom-up Incidences
471  //=====================================================================
472 
473 public:
474 
475  void enable_bottom_up_incidences(bool _enable = true) {
476 
477  enable_vertex_bottom_up_incidences(_enable);
478  enable_edge_bottom_up_incidences(_enable);
479  enable_face_bottom_up_incidences(_enable);
480  }
481 
482  void enable_vertex_bottom_up_incidences(bool _enable = true) {
483 
484  if(_enable && !v_bottom_up_) {
485  // Vertex bottom-up incidences have to be
486  // recomputed for the whole mesh
487  compute_vertex_bottom_up_incidences();
488  }
489 
490  if(!_enable) {
491  outgoing_hes_per_vertex_.clear();
492  }
493 
494  v_bottom_up_ = _enable;
495  }
496 
497  void enable_edge_bottom_up_incidences(bool _enable = true) {
498 
499  if(_enable && !e_bottom_up_) {
500  // Edge bottom-up incidences have to be
501  // recomputed for the whole mesh
502  compute_edge_bottom_up_incidences();
503 
504  if(f_bottom_up_) {
505  std::for_each(edges_begin(), edges_end(),
506  fun::bind(&TopologyKernel::reorder_incident_halffaces, this, fun::placeholders::_1));
507  }
508  }
509 
510  if(!_enable) {
511  incident_hfs_per_he_.clear();
512  }
513 
514  e_bottom_up_ = _enable;
515  }
516 
517  void enable_face_bottom_up_incidences(bool _enable = true) {
518 
519  bool updateOrder = false;
520  if(_enable && !f_bottom_up_) {
521  // Face bottom-up incidences have to be
522  // recomputed for the whole mesh
523  compute_face_bottom_up_incidences();
524 
525  updateOrder = true;
526  }
527 
528  if(!_enable) {
529  incident_cell_per_hf_.clear();
530  }
531 
532  f_bottom_up_ = _enable;
533 
534  if(updateOrder) {
535  if(e_bottom_up_) {
536  std::for_each(edges_begin(), edges_end(),
537  fun::bind(&TopologyKernel::reorder_incident_halffaces, this, fun::placeholders::_1));
538  }
539  }
540  }
541 
542  bool has_full_bottom_up_incidences() const {
543  return (has_vertex_bottom_up_incidences() &&
544  has_edge_bottom_up_incidences() &&
545  has_face_bottom_up_incidences());
546  }
547 
548  bool has_vertex_bottom_up_incidences() const { return v_bottom_up_; }
549 
550  bool has_edge_bottom_up_incidences() const { return e_bottom_up_; }
551 
552  bool has_face_bottom_up_incidences() const { return f_bottom_up_; }
553 
554 private:
555 
556  void compute_vertex_bottom_up_incidences();
557 
558  void compute_edge_bottom_up_incidences();
559 
560  void compute_face_bottom_up_incidences();
561 
562  void reorder_incident_halffaces(const EdgeHandle& _eh);
563 
564  // Outgoing halfedges per vertex
565  std::vector<std::vector<HalfEdgeHandle> > outgoing_hes_per_vertex_;
566 
567  // Incident halffaces per (directed) halfedge
568  std::vector<std::vector<HalfFaceHandle> > incident_hfs_per_he_;
569 
570  // Incident cell (at most one) per halfface
571  std::vector<CellHandle> incident_cell_per_hf_;
572 
573  bool v_bottom_up_;
574 
575  bool e_bottom_up_;
576 
577  bool f_bottom_up_;
578 
579  //=====================================================================
580  // Connectivity
581  //=====================================================================
582 
583 public:
584 
586  HalfFaceHandle adjacent_halfface_in_cell(const HalfFaceHandle& _halfFaceHandle, const HalfEdgeHandle& _halfEdgeHandle) const;
587 
589  CellHandle incident_cell(const HalfFaceHandle& _halfFaceHandle) const;
590 
591  bool is_boundary(const HalfFaceHandle& _halfFaceHandle) const {
592  return _halfFaceHandle.idx() >= 0 && (unsigned int)_halfFaceHandle.idx() < incident_cell_per_hf_.size() &&
593  incident_cell_per_hf_[_halfFaceHandle.idx()] == InvalidCellHandle;
594  }
595 
596  bool is_boundary(const FaceHandle& _faceHandle) const {
597  return is_boundary(halfface_handle(_faceHandle, 0)) ||
598  is_boundary(halfface_handle(_faceHandle, 1));
599  }
600 
601  bool is_boundary(const EdgeHandle& _edgeHandle) const {
602  if(!e_bottom_up_) {
603  std::cerr << "Error: Function is_boundary() needs bottom-up incidences for edges!" << std::endl;
604  return false;
605  }
606  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(halfedge_handle(_edgeHandle, 0));
607  hehf_it.valid(); ++hehf_it) {
608  if(is_boundary(face_handle(*hehf_it))) {
609  return true;
610  }
611  }
612  return false;
613  }
614 
615  bool is_boundary(const HalfEdgeHandle& _halfedgeHandle) const {
616  if(!e_bottom_up_) {
617  std::cerr << "Error: Function is_boundary() needs bottom-up incidences for edges!" << std::endl;
618  return false;
619  }
620  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(_halfedgeHandle);
621  hehf_it.valid(); ++hehf_it) {
622  if(is_boundary(face_handle(*hehf_it))) {
623  return true;
624  }
625  }
626  return false;
627  }
628 
629  bool is_boundary(const VertexHandle& _vertexHandle) const {
630  if(!v_bottom_up_) {
631  std::cerr << "Error: Function is_boundary() needs bottom-up incidences for vertices!" << std::endl;
632  return false;
633  }
634  for(VertexOHalfEdgeIter voh_it = voh_iter(_vertexHandle); voh_it.valid(); ++voh_it) {
635  if(is_boundary(*voh_it)) return true;
636  }
637  return false;
638  }
639 
640  unsigned int n_vertices_in_cell(const CellHandle& _ch) const {
641 
642  std::set<VertexHandle> vertices;
643  std::vector<HalfFaceHandle> hfs = cell(_ch).halffaces();
644  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin();
645  hf_it != hfs.end(); ++hf_it) {
646  std::vector<HalfEdgeHandle> hes = halfface(*hf_it).halfedges();
647  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin();
648  he_it != hes.end(); ++he_it) {
649  vertices.insert(halfedge(*he_it).to_vertex());
650  }
651  }
652  return vertices.size();
653  }
654 
655  //=========================================================================
656 
657  /*
658  * Non-virtual functions
659  */
660 
661  const Edge opposite_halfedge(const Edge& _edge) const {
662  return Edge(_edge.to_vertex(), _edge.from_vertex());
663  }
664 
665  const Face opposite_halfface(const Face& _face) const {
666 
667  std::vector<HalfEdgeHandle> opp_halfedges;
668  for(std::vector<HalfEdgeHandle>::const_iterator it = _face.halfedges().begin(); it
669  != _face.halfedges().end(); ++it) {
670  opp_halfedges.insert(opp_halfedges.begin(), opposite_halfedge_handle(*it));
671  }
672 
673  return Face(opp_halfedges);
674  }
675 
676  /*
677  * Static functions
678  */
679 
681  static inline HalfEdgeHandle halfedge_handle(const EdgeHandle& _h, const unsigned char _subIdx) {
682  // Is handle in range?
683  if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfEdgeHandle;
684  return HalfEdgeHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
685  }
686 
688  static inline HalfFaceHandle halfface_handle(const FaceHandle& _h, const unsigned char _subIdx) {
689  // Is handle in range?
690  if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfFaceHandle;
691  return HalfFaceHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
692  }
693 
695  static inline EdgeHandle edge_handle(const HalfEdgeHandle& _h) {
696  // Is handle in range?
697  if(_h.idx() < 0) return InvalidEdgeHandle;
698  return EdgeHandle((int)(_h.idx() / 2));
699  }
700 
701  static inline FaceHandle face_handle(const HalfFaceHandle& _h) {
702  // Is handle in range?
703  if(_h.idx() < 0) return InvalidFaceHandle;
704  return FaceHandle((int)(_h.idx() / 2));
705  }
706 
707  static inline HalfEdgeHandle opposite_halfedge_handle(const HalfEdgeHandle& _h) {
708  // Is handle in range?
709  if(_h.idx() < 0) return InvalidHalfEdgeHandle;
710 
711  // Is handle even?
712  if(_h.idx() % 2 == 0) {
713  return HalfEdgeHandle(_h.idx() + 1);
714  }
715  return HalfEdgeHandle(_h.idx() - 1);
716  }
717 
718  static inline HalfFaceHandle opposite_halfface_handle(const HalfFaceHandle& _h) {
719  // Is handle in range?
720  if(_h.idx() < 0) return InvalidHalfFaceHandle;
721 
722  // Is handle even?
723  if(_h.idx() % 2 == 0) {
724  return HalfFaceHandle(_h.idx() + 1);
725  }
726  return HalfFaceHandle(_h.idx() - 1);
727  }
728 
729 protected:
730 
731  // List of edges
732  std::vector<Edge> edges_;
733 
734  // List of faces
735  std::vector<Face> faces_;
736 
737  // List of cells
738  std::vector<Cell> cells_;
739 };
740 
741 }
742 
743 #endif /* TOPOLOGYKERNEL_HH_ */