44 #ifndef OPENMESH_CIRCULATORS_HH 45 #define OPENMESH_CIRCULATORS_HH 66 template<
class Mesh,
class CenterEntityHandle,
bool CW>
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);
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;
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);
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;
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);
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;
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);
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;
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);
129 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle>
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();
146 inline static bool isDereferenciable(
const Mesh *mesh,
const typename Mesh::HalfedgeHandle &heh) {
147 return mesh->face_handle(heh).is_valid();
151 template<
class Mesh,
class CenterEntityHandle,
class ValueHandle,
bool CW = true>
154 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const int lap_counter) {
155 return ( heh.is_valid() && (lap_counter == 0 ) );
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) {
161 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
166 template<
class Mesh,
class CenterEntityHandle,
bool CW>
171 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const int lap_counter) {
172 return ( heh.is_valid() && (lap_counter == 0));
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);
178 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
181 }
while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
183 inline static void decrement(
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));
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_) {}
205 inline typename Mesh::FaceHandle toFaceHandle()
const {
206 return mesh_->face_handle(heh_);
209 inline typename Mesh::FaceHandle toOppositeFaceHandle()
const {
210 return mesh_->face_handle(toOppositeHalfedgeHandle());
213 inline typename Mesh::EdgeHandle toEdgeHandle()
const {
214 return mesh_->edge_handle(heh_);
217 inline typename Mesh::HalfedgeHandle toHalfedgeHandle()
const {
221 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle()
const {
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);
247 typename Mesh::HalfedgeHandle start_, heh_;
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;
350 bool is_valid()
const {
351 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
354 template<
typename STREAM>
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>
387 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
388 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
390 inline static void init(
const Mesh*,
typename Mesh::HalfedgeHandle&,
typename Mesh::HalfedgeHandle&,
int&) {};
391 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
394 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
399 template<
class Mesh,
class CenterEntityHandle>
404 inline static bool is_valid(
const typename Mesh::HalfedgeHandle &heh,
const typename Mesh::HalfedgeHandle &start,
const int lap_counter) {
405 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
407 inline static void init(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
408 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
409 increment(mesh, heh, start, lap_counter);
411 inline static void increment(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
414 }
while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
416 inline static void decrement(
const Mesh *mesh,
typename Mesh::HalfedgeHandle &heh,
typename Mesh::HalfedgeHandle &start,
int &lap_counter) {
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;
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;
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
value_type operator*() const
Standard dereferencing operator.
Handle for a vertex entity.
pointer operator->() const
Pointer dereferentiation.
Handle for a halfedge entity.
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
GenericCirculatorT operator--(int)
Post-decrement.
pointer operator->() const
Pointer dereferentiation.
value_type operator*() const
Standard dereferencing operator.
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Handle for a face entity.
bool is_valid() const
The handle is valid iff the index is not negative.
GenericCirculatorT operator++(int)
Post-increment.