OpenMesh
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CirculatorsT.hh
1 /*===========================================================================*\
2  * *
3  * OpenMesh *
4  * Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen *
5  * www.openmesh.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenMesh. *
9  * *
10  * OpenMesh 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  * OpenMesh 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 OpenMesh. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision: 990 $ *
38  * $Date: 2014-02-05 10:01:07 +0100 (Mi, 05 Feb 2014) $ *
39  * *
40 \*===========================================================================*/
41 
42 #ifndef OPENMESH_CIRCULATORS_HH
43 #define OPENMESH_CIRCULATORS_HH
44 //=============================================================================
45 //
46 // Vertex and Face circulators for PolyMesh/TriMesh
47 //
48 //=============================================================================
49 
50 
51 
52 //== INCLUDES =================================================================
53 
54 #include <OpenMesh/Core/System/config.h>
55 #include <cassert>
56 #include <cstddef>
57 #include <iterator>
58 
59 //== NAMESPACES ===============================================================
60 
61 namespace OpenMesh {
62 namespace Iterators {
63 
64 template<class Mesh, class CenterEntityHandle>
66  public:
67  static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
68  static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
69 };
70 
71 template<class Mesh>
72 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle> {
73  public:
74  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
75  heh = mesh->cw_rotated_halfedge_handle(heh);
76  if (heh == start) ++lap_counter;
77  }
78  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
79  if (heh == start) --lap_counter;
80  heh = mesh->ccw_rotated_halfedge_handle(heh);
81  }
82 };
83 
84 template<class Mesh>
85 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle> {
86  public:
87  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
88  heh = mesh->next_halfedge_handle(heh);
89  if (heh == start) ++lap_counter;
90  }
91  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
92  if (heh == start) --lap_counter;
93  heh = mesh->prev_halfedge_handle(heh);
94  }
95 };
96 
97 template<class Mesh, class CenterEntityHandle, class ValueHandle>
99  public:
100  //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
101 };
102 
103 template<class Mesh>
104 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
105  public:
106  inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
107  return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
108  }
109 };
110 
111 template<class Mesh>
112 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
113  public:
114  inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
115  return mesh->face_handle(heh).is_valid();
116  }
117 };
118 
119 template<class Mesh, class CenterEntityHandle, class ValueHandle>
121  public:
122  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) {
123  return heh.is_valid() && ((start != heh) || (lap_counter == 0));
124  }
125  inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
126  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
128  }
129  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
131  }
132 };
133 
134 template<class Mesh, class CenterEntityHandle>
135 class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
136  public:
138 
139  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter) {
140  return heh.is_valid() && ((start != heh) || (lap_counter == 0));
141  }
142  inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
143  if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0)
144  increment(mesh, heh, start, lap_counter);
145  };
146  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
147  do {
149  } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
150  }
151  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
152  do {
154  } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
155  }
156 };
157 
158 template<class Mesh>
160  public:
161  typedef const Mesh* mesh_ptr;
162  typedef const Mesh& mesh_ref;
163 
164  public:
165  GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
166 
167  GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
168  mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end)) {}
169 
171  mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
172 
173  inline typename Mesh::FaceHandle toFaceHandle() const {
174  return mesh_->face_handle(heh_);
175  }
176 
177  inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
178  return mesh_->face_handle(toOppositeHalfedgeHandle());
179  }
180 
181  inline typename Mesh::EdgeHandle toEdgeHandle() const {
182  return mesh_->edge_handle(heh_);
183  }
184 
185  inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
186  return heh_;
187  }
188 
189  inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
190  return mesh_->opposite_halfedge_handle(heh_);
191  }
192 
193  inline typename Mesh::VertexHandle toVertexHandle() const {
194  return mesh_->to_vertex_handle(heh_);
195  }
196 
197  inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
198  mesh_ = rhs.mesh_;
199  start_ = rhs.start_;
200  heh_ = rhs.heh_;
201  lap_counter_ = rhs.lap_counter_;
202  return *this;
203  }
204 
205  inline bool operator==(const GenericCirculatorBaseT &rhs) const {
206  return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
207  }
208 
209  inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
210  return !operator==(rhs);
211  }
212 
213  protected:
214  mesh_ptr mesh_;
215  typename Mesh::HalfedgeHandle start_, heh_;
216  int lap_counter_;
217 };
218 
219 template<class Mesh, class CenterEntityHandle, class ValueHandle,
220  ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
222  public:
223  typedef std::ptrdiff_t difference_type;
224  typedef ValueHandle value_type;
225  typedef const value_type& reference;
226  typedef const value_type* pointer;
227  typedef std::bidirectional_iterator_tag iterator_category;
228 
229  typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
230  typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
232 
233  public:
234  GenericCirculatorT() {}
235  GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
236  GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
237 
238  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
239  }
240  GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
241  GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
242 
243  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
244  }
246 
247  GenericCirculatorT& operator++() {
248  assert(this->mesh_);
249  GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
250  return *this;
251  }
252  GenericCirculatorT& operator--() {
253  assert(this->mesh_);
254  GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
255  return *this;
256  }
257 
260  assert(this->mesh_);
261  GenericCirculatorT cpy(*this);
262  ++(*this);
263  return cpy;
264  }
265 
268  assert(this->mesh_);
269  GenericCirculatorT cpy(*this);
270  --(*this);
271  return cpy;
272  }
273 
275  value_type operator*() const {
276 #ifndef NDEBUG
277  assert(this->heh_.is_valid());
278  value_type res = (this->*Handle2Value)();
279  assert(res.is_valid());
280  return res;
281 #else
282  return (this->*Handle2Value)();
283 #endif
284  }
285 
294  pointer operator->() const {
295  pointer_deref_value = **this;
296  return &pointer_deref_value;
297  }
298 
299  GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
301  return *this;
302  };
303 
304  bool operator==(const GenericCirculatorT &rhs) const {
305  return GenericCirculatorBaseT<Mesh>::operator==(rhs);
306  }
307 
308  bool operator!=(const GenericCirculatorT &rhs) const {
309  return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
310  }
311 
312  bool is_valid() const {
313  return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->start_, this->lap_counter_);
314  }
315 
316  DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
322  const HalfedgeHandle &current_halfedge_handle() const {
323  return this->heh_;
324  }
325 
326  DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
332  operator bool() const {
333  return is_valid();
334  }
335 
341  DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
342  value_type handle() const {
343  return **this;
344  }
345 
352  DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
353  operator value_type() const {
354  return **this;
355  }
356 
357  template<typename STREAM>
358  friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
359  return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
360  }
361 
362  private:
363  mutable value_type pointer_deref_value;
364 };
365 
366 } // namespace Iterators
367 } // namespace OpenMesh
368 
369 #endif
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Definition: Handles.hh:70
Definition: CirculatorsT.hh:221
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:56
Handle for a halfedge entity.
Definition: Handles.hh:121
Definition: CirculatorsT.hh:159
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:294
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:259
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:267
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:275
Handle for a face entity.
Definition: Handles.hh:135
std::ostream & operator<<(std::ostream &_os, const BaseHandle &_hnd)
Write handle _hnd to stream _os.
Definition: Handles.hh:104
Handle for a vertex entity.
Definition: Handles.hh:114

acg pic Project OpenMesh, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .