| 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 #pragma once
44
45 //=============================================================================
46 //
47 // Vertex and Face circulators for PolyMesh/TriMesh
48 //
49 //=============================================================================
50
51
52
53 //== INCLUDES =================================================================
54
55 #include <OpenMesh/Core/System/config.h>
56 #include <OpenMesh/Core/Mesh/SmartHandles.hh>
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 template <typename GenericCirculatorT_TraitsT, bool CW = true>
254 class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
255 public:
256 using Mesh = typename GenericCirculatorT_TraitsT::Mesh;
257 using value_type = typename GenericCirculatorT_TraitsT::ValueHandle;
258 using CenterEntityHandle = typename GenericCirculatorT_TraitsT::CenterEntityHandle;
259
260 using smart_value_type = decltype(make_smart(std::declval<value_type>(), std::declval<Mesh>()));
261
262 typedef std::ptrdiff_t difference_type;
263 typedef const value_type& reference;
264 typedef const smart_value_type* pointer;
265 typedef std::bidirectional_iterator_tag iterator_category;
266
267 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
268 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
269 typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, value_type, CW> GenericCirculator_ValueHandleFns;
270
271 public:
272 GenericCirculatorT() {}
273 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
274 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
275
276 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
277 }
278 GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
279 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
280
281 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
282 }
283 GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
284
285 friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
286 explicit GenericCirculatorT( const GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>& rhs )
287 :GenericCirculatorBaseT<Mesh>(rhs){}
288
289 GenericCirculatorT& operator++() {
290 assert(this->mesh_);
291 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
292 return *this;
293 }
294 GenericCirculatorT& operator--() {
295 assert(this->mesh_);
296 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
297 return *this;
298 }
299
301 GenericCirculatorT operator++(int) {
302 assert(this->mesh_);
303 GenericCirculatorT cpy(*this);
304 ++(*this);
305 return cpy;
306 }
307
309 GenericCirculatorT operator--(int) {
310 assert(this->mesh_);
311 GenericCirculatorT cpy(*this);
312 --(*this);
313 return cpy;
314 }
315
317 smart_value_type operator*() const {
318 #ifndef NDEBUG
319 assert(this->heh_.is_valid());
320 value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
321 assert(res.is_valid());
322 return make_smart(res, this->mesh_);
323 #else
324 return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
325 #endif
326 }
327
336 pointer operator->() const {
337 pointer_deref_value = **this;
338 return &pointer_deref_value;
339 }
340
341 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
342 GenericCirculatorBaseT<Mesh>::operator=(rhs);
343 return *this;
344 };
345
346 bool operator==(const GenericCirculatorT &rhs) const {
347 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
348 }
349
350 bool operator!=(const GenericCirculatorT &rhs) const {
351 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
352 }
353
354 bool is_valid() const {
355 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
356 }
357
358 template<typename STREAM>
359 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
360 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
361 }
362
363 private:
364 mutable smart_value_type pointer_deref_value;
365 };
366
371 // OLD CIRCULATORS
372 // deprecated circulators, will be removed soon
373 // if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
374 //
375 // OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
376 // OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
377 // OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
378 // OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
379 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
380 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
381 // OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
382 // OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
383 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
384 // OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
385 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
386 //
387
388 template<class Mesh, class CenterEntityHandle, class ValueHandle>
389 class GenericCirculator_ValueHandleFnsT_DEPRECATED {
390 public:
391 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
392 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
393 }
394 inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
395 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
396 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
397 }
398 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
399 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
400 }
401 };
402
403 template<class Mesh, class CenterEntityHandle>
404 class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
405 public:
406 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
407
408 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
409 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
410 }
411 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
412 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
413 increment(mesh, heh, start, lap_counter);
414 };
415 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
416 do {
417 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
418 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
419 }
420 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
421 do {
422 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
423 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
424 }
425 };
426
427 template <typename GenericCirculatorT_DEPRECATED_TraitsT>
428 class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
429 public:
430 using Mesh = typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh;
431 using CenterEntityHandle = typename GenericCirculatorT_DEPRECATED_TraitsT::CenterEntityHandle;
432 using value_type = typename GenericCirculatorT_DEPRECATED_TraitsT::ValueHandle;
433 using smart_value_type = decltype (make_smart(std::declval<value_type>(), std::declval<Mesh>()));
434
435 typedef std::ptrdiff_t difference_type;
436 typedef const value_type& reference;
437 typedef const smart_value_type* pointer;
438 typedef std::bidirectional_iterator_tag iterator_category;
439
440 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
441 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
442 typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, value_type> GenericCirculator_ValueHandleFns;
443
444 public:
445 GenericCirculatorT_DEPRECATED() {}
446 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
447 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
448
449 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
450 }
451 GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
452 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
453
454 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
455 }
456 GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
457
458 GenericCirculatorT_DEPRECATED& operator++() {
459 assert(this->mesh_);
460 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
461 return *this;
462 }
463 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
464 #define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
465 valid when iterating below the start and will visit the first entity\
466 twice before getting invalid. Furthermore it gets valid again, if you\
467 increment at the end.\
468 When you are sure that you don't iterate below the start anywhere in\
469 your code or rely on this behaviour, you can disable this warning by\
470 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
471 cmake flags).\
472 To be save, you can use the CW/CCW circulator definitions, which behave\
473 the same as the original ones, without the previously mentioned issues."
474
475 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
476 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
477 GenericCirculatorT_DEPRECATED& operator--() {
478 assert(this->mesh_);
479 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
480 return *this;
481 }
482
484 GenericCirculatorT_DEPRECATED operator++(int) {
485 assert(this->mesh_);
486 GenericCirculatorT_DEPRECATED cpy(*this);
487 ++(*this);
488 return cpy;
489 }
490
492 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
493 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
494 #undef DECREMENT_DEPRECATED_WARNINGS_TEXT
495 #endif //NO_DECREMENT_DEPRECATED_WARNINGS
496 GenericCirculatorT_DEPRECATED operator--(int) {
497 assert(this->mesh_);
498 GenericCirculatorT_DEPRECATED cpy(*this);
499 --(*this);
500 return cpy;
501 }
502
504 smart_value_type operator*() const {
505 #ifndef NDEBUG
506 assert(this->heh_.is_valid());
507 value_type res = (GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_));
508 assert(res.is_valid());
509 return make_smart(res, this->mesh_);
510 #else
511 return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
512 #endif
513 }
514
523 pointer operator->() const {
524 pointer_deref_value = **this;
525 return &pointer_deref_value;
526 }
527
528 GenericCirculatorT_DEPRECATED &operator=(const GenericCirculatorT_DEPRECATED &rhs) {
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 OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
551 const HalfedgeHandle &current_halfedge_handle() const {
552 return this->heh_;
553 }
554
555 OM_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 OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
571 smart_value_type handle() const {
572 return **this;
573 }
574
581 OM_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 smart_value_type pointer_deref_value;
593 };
594
595 } // namespace Iterators
596 } // namespace OpenMesh
597
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator++
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition: CirculatorsT.hh:484
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED
Definition: CirculatorsT.hh:428
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::PolyMesh_ArrayKernelT
Polygonal mesh based on the ArrayKernel.
Definition: PolyMesh_ArrayKernelT.hh:94
OpenMesh::Iterators::GenericCirculatorT
Definition: CirculatorsT.hh:254
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT
Definition: CirculatorsT.hh:152
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator*
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:504
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:523
OpenMesh::Iterators::GenericCirculatorT::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:336
OpenMesh::Iterators::GenericCirculatorT::operator--
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:309
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:120
OpenMesh::Iterators::GenericCirculator_CenterEntityFnsT
Definition: CirculatorsT.hh:67
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator--
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:496
OpenMesh::Iterators::GenericCirculator_DereferenciabilityCheckT
Definition: CirculatorsT.hh:130
OpenMesh::Iterators::GenericCirculatorBaseT
Definition: CirculatorsT.hh:191
OpenMesh::make_smart
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
Definition: SmartHandles.hh:186
OpenMesh::Iterators::GenericCirculatorT::operator++
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:301
OpenMesh::Iterators::GenericCirculatorT::operator*
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:317
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:127
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT_DEPRECATED
Definition: CirculatorsT.hh:389