OpenMesh
CirculatorsT.hh
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2025, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42
43#pragma once
44
45//=============================================================================
46//
47// Vertex, Face, and Edge circulators for PolyMesh/TriMesh
48//
49//=============================================================================
50
51
52
53//== INCLUDES =================================================================
54
55#include <OpenMesh/Core/System/config.h>
56#include <cassert>
57#include <cstddef>
58#include <iterator>
59
60//== NAMESPACES ===============================================================
61
62namespace OpenMesh {
63
64template <typename> class CirculatorRange;
65
66namespace Iterators {
67
68template<class Mesh, class CenterEntityHandle, bool CW>
70 public:
71 static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter);
72 static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter);
73};
74
75template<class Mesh>
77 public:
78 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
79 heh = mesh->cw_rotated_halfedge_handle(heh);
80 if (heh == start) ++lap_counter;
81 }
82 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
83 if (heh == start) --lap_counter;
84 heh = mesh->ccw_rotated_halfedge_handle(heh);
85 }
86};
87
88template<class Mesh>
90 public:
91 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
92 heh = mesh->next_halfedge_handle(heh);
93 if (heh == start) ++lap_counter;
94 }
95 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
96 if (heh == start) --lap_counter;
97 heh = mesh->prev_halfedge_handle(heh);
98 }
99};
100
101template<class Mesh, bool CW>
103 public:
104 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
105 heh = mesh->opposite_halfedge_handle(heh);
106 if (heh == start) ++lap_counter;
107 }
108 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
109 if (heh == start) --lap_counter;
110 heh = mesh->opposite_halfedge_handle(heh);
111 }
112};
113
115// CCW
116
117template<class Mesh>
119 public:
120 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
121 heh = mesh->ccw_rotated_halfedge_handle(heh);
122 if (heh == start) ++lap_counter;
123 }
124 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
125 if (heh == start) --lap_counter;
126 heh = mesh->cw_rotated_halfedge_handle(heh);
127 }
128};
129
130template<class Mesh>
132 public:
133 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
134 heh = mesh->prev_halfedge_handle(heh);
135 if (heh == start) ++lap_counter;
136 }
137 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
138 if (heh == start) --lap_counter;
139 heh = mesh->next_halfedge_handle(heh);
140 }
141};
143
144template<class Mesh, class CenterEntityHandle, class ValueHandle>
146 public:
147 //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
148};
149
150template<class Mesh>
152 public:
153 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
154 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
155 }
156};
157
158template<class Mesh>
160 public:
161 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
162 return mesh->face_handle(heh).is_valid();
163 }
164};
165
166template<class Mesh>
168 public:
169 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
170 return mesh->face_handle(heh).is_valid();
171 }
172};
173
174template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
176 public:
177 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
178 return ( heh.is_valid() && (lap_counter == 0 ) );
179 }
180 inline static void init(const Mesh* mesh, typename Mesh::HalfedgeHandle& heh, typename Mesh::HalfedgeHandle& start, int& lap_counter, bool adjust_for_ccw)
181 {
182 if (!CW) // TODO: constexpr if
183 {
184 if (adjust_for_ccw)
185 {
186 // increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
187 int lc = lap_counter;
188 increment(mesh, heh, start, lap_counter);
189 start = heh;
190 lap_counter = lc;
191 }
192 }
193 }
194
195 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
197 }
198 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
200 }
201};
202
203template<class Mesh, class CenterEntityHandle, bool CW>
204class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
205 public:
207
208 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
209 return ( heh.is_valid() && (lap_counter == 0));
210 }
211 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter, bool adjust_for_ccw)
212 {
213 if (!CW) // TODO: constexpr if
214 {
215 if (adjust_for_ccw)
216 {
217 // increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
218 int lc = lap_counter;
219 increment(mesh, heh, start, lap_counter);
220 start = heh;
221 lap_counter = lc;
222 }
223 }
224 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
225 increment(mesh, heh, start, lap_counter);
226 };
227 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
228 do {
230 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
231 }
232 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
233 do {
235 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
236 }
237};
238
239template<class Mesh>
241 public:
242 typedef const Mesh* mesh_ptr;
243 typedef const Mesh& mesh_ref;
244
245 template <typename> friend class OpenMesh::CirculatorRange;
246
247 public:
248 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
249
250 GenericCirculatorBaseT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
251 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
252
254 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
255
256 inline typename Mesh::FaceHandle toFaceHandle() const {
257 return mesh_->face_handle(heh_);
258 }
259
260 inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
261 return mesh_->face_handle(toOppositeHalfedgeHandle());
262 }
263
264 inline typename Mesh::EdgeHandle toEdgeHandle() const {
265 return mesh_->edge_handle(heh_);
266 }
267
268 inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
269 return heh_;
270 }
271
272 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
273 return mesh_->opposite_halfedge_handle(heh_);
274 }
275
276 inline typename Mesh::VertexHandle toVertexHandle() const {
277 return mesh_->to_vertex_handle(heh_);
278 }
279
280 inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
281 mesh_ = rhs.mesh_;
282 start_ = rhs.start_;
283 heh_ = rhs.heh_;
284 lap_counter_ = rhs.lap_counter_;
285 return *this;
286 }
287
288 inline bool operator==(const GenericCirculatorBaseT &rhs) const {
289 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
290 }
291
292 inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
293 return !operator==(rhs);
294 }
295
296 protected:
297 mesh_ptr mesh_;
298 typename Mesh::HalfedgeHandle start_, heh_;
299 int lap_counter_;
300};
301
302//template<class Mesh, class CenterEntityHandle, class ValueHandle,
303// ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
304template <typename GenericCirculatorT_TraitsT, bool CW = true>
305class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
306 public:
307 using Mesh = typename GenericCirculatorT_TraitsT::Mesh;
308 using value_type = typename GenericCirculatorT_TraitsT::ValueHandle;
309 using CenterEntityHandle = typename GenericCirculatorT_TraitsT::CenterEntityHandle;
310
311 using smart_value_type = decltype(make_smart(std::declval<value_type>(), std::declval<Mesh>()));
312
313 typedef std::ptrdiff_t difference_type;
314 typedef const value_type& reference;
315 typedef const smart_value_type* pointer;
316 typedef std::bidirectional_iterator_tag iterator_category;
317
321
322 template <typename> friend class OpenMesh::CirculatorRange;
323
324 public:
326 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
327 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end)
328 {
329 bool adjust_for_ccw = true;
330 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
331 }
332 GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
333 GenericCirculatorBaseT<Mesh>(mesh, heh, end)
334 {
335 bool adjust_for_ccw = false; // if iterator is initialized with specific heh, we want to start there
336 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
337 }
339
340 friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
343
344 GenericCirculatorT& operator++() {
345 assert(this->mesh_);
346 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
347 return *this;
348 }
349 GenericCirculatorT& operator--() {
350 assert(this->mesh_);
351 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
352 return *this;
353 }
354
357 assert(this->mesh_);
358 GenericCirculatorT cpy(*this);
359 ++(*this);
360 return cpy;
361 }
362
365 assert(this->mesh_);
366 GenericCirculatorT cpy(*this);
367 --(*this);
368 return cpy;
369 }
370
372 smart_value_type operator*() const {
373#ifndef NDEBUG
374 assert(this->heh_.is_valid());
375 value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
376 assert(res.is_valid());
377 return make_smart(res, this->mesh_);
378#else
379 return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
380#endif
381 }
382
391 pointer operator->() const {
392 pointer_deref_value = **this;
393 return &pointer_deref_value;
394 }
395
396 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
398 return *this;
399 };
400
401 bool operator==(const GenericCirculatorT &rhs) const {
402 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
403 }
404
405 bool operator!=(const GenericCirculatorT &rhs) const {
406 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
407 }
408
409 bool is_valid() const {
410 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
411 }
412
413 template<typename STREAM>
414 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
415 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
416 }
417
418 private:
419 mutable smart_value_type pointer_deref_value;
420};
421
426// OLD CIRCULATORS
427// deprecated circulators, will be removed soon
428// if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
429//
430// OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
431// OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
432// OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
433// OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
434// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
435// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
436// OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
437// OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
438// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
439// OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
440// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
441//
442
443template<class Mesh, class CenterEntityHandle, class ValueHandle>
445 public:
446 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
447 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
448 }
449 inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
450 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
452 }
453 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
455 }
456};
457
458template<class Mesh, class CenterEntityHandle>
460 public:
462
463 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
464 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
465 }
466 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
467 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
468 increment(mesh, heh, start, lap_counter);
469 };
470 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
471 do {
473 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
474 }
475 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, int &lap_counter) {
476 do {
478 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
479 }
480};
481
482template <typename GenericCirculatorT_DEPRECATED_TraitsT>
483class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
484 public:
485 using Mesh = typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh;
486 using CenterEntityHandle = typename GenericCirculatorT_DEPRECATED_TraitsT::CenterEntityHandle;
487 using value_type = typename GenericCirculatorT_DEPRECATED_TraitsT::ValueHandle;
488 using smart_value_type = decltype (make_smart(std::declval<value_type>(), std::declval<Mesh>()));
489
490 typedef std::ptrdiff_t difference_type;
491 typedef const value_type& reference;
492 typedef const smart_value_type* pointer;
493 typedef std::bidirectional_iterator_tag iterator_category;
494
498
499 template <typename> friend class OpenMesh::CirculatorRange;
500
501 public:
503 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
504 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
505
506 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
507 }
508 GenericCirculatorT_DEPRECATED(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
509 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
510
511 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
512 }
514
515 GenericCirculatorT_DEPRECATED& operator++() {
516 assert(this->mesh_);
517 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
518 return *this;
519 }
520#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
521#define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
522 valid when iterating below the start and will visit the first entity\
523 twice before getting invalid. Furthermore it gets valid again, if you\
524 increment at the end.\
525 When you are sure that you don't iterate below the start anywhere in\
526 your code or rely on this behaviour, you can disable this warning by\
527 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
528 cmake flags).\
529 To be save, you can use the CW/CCW circulator definitions, which behave\
530 the same as the original ones, without the previously mentioned issues."
531
532 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
533#endif // NO_DECREMENT_DEPRECATED_WARNINGS
534 GenericCirculatorT_DEPRECATED& operator--() {
535 assert(this->mesh_);
536 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
537 return *this;
538 }
539
542 assert(this->mesh_);
544 ++(*this);
545 return cpy;
546 }
547
549#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
550 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
551#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
552#endif //NO_DECREMENT_DEPRECATED_WARNINGS
554 assert(this->mesh_);
556 --(*this);
557 return cpy;
558 }
559
561 smart_value_type operator*() const {
562#ifndef NDEBUG
563 assert(this->heh_.is_valid());
564 value_type res = (GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_));
565 assert(res.is_valid());
566 return make_smart(res, this->mesh_);
567#else
568 return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
569#endif
570 }
571
580 pointer operator->() const {
581 pointer_deref_value = **this;
582 return &pointer_deref_value;
583 }
584
587 return *this;
588 };
589
590 bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
591 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
592 }
593
594 bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
595 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
596 }
597
598 bool is_valid() const {
599 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
600 }
601
602 OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
608 const typename Mesh::HalfedgeHandle &current_halfedge_handle() const {
609 return this->heh_;
610 }
611
612 OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
618 operator bool() const {
619 return is_valid();
620 }
621
627 OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
628 smart_value_type handle() const {
629 return **this;
630 }
631
638 OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
639 operator value_type() const {
640 return **this;
641 }
642
643 template<typename STREAM>
644 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
645 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
646 }
647
648 private:
649 mutable smart_value_type pointer_deref_value;
650};
651
652} // namespace Iterators
653} // namespace OpenMesh
654
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
Definition: SmartHandles.hh:265
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
Generic class for iterator ranges.
Definition: PolyConnectivity_inline_impl.hh:92
Definition: CirculatorsT.hh:240
Definition: CirculatorsT.hh:305
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:372
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:356
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:364
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:391
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition: CirculatorsT.hh:541
const Mesh::HalfedgeHandle & current_halfedge_handle() const
Definition: CirculatorsT.hh:608
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:580
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:553
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:561
smart_value_type handle() const
Return the handle of the current target.
Definition: CirculatorsT.hh:628
Handle for a vertex entity.
Definition: Handles.hh:121
Handle for a halfedge entity.
Definition: Handles.hh:128
Handle for a edge entity.
Definition: Handles.hh:135
Handle for a face entity.
Definition: Handles.hh:142
Polygonal mesh based on the ArrayKernel.
Definition: PolyMesh_ArrayKernelT.hh:96
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Kernel::EdgeHandle EdgeHandle
Scalar type.
Definition: PolyMeshT.hh:138
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:139
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .