| OpenMesh

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 #ifndef OPENMESH_CIRCULATORS_HH
45 #define OPENMESH_CIRCULATORS_HH
46 //=============================================================================
47 //
48 // Vertex and Face circulators for PolyMesh/TriMesh
49 //
50 //=============================================================================
51
52
53
54 //== INCLUDES =================================================================
55
56 #include <OpenMesh/Core/System/config.h>
57 #include <cassert>
58 #include <cstddef>
59 #include <iterator>
60
61 //== NAMESPACES ===============================================================
62
63 namespace OpenMesh {
64 namespace Iterators {
65
66 template<class Mesh, class CenterEntityHandle, bool CW>
67 class GenericCirculator_CenterEntityFnsT {
68 public:
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);
71 };
72
73 template<class Mesh>
74 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, true> {
75 public:
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;
79 }
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);
83 }
84 };
85
86 template<class Mesh>
87 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, true> {
88 public:
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;
92 }
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);
96 }
97 };
98
100 // CCW
101
102 template<class Mesh>
103 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, false> {
104 public:
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;
108 }
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);
112 }
113 };
114
115 template<class Mesh>
116 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, false> {
117 public:
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;
121 }
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);
125 }
126 };
128
129 template<class Mesh, class CenterEntityHandle, class ValueHandle>
130 class GenericCirculator_DereferenciabilityCheckT {
131 public:
132 //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
133 };
134
135 template<class Mesh>
136 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
137 public:
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();
140 }
141 };
142
143 template<class Mesh>
144 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
145 public:
146 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
147 return mesh->face_handle(heh).is_valid();
148 }
149 };
150
151 template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
152 class GenericCirculator_ValueHandleFnsT {
153 public:
154 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
155 return ( heh.is_valid() && (lap_counter == 0 ) );
156 }
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) {
159 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
160 }
161 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
162 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
163 }
164 };
165
166 template<class Mesh, class CenterEntityHandle, bool CW>
167 class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
168 public:
169 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
170
171 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
172 return ( heh.is_valid() && (lap_counter == 0));
173 }
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);
177 };
178 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
179 do {
180 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
181 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
182 }
183 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
184 do {
185 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
186 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
187 }
188 };
189
190 template<class Mesh>
191 class GenericCirculatorBaseT {
192 public:
193 typedef const Mesh* mesh_ptr;
194 typedef const Mesh& mesh_ref;
195
196 public:
197 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
198
199 GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
200 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
201
202 GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
203 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
204
205 inline typename Mesh::FaceHandle toFaceHandle() const {
206 return mesh_->face_handle(heh_);
207 }
208
209 inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
210 return mesh_->face_handle(toOppositeHalfedgeHandle());
211 }
212
213 inline typename Mesh::EdgeHandle toEdgeHandle() const {
214 return mesh_->edge_handle(heh_);
215 }
216
217 inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
218 return heh_;
219 }
220
221 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
222 return mesh_->opposite_halfedge_handle(heh_);
223 }
224
225 inline typename Mesh::VertexHandle toVertexHandle() const {
226 return mesh_->to_vertex_handle(heh_);
227 }
228
229 inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
230 mesh_ = rhs.mesh_;
231 start_ = rhs.start_;
232 heh_ = rhs.heh_;
233 lap_counter_ = rhs.lap_counter_;
234 return *this;
235 }
236
237 inline bool operator==(const GenericCirculatorBaseT &rhs) const {
238 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
239 }
240
241 inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
242 return !operator==(rhs);
243 }
244
245 protected:
246 mesh_ptr mesh_;
247 typename Mesh::HalfedgeHandle start_, heh_;
248 int lap_counter_;
249 };
250
251 template<class Mesh, class CenterEntityHandle, class ValueHandle,
252 ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
253 class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
254 public:
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;
260
261 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
262 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
263 typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, ValueHandle, CW> GenericCirculator_ValueHandleFns;
264
265 public:
266 GenericCirculatorT() {}
267 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
268 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
269
270 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
271 }
272 GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
273 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
274
275 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
276 }
277 GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
278
279 friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
280 explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
281 :GenericCirculatorBaseT<Mesh>(rhs){}
282
283 GenericCirculatorT& operator++() {
284 assert(this->mesh_);
285 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
286 return *this;
287 }
288 GenericCirculatorT& operator--() {
289 assert(this->mesh_);
290 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
291 return *this;
292 }
293
295 GenericCirculatorT operator++(int) {
296 assert(this->mesh_);
297 GenericCirculatorT cpy(*this);
298 ++(*this);
299 return cpy;
300 }
301
303 GenericCirculatorT operator--(int) {
304 assert(this->mesh_);
305 GenericCirculatorT cpy(*this);
306 --(*this);
307 return cpy;
308 }
309
311 value_type operator*() const {
312 // We can't use this due to a GCC6 compiler bug
313 const GenericCirculatorBaseT<Mesh>* self = this;
314 #ifndef NDEBUG
315 assert(this->heh_.is_valid());
316 value_type res = (self->*Handle2Value)();
317 assert(res.is_valid());
318 return res;
319 #else
320 return (self->*Handle2Value)();
321 #endif
322 }
323
332 pointer operator->() const {
333 pointer_deref_value = **this;
334 return &pointer_deref_value;
335 }
336
337 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
338 GenericCirculatorBaseT<Mesh>::operator=(rhs);
339 return *this;
340 };
341
342 bool operator==(const GenericCirculatorT &rhs) const {
343 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
344 }
345
346 bool operator!=(const GenericCirculatorT &rhs) const {
347 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
348 }
349
350 bool is_valid() const {
351 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
352 }
353
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_;
357 }
358
359 private:
360 mutable value_type pointer_deref_value;
361 };
362
367 // OLD CIRCULATORS
368 // deprecated circulators, will be removed soon
369 // if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
370 //
371 // OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
372 // OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
373 // OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
374 // OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
375 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
376 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
377 // OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
378 // OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
379 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
380 // OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
381 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
382 //
383
384 template<class Mesh, class CenterEntityHandle, class ValueHandle>
385 class GenericCirculator_ValueHandleFnsT_DEPRECATED {
386 public:
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 )) );
389 }
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) {
392 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
393 }
394 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
395 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
396 }
397 };
398
399 template<class Mesh, class CenterEntityHandle>
400 class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
401 public:
402 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
403
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 )));
406 }
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);
410 };
411 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
412 do {
413 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
414 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
415 }
416 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
417 do {
418 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
419 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
420 }
421 };
422
423 template<class Mesh, class CenterEntityHandle, class ValueHandle,
424 ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
425 class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
426 public:
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;
432
433 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
434 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
435 typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, ValueHandle> GenericCirculator_ValueHandleFns;
436
437 public:
438 GenericCirculatorT_DEPRECATED() {}
439 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
440 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
441
442 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
443 }
444 GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
445 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
446
447 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
448 }
449 GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
450
451 GenericCirculatorT_DEPRECATED& operator++() {
452 assert(this->mesh_);
453 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
454 return *this;
455 }
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\
464 cmake flags).\
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."
467
468 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
469 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
470 GenericCirculatorT_DEPRECATED& operator--() {
471 assert(this->mesh_);
472 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
473 return *this;
474 }
475
477 GenericCirculatorT_DEPRECATED operator++(int) {
478 assert(this->mesh_);
479 GenericCirculatorT_DEPRECATED cpy(*this);
480 ++(*this);
481 return cpy;
482 }
483
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
489 GenericCirculatorT_DEPRECATED operator--(int) {
490 assert(this->mesh_);
491 GenericCirculatorT_DEPRECATED cpy(*this);
492 --(*this);
493 return cpy;
494 }
495
497 value_type operator*() const {
498 // We can't use this due to a GCC6 compiler bug
499 const GenericCirculatorBaseT<Mesh>* self = this;
500 #ifndef NDEBUG
501 assert(this->heh_.is_valid());
502 value_type res = (self->*Handle2Value)();
503 assert(res.is_valid());
504 return res;
505 #else
506 return (self->*Handle2Value)();
507 #endif
508 }
509
518 pointer operator->() const {
519 pointer_deref_value = **this;
520 return &pointer_deref_value;
521 }
522
523 GenericCirculatorT_DEPRECATED &operator=(const GenericCirculatorT_DEPRECATED &rhs) {
524 GenericCirculatorBaseT<Mesh>::operator=(rhs);
525 return *this;
526 };
527
528 bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
529 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
530 }
531
532 bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
533 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
534 }
535
536 bool is_valid() const {
537 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
538 }
539
540 OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
546 const HalfedgeHandle &current_halfedge_handle() const {
547 return this->heh_;
548 }
549
550 OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
556 operator bool() const {
557 return is_valid();
558 }
559
565 OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
566 value_type handle() const {
567 return **this;
568 }
569
576 OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
577 operator value_type() const {
578 return **this;
579 }
580
581 template<typename STREAM>
582 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
583 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
584 }
585
586 private:
587 mutable value_type pointer_deref_value;
588 };
589
590 } // namespace Iterators
591 } // namespace OpenMesh
592
593 #endif
OpenMesh::operator<<
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
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:127
OpenMesh::Iterators::GenericCirculator_CenterEntityFnsT
Definition: CirculatorsT.hh:67
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:120
OpenMesh::Iterators::GenericCirculatorT::operator--
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:303
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator++
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition: CirculatorsT.hh:477
OpenMesh::Iterators::GenericCirculatorT::operator*
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:311
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT_DEPRECATED
Definition: CirculatorsT.hh:385
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator*
value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:497
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED
Definition: CirculatorsT.hh:425
OpenMesh::Iterators::GenericCirculatorT
Definition: CirculatorsT.hh:253
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT
Definition: CirculatorsT.hh:152
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator--
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:489
OpenMesh::Iterators::GenericCirculator_DereferenciabilityCheckT
Definition: CirculatorsT.hh:130
OpenMesh::PolyMesh_ArrayKernelT
Polygonal mesh based on the ArrayKernel.
Definition: PolyMesh_ArrayKernelT.hh:94
OpenMesh::Iterators::GenericCirculatorT::operator++
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:295
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT_DEPRECATED< Mesh, CenterEntityHandle, typename Mesh::FaceHandle >
Definition: CirculatorsT.hh:400
OpenMesh::Iterators::GenericCirculatorBaseT
Definition: CirculatorsT.hh:191
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
OpenMesh::Iterators::GenericCirculatorT::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:332
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:518