49 #ifndef OPENMESH_CIRCULATORS_HH
50 #define OPENMESH_CIRCULATORS_HH
71 template<
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);
134 template<
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();
156 template<
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) {
166 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
171 template<
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) {
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) {
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_) {}
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_);
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);
252 typename Mesh::HalfedgeHandle start_, heh_;
256 template<
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_);
318 assert(this->heh_.is_valid());
319 value_type res = (this->*Handle2Value)();
320 assert(res.is_valid());
323 return (this->*Handle2Value)();
336 pointer_deref_value = **
this;
337 return &pointer_deref_value;
345 bool operator==(
const GenericCirculatorT &rhs)
const {
346 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
349 bool operator!=(
const GenericCirculatorT &rhs)
const {
350 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
353 bool is_valid()
const {
354 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
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_;
363 mutable value_type pointer_deref_value;
387 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
390 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
391 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
393 inline static void init(
const Mesh*,
typename Mesh::HalfedgeHandle&,
typename Mesh::HalfedgeHandle&,
int&) {};
394 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
397 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
402 template<
class Mesh,
class CenterEntityHandle>
407 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
408 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
410 inline static void init(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
411 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
412 increment(mesh, heh, start, lap_counter);
414 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
417 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
419 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
422 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
426 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
430 typedef std::ptrdiff_t difference_type;
431 typedef ValueHandle value_type;
432 typedef const value_type& reference;
433 typedef const value_type* pointer;
434 typedef std::bidirectional_iterator_tag iterator_category;
445 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
450 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
456 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
459 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
460 #define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
461 valid when iterating below the start and will visit the first entity\
462 twice before getting invalid. Furthermore it gets valid again, if you\
463 increment at the end.\
464 When you are sure that you don't iterate below the start anywhere in\
465 your code or rely on this behaviour, you can disable this warning by\
466 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
468 To be save, you can use the CW/CCW circulator definitions, which behave\
469 the same as the original ones, without the previously mentioned issues."
471 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
472 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
475 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
488 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
489 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
490 #undef DECREMENT_DEPRECATED_WARNINGS_TEXT
491 #endif //NO_DECREMENT_DEPRECATED_WARNINGS
502 assert(this->heh_.is_valid());
503 value_type res = (this->*Handle2Value)();
504 assert(res.is_valid());
507 return (this->*Handle2Value)();
520 pointer_deref_value = **
this;
521 return &pointer_deref_value;
529 bool operator==(
const GenericCirculatorT_DEPRECATED &rhs)
const {
530 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
533 bool operator!=(
const GenericCirculatorT_DEPRECATED &rhs)
const {
534 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
537 bool is_valid()
const {
538 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
541 DEPRECATED(
"current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
551 DEPRECATED(
"Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
557 operator
bool()
const {
566 DEPRECATED(
"This function clutters your code. Use dereferencing operators -> and * instead.")
567 value_type handle()
const {
577 DEPRECATED(
"Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
578 operator value_type()
const {
582 template<
typename STREAM>
584 return s <<
self.mesh_ <<
", " <<
self.start_.idx() <<
", " <<
self.heh_.idx() <<
", " <<
self.lap_counter_;
588 mutable value_type pointer_deref_value;
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
pointer operator->() const
Pointer dereferentiation.
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Handle for a halfedge entity.
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
pointer operator->() const
Pointer dereferentiation.
value_type operator*() const
Standard dereferencing operator.
GenericCirculatorT operator++(int)
Post-increment.
Handle for a vertex entity.
GenericCirculatorT operator--(int)
Post-decrement.
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Handle for a face entity.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
value_type operator*() const
Standard dereferencing operator.