OpenMesh
Loading...
Searching...
No Matches
CirculatorsT.hh
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, 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 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47\*===========================================================================*/
48
49#ifndef OPENMESH_CIRCULATORS_HH
50#define OPENMESH_CIRCULATORS_HH
51//=============================================================================
52//
53// Vertex and Face circulators for PolyMesh/TriMesh
54//
55//=============================================================================
56
57
58
59//== INCLUDES =================================================================
60
61#include <OpenMesh/Core/System/config.h>
62#include <cassert>
63#include <cstddef>
64#include <iterator>
65
66//== NAMESPACES ===============================================================
67
68namespace OpenMesh {
69namespace Iterators {
70
71template<class Mesh, class CenterEntityHandle, bool CW>
73 public:
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);
76};
77
78template<class Mesh>
79class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, true> {
80 public:
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;
84 }
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);
88 }
89};
90
91template<class Mesh>
92class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, true> {
93 public:
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;
97 }
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);
101 }
102};
103
105// CCW
106
107template<class Mesh>
108class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, false> {
109 public:
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;
113 }
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);
117 }
118};
119
120template<class Mesh>
121class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, false> {
122 public:
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;
126 }
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);
130 }
131};
132
133
134template<class Mesh, class CenterEntityHandle, class ValueHandle>
136 public:
137 //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
138};
139
140template<class Mesh>
141class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
142 public:
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();
145 }
146};
147
148template<class Mesh>
149class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
150 public:
151 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
152 return mesh->face_handle(heh).is_valid();
153 }
154};
155
156template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
158 public:
159 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
160 return ( heh.is_valid() && (lap_counter == 0 ) );
161 }
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);
165 }
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);
168 }
169};
170
171template<class Mesh, class CenterEntityHandle, bool CW>
172class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
173 public:
175
176 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
177 return ( heh.is_valid() && (lap_counter == 0));
178 }
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);
182 };
183 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
184 do {
185 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
186 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
187 }
188 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
189 do {
190 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
191 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
192 }
193};
194
195template<class Mesh>
196class GenericCirculatorBaseT {
197 public:
198 typedef const Mesh* mesh_ptr;
199 typedef const Mesh& mesh_ref;
200
201 public:
202 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
203
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())) {}
206
207 GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
208 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
209
210 inline typename Mesh::FaceHandle toFaceHandle() const {
211 return mesh_->face_handle(heh_);
212 }
213
214 inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
215 return mesh_->face_handle(toOppositeHalfedgeHandle());
216 }
217
218 inline typename Mesh::EdgeHandle toEdgeHandle() const {
219 return mesh_->edge_handle(heh_);
220 }
221
222 inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
223 return heh_;
224 }
225
226 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
227 return mesh_->opposite_halfedge_handle(heh_);
228 }
229
230 inline typename Mesh::VertexHandle toVertexHandle() const {
231 return mesh_->to_vertex_handle(heh_);
232 }
233
234 inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
235 mesh_ = rhs.mesh_;
236 start_ = rhs.start_;
237 heh_ = rhs.heh_;
238 lap_counter_ = rhs.lap_counter_;
239 return *this;
240 }
241
242 inline bool operator==(const GenericCirculatorBaseT &rhs) const {
243 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
244 }
245
246 inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
247 return !operator==(rhs);
248 }
249
250 protected:
251 mesh_ptr mesh_;
252 typename Mesh::HalfedgeHandle start_, heh_;
253 int lap_counter_;
254};
255
256template<class Mesh, class CenterEntityHandle, class ValueHandle,
257 ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
258class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
259 public:
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;
265
266 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
267 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
269
270 public:
271 GenericCirculatorT() {}
272 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
273 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
274
275 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
276 }
277 GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
278 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
279
280 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
281 }
282 GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
283
284 friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
285 explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
286 :GenericCirculatorBaseT<Mesh>(rhs){}
287
288 GenericCirculatorT& operator++() {
289 assert(this->mesh_);
290 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
291 return *this;
292 }
293 GenericCirculatorT& operator--() {
294 assert(this->mesh_);
295 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
296 return *this;
297 }
298
300 GenericCirculatorT operator++(int) {
301 assert(this->mesh_);
302 GenericCirculatorT cpy(*this);
303 ++(*this);
304 return cpy;
305 }
306
308 GenericCirculatorT operator--(int) {
309 assert(this->mesh_);
310 GenericCirculatorT cpy(*this);
311 --(*this);
312 return cpy;
313 }
314
316 value_type operator*() const {
317 // We can't use this due to a GCC6 compiler bug
318 const GenericCirculatorBaseT<Mesh>* self = this;
319#ifndef NDEBUG
320 assert(this->heh_.is_valid());
321 value_type res = (self->*Handle2Value)();
322 assert(res.is_valid());
323 return res;
324#else
325 return (self->*Handle2Value)();
326#endif
327 }
328
337 pointer operator->() const {
338 pointer_deref_value = **this;
339 return &pointer_deref_value;
340 }
341
342 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
343 GenericCirculatorBaseT<Mesh>::operator=(rhs);
344 return *this;
345 };
346
347 bool operator==(const GenericCirculatorT &rhs) const {
348 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
349 }
350
351 bool operator!=(const GenericCirculatorT &rhs) const {
352 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
353 }
354
355 bool is_valid() const {
356 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
357 }
358
359 template<typename STREAM>
360 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
361 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
362 }
363
364 private:
365 mutable value_type pointer_deref_value;
366};
367
372// OLD CIRCULATORS
373// deprecated circulators, will be removed soon
374// if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
375//
376// OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
377// OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
378// OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
379// OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
380// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
381// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
382// OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
383// OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
384// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
385// OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
386// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
387//
388
389template<class Mesh, class CenterEntityHandle, class ValueHandle>
391 public:
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 )) );
394 }
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);
398 }
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);
401 }
402};
403
404template<class Mesh, class CenterEntityHandle>
406 public:
408
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 )));
411 }
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);
415 };
416 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
417 do {
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));
420 }
421 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
422 do {
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));
425 }
426};
427
428template<class Mesh, class CenterEntityHandle, class ValueHandle,
429 ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
430class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
431 public:
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;
437
438 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
439 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
441
442 public:
443 GenericCirculatorT_DEPRECATED() {}
444 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
445 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
446
447 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
448 }
449 GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
450 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
451
452 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
453 }
454 GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
455
456 GenericCirculatorT_DEPRECATED& operator++() {
457 assert(this->mesh_);
458 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
459 return *this;
460 }
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\
469 cmake flags).\
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."
472
473 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
474#endif // NO_DECREMENT_DEPRECATED_WARNINGS
475 GenericCirculatorT_DEPRECATED& operator--() {
476 assert(this->mesh_);
477 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
478 return *this;
479 }
480
482 GenericCirculatorT_DEPRECATED operator++(int) {
483 assert(this->mesh_);
484 GenericCirculatorT_DEPRECATED cpy(*this);
485 ++(*this);
486 return cpy;
487 }
488
490#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
491 DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
492#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
493#endif //NO_DECREMENT_DEPRECATED_WARNINGS
494 GenericCirculatorT_DEPRECATED operator--(int) {
495 assert(this->mesh_);
496 GenericCirculatorT_DEPRECATED cpy(*this);
497 --(*this);
498 return cpy;
499 }
500
502 value_type operator*() const {
503 // We can't use this due to a GCC6 compiler bug
504 const GenericCirculatorBaseT<Mesh>* self = this;
505#ifndef NDEBUG
506 assert(this->heh_.is_valid());
507 value_type res = (self->*Handle2Value)();
508 assert(res.is_valid());
509 return res;
510#else
511 return (self->*Handle2Value)();
512#endif
513 }
514
523 pointer operator->() const {
524 pointer_deref_value = **this;
525 return &pointer_deref_value;
526 }
527
529 GenericCirculatorBaseT<Mesh>::operator=(rhs);
530 return *this;
531 };
532
533 bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
534 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
535 }
536
537 bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
538 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
539 }
540
541 bool is_valid() const {
542 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
543 }
544
545 DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
552 return this->heh_;
553 }
554
555 DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
561 operator bool() const {
562 return is_valid();
563 }
564
570 DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
571 value_type handle() const {
572 return **this;
573 }
574
581 DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
582 operator value_type() const {
583 return **this;
584 }
585
586 template<typename STREAM>
587 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
588 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
589 }
590
591 private:
592 mutable value_type pointer_deref_value;
593};
594
595} // namespace Iterators
596} // namespace OpenMesh
597
598#endif
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: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
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition CirculatorsT.hh:494
value_type operator*() const
Standard dereferencing operator.
Definition CirculatorsT.hh:502
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

Project OpenMesh, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .