49#ifndef OPENMESH_CIRCULATORS_HH
50#define OPENMESH_CIRCULATORS_HH
61#include <OpenMesh/Core/System/config.h>
71template<
class Mesh,
class CenterEntityHandle,
bool CW>
82 heh = mesh->cw_rotated_halfedge_handle(heh);
83 if (heh == start) ++lap_counter;
86 if (heh == start) --lap_counter;
87 heh = mesh->ccw_rotated_halfedge_handle(heh);
95 heh = mesh->next_halfedge_handle(heh);
96 if (heh == start) ++lap_counter;
99 if (heh == start) --lap_counter;
100 heh = mesh->prev_halfedge_handle(heh);
111 heh = mesh->ccw_rotated_halfedge_handle(heh);
112 if (heh == start) ++lap_counter;
115 if (heh == start) --lap_counter;
116 heh = mesh->cw_rotated_halfedge_handle(heh);
124 heh = mesh->prev_halfedge_handle(heh);
125 if (heh == start) ++lap_counter;
128 if (heh == start) --lap_counter;
129 heh = mesh->next_halfedge_handle(heh);
134template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
144 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
152 return mesh->face_handle(heh).is_valid();
156template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
bool CW = true>
160 return ( heh.is_valid() && (lap_counter == 0 ) );
171template<
class Mesh,
class CenterEntityHandle,
bool CW>
177 return ( heh.is_valid() && (lap_counter == 0));
180 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
181 increment(mesh, heh, start, lap_counter);
186 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
191 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
205 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(
static_cast<int>(end && heh.is_valid())) {}
208 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
211 return mesh_->face_handle(heh_);
215 return mesh_->face_handle(toOppositeHalfedgeHandle());
219 return mesh_->edge_handle(heh_);
227 return mesh_->opposite_halfedge_handle(heh_);
231 return mesh_->to_vertex_handle(heh_);
238 lap_counter_ = rhs.lap_counter_;
243 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
247 return !operator==(rhs);
256template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
260 typedef std::ptrdiff_t difference_type;
261 typedef ValueHandle value_type;
262 typedef const value_type& reference;
263 typedef const value_type* pointer;
264 typedef std::bidirectional_iterator_tag iterator_category;
275 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
280 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
290 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
295 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
320 assert(this->heh_.is_valid());
321 value_type res = (self->*Handle2Value)();
322 assert(res.is_valid());
325 return (self->*Handle2Value)();
338 pointer_deref_value = **
this;
339 return &pointer_deref_value;
347 bool operator==(
const GenericCirculatorT &rhs)
const {
348 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
351 bool operator!=(
const GenericCirculatorT &rhs)
const {
352 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
355 bool is_valid()
const {
356 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
359 template<
typename STREAM>
360 friend STREAM &
operator<< (STREAM &s,
const GenericCirculatorT &self) {
361 return s << self.mesh_ <<
", " << self.start_.idx() <<
", " << self.heh_.idx() <<
", " << self.lap_counter_;
365 mutable value_type pointer_deref_value;
389template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
393 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
404template<
class Mesh,
class CenterEntityHandle>
410 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
413 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
414 increment(mesh, heh, start, lap_counter);
419 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
424 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
428template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
432 typedef std::ptrdiff_t difference_type;
433 typedef ValueHandle value_type;
434 typedef const value_type& reference;
435 typedef const value_type* pointer;
436 typedef std::bidirectional_iterator_tag iterator_category;
447 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
452 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
458 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
461#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
462#define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
463 valid when iterating below the start and will visit the first entity\
464 twice before getting invalid. Furthermore it gets valid again, if you\
465 increment at the end.\
466 When you are sure that you don't iterate below the start anywhere in\
467 your code or rely on this behaviour, you can disable this warning by\
468 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
470 To be save, you can use the CW/CCW circulator definitions, which behave\
471 the same as the original ones, without the previously mentioned issues."
473 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
477 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
490#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
491 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
492#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
506 assert(this->heh_.is_valid());
507 value_type res = (self->*Handle2Value)();
508 assert(res.is_valid());
511 return (self->*Handle2Value)();
524 pointer_deref_value = **
this;
525 return &pointer_deref_value;
533 bool operator==(
const GenericCirculatorT_DEPRECATED &rhs)
const {
534 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
537 bool operator!=(
const GenericCirculatorT_DEPRECATED &rhs)
const {
538 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
541 bool is_valid()
const {
542 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
545 DEPRECATED(
"current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
555 DEPRECATED(
"Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
561 operator
bool()
const {
570 DEPRECATED(
"This function clutters your code. Use dereferencing operators -> and * instead.")
571 value_type handle()
const {
581 DEPRECATED(
"Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
582 operator value_type()
const {
586 template<
typename STREAM>
588 return s << self.mesh_ <<
", " << self.start_.idx() <<
", " << self.heh_.idx() <<
", " << self.lap_counter_;
592 mutable value_type pointer_deref_value;
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
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: CirculatorsT.hh:72
Definition: CirculatorsT.hh:135
Definition: CirculatorsT.hh:157
Definition: CirculatorsT.hh:196
Definition: CirculatorsT.hh:258
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:308
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:316
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:337
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:300
Definition: CirculatorsT.hh:390
Definition: CirculatorsT.hh:430
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:494
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:502
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:523
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition: CirculatorsT.hh:482
Handle for a vertex entity.
Definition: Handles.hh:126
Handle for a halfedge entity.
Definition: Handles.hh:133
Handle for a face entity.
Definition: Handles.hh:147
Polygonal mesh based on the ArrayKernel.
Definition: PolyMesh_ArrayKernelT.hh:100
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
Kernel::EdgeHandle EdgeHandle
Scalar type.
Definition: PolyMeshT.hh:141
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:142
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:140