49#ifndef OPENMESH_CIRCULATORS_HH
50#define OPENMESH_CIRCULATORS_HH
61#include <OpenMesh/Core/System/config.h>
71template<
class Mesh,
class CenterEntityHandle,
bool CW>
74 static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter);
75 static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter);
81 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
82 heh = mesh->cw_rotated_halfedge_handle(heh);
83 if (heh == start) ++lap_counter;
85 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
86 if (heh == start) --lap_counter;
87 heh = mesh->ccw_rotated_halfedge_handle(heh);
94 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
95 heh = mesh->next_halfedge_handle(heh);
96 if (heh == start) ++lap_counter;
98 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
99 if (heh == start) --lap_counter;
100 heh = mesh->prev_halfedge_handle(heh);
110 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
111 heh = mesh->ccw_rotated_halfedge_handle(heh);
112 if (heh == start) ++lap_counter;
114 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
115 if (heh == start) --lap_counter;
116 heh = mesh->cw_rotated_halfedge_handle(heh);
123 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
124 heh = mesh->prev_halfedge_handle(heh);
125 if (heh == start) ++lap_counter;
127 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
128 if (heh == start) --lap_counter;
129 heh = mesh->next_halfedge_handle(heh);
134template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
143 inline static bool isDereferenciable(
const Mesh *mesh,
const typename Mesh::HalfedgeHandle &heh) {
144 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).
is_valid();
151 inline static bool isDereferenciable(
const Mesh *mesh,
const typename Mesh::HalfedgeHandle &heh) {
152 return mesh->face_handle(heh).
is_valid();
156template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
bool CW = true>
159 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const int lap_counter) {
160 return ( heh.is_valid() && (lap_counter == 0 ) );
162 inline static void init(
const Mesh*,
typename Mesh::HalfedgeHandle&,
typename Mesh::HalfedgeHandle&,
int&) {};
163 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
164 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
166 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
167 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
171template<
class Mesh,
class CenterEntityHandle,
bool CW>
176 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const int lap_counter) {
177 return ( heh.is_valid() && (lap_counter == 0));
179 inline static void init(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
180 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
181 increment(mesh, heh, start, lap_counter);
183 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
185 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
186 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
188 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
190 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
191 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
196class GenericCirculatorBaseT {
198 typedef const Mesh* mesh_ptr;
199 typedef const Mesh& mesh_ref;
202 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
204 GenericCirculatorBaseT(mesh_ref mesh,
HalfedgeHandle heh,
bool end =
false) :
205 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(
static_cast<int>(end && heh.is_valid())) {}
207 GenericCirculatorBaseT(
const GenericCirculatorBaseT &rhs) :
208 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
210 inline typename Mesh::FaceHandle toFaceHandle()
const {
211 return mesh_->face_handle(heh_);
214 inline typename Mesh::FaceHandle toOppositeFaceHandle()
const {
215 return mesh_->face_handle(toOppositeHalfedgeHandle());
218 inline typename Mesh::EdgeHandle toEdgeHandle()
const {
219 return mesh_->edge_handle(heh_);
222 inline typename Mesh::HalfedgeHandle toHalfedgeHandle()
const {
226 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle()
const {
227 return mesh_->opposite_halfedge_handle(heh_);
230 inline typename Mesh::VertexHandle toVertexHandle()
const {
231 return mesh_->to_vertex_handle(heh_);
234 inline GenericCirculatorBaseT &operator=(
const GenericCirculatorBaseT &rhs) {
238 lap_counter_ = rhs.lap_counter_;
242 inline bool operator==(
const GenericCirculatorBaseT &rhs)
const {
243 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
246 inline bool operator!=(
const GenericCirculatorBaseT &rhs)
const {
247 return !operator==(rhs);
252 typename Mesh::HalfedgeHandle start_, heh_;
256template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
258class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
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;
266 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
267 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
271 GenericCirculatorT() {}
272 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start,
bool end =
false) :
273 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
275 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
277 GenericCirculatorT(mesh_ref mesh,
HalfedgeHandle heh,
bool end =
false) :
278 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
280 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
282 GenericCirculatorT(
const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
284 friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
285 explicit GenericCirculatorT(
const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
286 :GenericCirculatorBaseT<Mesh>(rhs){}
288 GenericCirculatorT& operator++() {
290 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
293 GenericCirculatorT& operator--() {
295 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
302 GenericCirculatorT cpy(*
this);
310 GenericCirculatorT cpy(*
this);
318 const GenericCirculatorBaseT<Mesh>* self =
this;
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;
343 GenericCirculatorBaseT<Mesh>::operator=(rhs);
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>
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>
392 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
393 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
395 inline static void init(
const Mesh*,
typename Mesh::HalfedgeHandle&,
typename Mesh::HalfedgeHandle&,
int&) {};
396 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
397 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
399 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
400 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
404template<
class Mesh,
class CenterEntityHandle>
409 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
410 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
412 inline static void init(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
413 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
414 increment(mesh, heh, start, lap_counter);
416 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
418 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
419 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
421 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
423 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
424 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
428template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
430class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
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;
438 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
439 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
443 GenericCirculatorT_DEPRECATED() {}
444 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start,
bool end =
false) :
445 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
447 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
449 GenericCirculatorT_DEPRECATED(mesh_ref mesh,
HalfedgeHandle heh,
bool end =
false) :
450 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
452 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
454 GenericCirculatorT_DEPRECATED(
const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
456 GenericCirculatorT_DEPRECATED& operator++() {
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 )
475 GenericCirculatorT_DEPRECATED& operator--() {
477 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
484 GenericCirculatorT_DEPRECATED cpy(*
this);
490#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
491 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
492#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
496 GenericCirculatorT_DEPRECATED cpy(*
this);
504 const GenericCirculatorBaseT<Mesh>* self =
this;
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;
529 GenericCirculatorBaseT<Mesh>::operator=(rhs);
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.")
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_;
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
Contains all mesh iterators and circulators.
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
const HalfedgeHandle & current_halfedge_handle() const
Definition CirculatorsT.hh:551
value_type handle() const
Definition CirculatorsT.hh:571
pointer operator->() const
Pointer dereferentiation.
Definition CirculatorsT.hh:523
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition CirculatorsT.hh:482
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Definition Handles.hh:77
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