44 #ifndef OPENMESH_CIRCULATORS_HH
45 #define OPENMESH_CIRCULATORS_HH
56 #include <OpenMesh/Core/System/config.h>
66 template<
class Mesh,
class CenterEntityHandle,
bool CW>
77 heh = mesh->cw_rotated_halfedge_handle(heh);
78 if (heh == start) ++lap_counter;
81 if (heh == start) --lap_counter;
82 heh = mesh->ccw_rotated_halfedge_handle(heh);
90 heh = mesh->next_halfedge_handle(heh);
91 if (heh == start) ++lap_counter;
94 if (heh == start) --lap_counter;
95 heh = mesh->prev_halfedge_handle(heh);
106 heh = mesh->ccw_rotated_halfedge_handle(heh);
107 if (heh == start) ++lap_counter;
110 if (heh == start) --lap_counter;
111 heh = mesh->cw_rotated_halfedge_handle(heh);
119 heh = mesh->prev_halfedge_handle(heh);
120 if (heh == start) ++lap_counter;
123 if (heh == start) --lap_counter;
124 heh = mesh->next_halfedge_handle(heh);
129 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
139 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
147 return mesh->face_handle(heh).is_valid();
151 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
bool CW = true>
155 return ( heh.is_valid() && (lap_counter == 0 ) );
166 template<
class Mesh,
class CenterEntityHandle,
bool CW>
172 return ( heh.is_valid() && (lap_counter == 0));
175 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
176 increment(mesh, heh, start, lap_counter);
181 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
186 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
193 typedef const Mesh* mesh_ptr;
194 typedef const Mesh& mesh_ref;
200 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
203 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
206 return mesh_->face_handle(heh_);
210 return mesh_->face_handle(toOppositeHalfedgeHandle());
214 return mesh_->edge_handle(heh_);
222 return mesh_->opposite_halfedge_handle(heh_);
226 return mesh_->to_vertex_handle(heh_);
233 lap_counter_ = rhs.lap_counter_;
238 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
242 return !operator==(rhs);
251 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
255 typedef std::ptrdiff_t difference_type;
256 typedef ValueHandle value_type;
257 typedef const value_type& reference;
258 typedef const value_type* pointer;
259 typedef std::bidirectional_iterator_tag iterator_category;
270 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
275 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
285 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
290 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
315 assert(this->heh_.is_valid());
316 value_type res = (
self->*Handle2Value)();
317 assert(res.is_valid());
320 return (self->*Handle2Value)();
333 pointer_deref_value = **
this;
334 return &pointer_deref_value;
342 bool operator==(
const GenericCirculatorT &rhs)
const {
343 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
346 bool operator!=(
const GenericCirculatorT &rhs)
const {
347 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
350 bool is_valid()
const {
351 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
354 template<
typename STREAM>
355 friend STREAM &
operator<< (STREAM &s,
const GenericCirculatorT &
self) {
356 return s <<
self.mesh_ <<
", " <<
self.start_.idx() <<
", " <<
self.heh_.idx() <<
", " <<
self.lap_counter_;
360 mutable value_type pointer_deref_value;
384 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
388 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
399 template<
class Mesh,
class CenterEntityHandle>
405 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
408 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
409 increment(mesh, heh, start, lap_counter);
414 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
419 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
423 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
427 typedef std::ptrdiff_t difference_type;
428 typedef ValueHandle value_type;
429 typedef const value_type& reference;
430 typedef const value_type* pointer;
431 typedef std::bidirectional_iterator_tag iterator_category;
442 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
447 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
453 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
456 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
457 #define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
458 valid when iterating below the start and will visit the first entity\
459 twice before getting invalid. Furthermore it gets valid again, if you\
460 increment at the end.\
461 When you are sure that you don't iterate below the start anywhere in\
462 your code or rely on this behaviour, you can disable this warning by\
463 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
465 To be save, you can use the CW/CCW circulator definitions, which behave\
466 the same as the original ones, without the previously mentioned issues."
468 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
469 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
472 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
485 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
486 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
487 #undef DECREMENT_DEPRECATED_WARNINGS_TEXT
488 #endif //NO_DECREMENT_DEPRECATED_WARNINGS
501 assert(this->heh_.is_valid());
502 value_type res = (
self->*Handle2Value)();
503 assert(res.is_valid());
506 return (self->*Handle2Value)();
519 pointer_deref_value = **
this;
520 return &pointer_deref_value;
528 bool operator==(
const GenericCirculatorT_DEPRECATED &rhs)
const {
529 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
532 bool operator!=(
const GenericCirculatorT_DEPRECATED &rhs)
const {
533 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
536 bool is_valid()
const {
537 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
540 OM_DEPRECATED(
"current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
550 OM_DEPRECATED(
"Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
556 operator
bool()
const {
565 OM_DEPRECATED(
"This function clutters your code. Use dereferencing operators -> and * instead.")
566 value_type handle()
const {
576 OM_DEPRECATED(
"Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
577 operator value_type()
const {
581 template<
typename STREAM>
583 return s <<
self.mesh_ <<
", " <<
self.start_.idx() <<
", " <<
self.heh_.idx() <<
", " <<
self.lap_counter_;
587 mutable value_type pointer_deref_value;