Developer Documentation
CirculatorsT.hh
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 #pragma once
44 
45 //=============================================================================
46 //
47 // Vertex and Face circulators for PolyMesh/TriMesh
48 //
49 //=============================================================================
50 
51 
52 
53 //== INCLUDES =================================================================
54 
56 #include <OpenMesh/Core/Mesh/SmartHandles.hh>
57 #include <cassert>
58 #include <cstddef>
59 #include <iterator>
60 
61 //== NAMESPACES ===============================================================
62 
63 namespace OpenMesh {
64 namespace Iterators {
65 
66 template<class Mesh, class CenterEntityHandle, bool CW>
68  public:
69  static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
70  static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
71 };
72 
73 template<class Mesh>
75  public:
76  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
77  heh = mesh->cw_rotated_halfedge_handle(heh);
78  if (heh == start) ++lap_counter;
79  }
80  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
81  if (heh == start) --lap_counter;
82  heh = mesh->ccw_rotated_halfedge_handle(heh);
83  }
84 };
85 
86 template<class Mesh>
88  public:
89  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
90  heh = mesh->next_halfedge_handle(heh);
91  if (heh == start) ++lap_counter;
92  }
93  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
94  if (heh == start) --lap_counter;
95  heh = mesh->prev_halfedge_handle(heh);
96  }
97 };
98 
100 // CCW
101 
102 template<class Mesh>
104  public:
105  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
106  heh = mesh->ccw_rotated_halfedge_handle(heh);
107  if (heh == start) ++lap_counter;
108  }
109  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
110  if (heh == start) --lap_counter;
111  heh = mesh->cw_rotated_halfedge_handle(heh);
112  }
113 };
114 
115 template<class Mesh>
117  public:
118  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
119  heh = mesh->prev_halfedge_handle(heh);
120  if (heh == start) ++lap_counter;
121  }
122  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
123  if (heh == start) --lap_counter;
124  heh = mesh->next_halfedge_handle(heh);
125  }
126 };
128 
129 template<class Mesh, class CenterEntityHandle, class ValueHandle>
131  public:
132  //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
133 };
134 
135 template<class Mesh>
136 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
137  public:
138  inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
139  return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
140  }
141 };
142 
143 template<class Mesh>
144 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
145  public:
146  inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
147  return mesh->face_handle(heh).is_valid();
148  }
149 };
150 
151 template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
153  public:
154  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
155  return ( heh.is_valid() && (lap_counter == 0 ) );
156  }
157  inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
158  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
160  }
161  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
163  }
164 };
165 
166 template<class Mesh, class CenterEntityHandle, bool CW>
167 class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
168  public:
170 
171  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
172  return ( heh.is_valid() && (lap_counter == 0));
173  }
174  inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
175  if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
176  increment(mesh, heh, start, lap_counter);
177  };
178  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
179  do {
181  } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
182  }
183  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
184  do {
186  } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
187  }
188 };
189 
190 template<class Mesh>
192  public:
193  typedef const Mesh* mesh_ptr;
194  typedef const Mesh& mesh_ref;
195 
196  public:
197  GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
198 
199  GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
200  mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
201 
203  mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
204 
205  inline typename Mesh::FaceHandle toFaceHandle() const {
206  return mesh_->face_handle(heh_);
207  }
208 
209  inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
210  return mesh_->face_handle(toOppositeHalfedgeHandle());
211  }
212 
213  inline typename Mesh::EdgeHandle toEdgeHandle() const {
214  return mesh_->edge_handle(heh_);
215  }
216 
217  inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
218  return heh_;
219  }
220 
221  inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
222  return mesh_->opposite_halfedge_handle(heh_);
223  }
224 
225  inline typename Mesh::VertexHandle toVertexHandle() const {
226  return mesh_->to_vertex_handle(heh_);
227  }
228 
229  inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
230  mesh_ = rhs.mesh_;
231  start_ = rhs.start_;
232  heh_ = rhs.heh_;
233  lap_counter_ = rhs.lap_counter_;
234  return *this;
235  }
236 
237  inline bool operator==(const GenericCirculatorBaseT &rhs) const {
238  return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
239  }
240 
241  inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
242  return !operator==(rhs);
243  }
244 
245  protected:
246  mesh_ptr mesh_;
247  typename Mesh::HalfedgeHandle start_, heh_;
248  int lap_counter_;
249 };
250 
251 //template<class Mesh, class CenterEntityHandle, class ValueHandle,
252 // ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
253 template <typename GenericCirculatorT_TraitsT, bool CW = true>
254 class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
255  public:
256  using Mesh = typename GenericCirculatorT_TraitsT::Mesh;
257  using value_type = typename GenericCirculatorT_TraitsT::ValueHandle;
258  using CenterEntityHandle = typename GenericCirculatorT_TraitsT::CenterEntityHandle;
259 
260  using smart_value_type = decltype(make_smart(std::declval<value_type>(), std::declval<Mesh>()));
261 
262  typedef std::ptrdiff_t difference_type;
263  typedef const value_type& reference;
264  typedef const smart_value_type* pointer;
265  typedef std::bidirectional_iterator_tag iterator_category;
266 
270 
271  public:
272  GenericCirculatorT() {}
273  GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
274  GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
275 
276  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
277  }
278  GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
279  GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
280 
281  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
282  }
284 
285  friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
288 
289  GenericCirculatorT& operator++() {
290  assert(this->mesh_);
291  GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
292  return *this;
293  }
294  GenericCirculatorT& operator--() {
295  assert(this->mesh_);
296  GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
297  return *this;
298  }
299 
301  GenericCirculatorT operator++(int) {
302  assert(this->mesh_);
303  GenericCirculatorT cpy(*this);
304  ++(*this);
305  return cpy;
306  }
307 
309  GenericCirculatorT operator--(int) {
310  assert(this->mesh_);
311  GenericCirculatorT cpy(*this);
312  --(*this);
313  return cpy;
314  }
315 
317  smart_value_type operator*() const {
318 #ifndef NDEBUG
319  assert(this->heh_.is_valid());
320  value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
321  assert(res.is_valid());
322  return make_smart(res, this->mesh_);
323 #else
324  return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
325 #endif
326  }
327 
336  pointer operator->() const {
337  pointer_deref_value = **this;
338  return &pointer_deref_value;
339  }
340 
341  GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
343  return *this;
344  };
345 
346  bool operator==(const GenericCirculatorT &rhs) const {
348  }
349 
350  bool operator!=(const GenericCirculatorT &rhs) const {
352  }
353 
354  bool is_valid() const {
355  return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
356  }
357 
358  template<typename STREAM>
359  friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
360  return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
361  }
362 
363  private:
364  mutable smart_value_type pointer_deref_value;
365 };
366 
371 // OLD CIRCULATORS
372 // deprecated circulators, will be removed soon
373 // if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
374 //
375 // OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
376 // OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
377 // OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
378 // OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
379 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
380 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
381 // OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
382 // OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
383 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
384 // OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
385 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
386 //
387 
388 template<class Mesh, class CenterEntityHandle, class ValueHandle>
390  public:
391  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
392  return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
393  }
394  inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
395  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
397  }
398  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
400  }
401 };
402 
403 template<class Mesh, class CenterEntityHandle>
404 class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
405  public:
407 
408  inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
409  return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
410  }
411  inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
412  if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
413  increment(mesh, heh, start, lap_counter);
414  };
415  inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
416  do {
418  } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
419  }
420  inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
421  do {
423  } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
424  }
425 };
426 
427 template <typename GenericCirculatorT_DEPRECATED_TraitsT>
428 class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
429  public:
430  using Mesh = typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh;
431  using CenterEntityHandle = typename GenericCirculatorT_DEPRECATED_TraitsT::CenterEntityHandle;
432  using value_type = typename GenericCirculatorT_DEPRECATED_TraitsT::ValueHandle;
433  using smart_value_type = decltype (make_smart(std::declval<value_type>(), std::declval<Mesh>()));
434 
435  typedef std::ptrdiff_t difference_type;
436  typedef const value_type& reference;
437  typedef const smart_value_type* pointer;
438  typedef std::bidirectional_iterator_tag iterator_category;
439 
443 
444  public:
446  GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
447  GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
448 
449  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
450  }
451  GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
452  GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
453 
454  GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
455  }
457 
458  GenericCirculatorT_DEPRECATED& operator++() {
459  assert(this->mesh_);
460  GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
461  return *this;
462  }
463 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
464 #define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
465  valid when iterating below the start and will visit the first entity\
466  twice before getting invalid. Furthermore it gets valid again, if you\
467  increment at the end.\
468  When you are sure that you don't iterate below the start anywhere in\
469  your code or rely on this behaviour, you can disable this warning by\
470  setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
471  cmake flags).\
472  To be save, you can use the CW/CCW circulator definitions, which behave\
473  the same as the original ones, without the previously mentioned issues."
474 
475  OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
476 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
477  GenericCirculatorT_DEPRECATED& operator--() {
478  assert(this->mesh_);
479  GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
480  return *this;
481  }
482 
485  assert(this->mesh_);
487  ++(*this);
488  return cpy;
489  }
490 
492 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
493  OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
494 #undef DECREMENT_DEPRECATED_WARNINGS_TEXT
495 #endif //NO_DECREMENT_DEPRECATED_WARNINGS
497  assert(this->mesh_);
499  --(*this);
500  return cpy;
501  }
502 
504  smart_value_type operator*() const {
505 #ifndef NDEBUG
506  assert(this->heh_.is_valid());
507  value_type res = (GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_));
508  assert(res.is_valid());
509  return make_smart(res, this->mesh_);
510 #else
511  return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
512 #endif
513  }
514 
523  pointer operator->() const {
524  pointer_deref_value = **this;
525  return &pointer_deref_value;
526  }
527 
530  return *this;
531  };
532 
533  bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
535  }
536 
537  bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
539  }
540 
541  bool is_valid() const {
542  return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
543  }
544 
545  OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
551  const HalfedgeHandle &current_halfedge_handle() const {
552  return this->heh_;
553  }
554 
555  OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
561  operator bool() const {
562  return is_valid();
563  }
564 
570  OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
571  smart_value_type handle() const {
572  return **this;
573  }
574 
581  OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
582  operator value_type() const {
583  return **this;
584  }
585 
586  template<typename STREAM>
587  friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
588  return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
589  }
590 
591  private:
592  mutable smart_value_type pointer_deref_value;
593 };
594 
595 } // namespace Iterators
596 } // namespace OpenMesh
597 
Handle for a face entity.
Definition: Handles.hh:141
auto operator<<(std::ostream &os, const VectorT< Scalar, DIM > &_vec) -> typename std::enable_if< sizeof(decltype(os<< _vec[0])) >=0
output a vector by printing its space-separated compontens
Definition: VectorT.hh:647
Handle for a halfedge entity.
Definition: Handles.hh:127
pointer operator->() const
Pointer dereferentiation.
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
smart_value_type operator*() const
Standard dereferencing operator.
Handle for a vertex entity.
Definition: Handles.hh:120
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
GenericCirculatorT operator++(int)
Post-increment.
smart_value_type operator*() const
Standard dereferencing operator.
pointer operator->() const
Pointer dereferentiation.
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
GenericCirculatorT operator--(int)
Post-decrement.