OpenMesh: OpenMesh/Core/Mesh/CirculatorsT.hh Source File

| OpenMesh

CirculatorsT.hh
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2022, 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 <cassert>
57 #include <cstddef>
58 #include <iterator>
59
60 //== NAMESPACES ===============================================================
61
62 namespace OpenMesh {
63
64 template <typename> class CirculatorRange;
65
66 namespace Iterators {
67
68 template<class Mesh, class CenterEntityHandle, bool CW>
69 class GenericCirculator_CenterEntityFnsT {
70 public:
71 static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
72 static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
73 };
74
75 template<class Mesh>
76 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, true> {
77 public:
78 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, 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, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
83 if (heh == start) --lap_counter;
84 heh = mesh->ccw_rotated_halfedge_handle(heh);
85 }
86 };
87
88 template<class Mesh>
89 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, true> {
90 public:
91 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, 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, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
96 if (heh == start) --lap_counter;
97 heh = mesh->prev_halfedge_handle(heh);
98 }
99 };
100
102 // CCW
103
104 template<class Mesh>
105 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, false> {
106 public:
107 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
108 heh = mesh->ccw_rotated_halfedge_handle(heh);
109 if (heh == start) ++lap_counter;
110 }
111 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
112 if (heh == start) --lap_counter;
113 heh = mesh->cw_rotated_halfedge_handle(heh);
114 }
115 };
116
117 template<class Mesh>
118 class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, false> {
119 public:
120 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
121 heh = mesh->prev_halfedge_handle(heh);
122 if (heh == start) ++lap_counter;
123 }
124 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
125 if (heh == start) --lap_counter;
126 heh = mesh->next_halfedge_handle(heh);
127 }
128 };
130
131 template<class Mesh, class CenterEntityHandle, class ValueHandle>
132 class GenericCirculator_DereferenciabilityCheckT {
133 public:
134 //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
135 };
136
137 template<class Mesh>
138 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
139 public:
140 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
141 return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
142 }
143 };
144
145 template<class Mesh>
146 class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
147 public:
148 inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
149 return mesh->face_handle(heh).is_valid();
150 }
151 };
152
153 template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
154 class GenericCirculator_ValueHandleFnsT {
155 public:
156 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
157 return ( heh.is_valid() && (lap_counter == 0 ) );
158 }
159 inline static void init(const Mesh* mesh, typename Mesh::HalfedgeHandle& heh, typename Mesh::HalfedgeHandle& start, int& lap_counter, bool adjust_for_ccw)
160 {
161 if (!CW) // TODO: constexpr if
162 {
163 if (adjust_for_ccw)
164 {
165 // increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
166 int lc = lap_counter;
167 increment(mesh, heh, start, lap_counter);
168 start = heh;
169 lap_counter = lc;
170 }
171 }
172 }
173
174 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
175 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
176 }
177 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
178 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
179 }
180 };
181
182 template<class Mesh, class CenterEntityHandle, bool CW>
183 class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
184 public:
185 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
186
187 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
188 return ( heh.is_valid() && (lap_counter == 0));
189 }
190 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter, bool adjust_for_ccw)
191 {
192 if (!CW) // TODO: constexpr if
193 {
194 if (adjust_for_ccw)
195 {
196 // increment current heh and start so that cw and ccw version dont start with the same element but ranges are actually reversed
197 int lc = lap_counter;
198 increment(mesh, heh, start, lap_counter);
199 start = heh;
200 lap_counter = lc;
201 }
202 }
203 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
204 increment(mesh, heh, start, lap_counter);
205 };
206 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
207 do {
208 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
209 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
210 }
211 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
212 do {
213 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
214 } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
215 }
216 };
217
218 template<class Mesh>
219 class GenericCirculatorBaseT {
220 public:
221 typedef const Mesh* mesh_ptr;
222 typedef const Mesh& mesh_ref;
223
224 template <typename> friend class OpenMesh::CirculatorRange;
225
226 public:
227 GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
228
229 GenericCirculatorBaseT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
230 mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
231
232 GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
233 mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
234
235 inline typename Mesh::FaceHandle toFaceHandle() const {
236 return mesh_->face_handle(heh_);
237 }
238
239 inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
240 return mesh_->face_handle(toOppositeHalfedgeHandle());
241 }
242
243 inline typename Mesh::EdgeHandle toEdgeHandle() const {
244 return mesh_->edge_handle(heh_);
245 }
246
247 inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
248 return heh_;
249 }
250
251 inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
252 return mesh_->opposite_halfedge_handle(heh_);
253 }
254
255 inline typename Mesh::VertexHandle toVertexHandle() const {
256 return mesh_->to_vertex_handle(heh_);
257 }
258
259 inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
260 mesh_ = rhs.mesh_;
261 start_ = rhs.start_;
262 heh_ = rhs.heh_;
263 lap_counter_ = rhs.lap_counter_;
264 return *this;
265 }
266
267 inline bool operator==(const GenericCirculatorBaseT &rhs) const {
268 return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
269 }
270
271 inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
272 return !operator==(rhs);
273 }
274
275 protected:
276 mesh_ptr mesh_;
277 typename Mesh::HalfedgeHandle start_, heh_;
278 int lap_counter_;
279 };
280
281 //template<class Mesh, class CenterEntityHandle, class ValueHandle,
282 // ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
283 template <typename GenericCirculatorT_TraitsT, bool CW = true>
284 class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirculatorT_TraitsT::Mesh> {
285 public:
286 using Mesh = typename GenericCirculatorT_TraitsT::Mesh;
287 using value_type = typename GenericCirculatorT_TraitsT::ValueHandle;
288 using CenterEntityHandle = typename GenericCirculatorT_TraitsT::CenterEntityHandle;
289
290 using smart_value_type = decltype(make_smart(std::declval<value_type>(), std::declval<Mesh>()));
291
292 typedef std::ptrdiff_t difference_type;
293 typedef const value_type& reference;
294 typedef const smart_value_type* pointer;
295 typedef std::bidirectional_iterator_tag iterator_category;
296
297 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
298 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
299 typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, value_type, CW> GenericCirculator_ValueHandleFns;
300
301 template <typename> friend class OpenMesh::CirculatorRange;
302
303 public:
304 GenericCirculatorT() {}
305 GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
306 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end)
307 {
308 bool adjust_for_ccw = true;
309 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
310 }
311 GenericCirculatorT(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
312 GenericCirculatorBaseT<Mesh>(mesh, heh, end)
313 {
314 bool adjust_for_ccw = false; // if iterator is initialized with specific heh, we want to start there
315 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_, adjust_for_ccw);
316 }
317 GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
318
319 friend class GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>;
320 explicit GenericCirculatorT( const GenericCirculatorT<GenericCirculatorT_TraitsT,!CW>& rhs )
321 :GenericCirculatorBaseT<Mesh>(rhs){}
322
323 GenericCirculatorT& operator++() {
324 assert(this->mesh_);
325 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
326 return *this;
327 }
328 GenericCirculatorT& operator--() {
329 assert(this->mesh_);
330 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
331 return *this;
332 }
333
335 GenericCirculatorT operator++(int) {
336 assert(this->mesh_);
337 GenericCirculatorT cpy(*this);
338 ++(*this);
339 return cpy;
340 }
341
343 GenericCirculatorT operator--(int) {
344 assert(this->mesh_);
345 GenericCirculatorT cpy(*this);
346 --(*this);
347 return cpy;
348 }
349
351 smart_value_type operator*() const {
352 #ifndef NDEBUG
353 assert(this->heh_.is_valid());
354 value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
355 assert(res.is_valid());
356 return make_smart(res, this->mesh_);
357 #else
358 return make_smart(GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
359 #endif
360 }
361
370 pointer operator->() const {
371 pointer_deref_value = **this;
372 return &pointer_deref_value;
373 }
374
375 GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
376 GenericCirculatorBaseT<Mesh>::operator=(rhs);
377 return *this;
378 };
379
380 bool operator==(const GenericCirculatorT &rhs) const {
381 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
382 }
383
384 bool operator!=(const GenericCirculatorT &rhs) const {
385 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
386 }
387
388 bool is_valid() const {
389 return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
390 }
391
392 template<typename STREAM>
393 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
394 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
395 }
396
397 private:
398 mutable smart_value_type pointer_deref_value;
399 };
400
405 // OLD CIRCULATORS
406 // deprecated circulators, will be removed soon
407 // if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
408 //
409 // OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
410 // OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
411 // OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
412 // OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
413 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
414 // OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
415 // OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
416 // OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
417 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
418 // OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
419 // OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
420 //
421
422 template<class Mesh, class CenterEntityHandle, class ValueHandle>
423 class GenericCirculator_ValueHandleFnsT_DEPRECATED {
424 public:
425 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
426 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
427 }
428 inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
429 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
430 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
431 }
432 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
433 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
434 }
435 };
436
437 template<class Mesh, class CenterEntityHandle>
438 class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
439 public:
440 typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
441
442 inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
443 return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
444 }
445 inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
446 if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
447 increment(mesh, heh, start, lap_counter);
448 };
449 inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
450 do {
451 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
452 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
453 }
454 inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
455 do {
456 GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
457 } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
458 }
459 };
460
461 template <typename GenericCirculatorT_DEPRECATED_TraitsT>
462 class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh> {
463 public:
464 using Mesh = typename GenericCirculatorT_DEPRECATED_TraitsT::Mesh;
465 using CenterEntityHandle = typename GenericCirculatorT_DEPRECATED_TraitsT::CenterEntityHandle;
466 using value_type = typename GenericCirculatorT_DEPRECATED_TraitsT::ValueHandle;
467 using smart_value_type = decltype (make_smart(std::declval<value_type>(), std::declval<Mesh>()));
468
469 typedef std::ptrdiff_t difference_type;
470 typedef const value_type& reference;
471 typedef const smart_value_type* pointer;
472 typedef std::bidirectional_iterator_tag iterator_category;
473
474 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
475 typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
476 typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, value_type> GenericCirculator_ValueHandleFns;
477
478 template <typename> friend class OpenMesh::CirculatorRange;
479
480 public:
481 GenericCirculatorT_DEPRECATED() {}
482 GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
483 GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
484
485 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
486 }
487 GenericCirculatorT_DEPRECATED(mesh_ref mesh, typename Mesh::HalfedgeHandle heh, bool end = false) :
488 GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
489
490 GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
491 }
492 GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
493
494 GenericCirculatorT_DEPRECATED& operator++() {
495 assert(this->mesh_);
496 GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
497 return *this;
498 }
499 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
500 #define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
501 valid when iterating below the start and will visit the first entity\
502 twice before getting invalid. Furthermore it gets valid again, if you\
503 increment at the end.\
504 When you are sure that you don't iterate below the start anywhere in\
505 your code or rely on this behaviour, you can disable this warning by\
506 setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
507 cmake flags).\
508 To be save, you can use the CW/CCW circulator definitions, which behave\
509 the same as the original ones, without the previously mentioned issues."
510
511 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
512 #endif // NO_DECREMENT_DEPRECATED_WARNINGS
513 GenericCirculatorT_DEPRECATED& operator--() {
514 assert(this->mesh_);
515 GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
516 return *this;
517 }
518
520 GenericCirculatorT_DEPRECATED operator++(int) {
521 assert(this->mesh_);
522 GenericCirculatorT_DEPRECATED cpy(*this);
523 ++(*this);
524 return cpy;
525 }
526
528 #ifndef NO_DECREMENT_DEPRECATED_WARNINGS
529 OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
530 #undef DECREMENT_DEPRECATED_WARNINGS_TEXT
531 #endif //NO_DECREMENT_DEPRECATED_WARNINGS
532 GenericCirculatorT_DEPRECATED operator--(int) {
533 assert(this->mesh_);
534 GenericCirculatorT_DEPRECATED cpy(*this);
535 --(*this);
536 return cpy;
537 }
538
540 smart_value_type operator*() const {
541 #ifndef NDEBUG
542 assert(this->heh_.is_valid());
543 value_type res = (GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_));
544 assert(res.is_valid());
545 return make_smart(res, this->mesh_);
546 #else
547 return make_smart(GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_), this->mesh_);
548 #endif
549 }
550
559 pointer operator->() const {
560 pointer_deref_value = **this;
561 return &pointer_deref_value;
562 }
563
564 GenericCirculatorT_DEPRECATED &operator=(const GenericCirculatorT_DEPRECATED &rhs) {
565 GenericCirculatorBaseT<Mesh>::operator=(rhs);
566 return *this;
567 };
568
569 bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
570 return GenericCirculatorBaseT<Mesh>::operator==(rhs);
571 }
572
573 bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
574 return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
575 }
576
577 bool is_valid() const {
578 return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
579 }
580
581 OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
587 const typename Mesh::HalfedgeHandle &current_halfedge_handle() const {
588 return this->heh_;
589 }
590
591 OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
597 operator bool() const {
598 return is_valid();
599 }
600
606 OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
607 smart_value_type handle() const {
608 return **this;
609 }
610
617 OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
618 operator value_type() const {
619 return **this;
620 }
621
622 template<typename STREAM>
623 friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
624 return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
625 }
626
627 private:
628 mutable smart_value_type pointer_deref_value;
629 };
630
631 } // namespace Iterators
632 } // namespace OpenMesh
633
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::make_smart
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
Definition: SmartHandles.hh:256
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::CirculatorRange
Generic class for iterator ranges.
Definition: PolyConnectivity_inline_impl.hh:92
OpenMesh::Iterators::GenericCirculator_CenterEntityFnsT
Definition: CirculatorsT.hh:69
OpenMesh::Iterators::GenericCirculator_DereferenciabilityCheckT
Definition: CirculatorsT.hh:132
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT
Definition: CirculatorsT.hh:154
OpenMesh::Iterators::GenericCirculatorBaseT
Definition: CirculatorsT.hh:219
OpenMesh::Iterators::GenericCirculatorT
Definition: CirculatorsT.hh:284
OpenMesh::Iterators::GenericCirculatorT::operator*
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:351
OpenMesh::Iterators::GenericCirculatorT::operator++
GenericCirculatorT operator++(int)
Post-increment.
Definition: CirculatorsT.hh:335
OpenMesh::Iterators::GenericCirculatorT::operator--
GenericCirculatorT operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:343
OpenMesh::Iterators::GenericCirculatorT::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:370
OpenMesh::Iterators::GenericCirculator_ValueHandleFnsT_DEPRECATED
Definition: CirculatorsT.hh:423
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED
Definition: CirculatorsT.hh:462
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::current_halfedge_handle
const Mesh::HalfedgeHandle & current_halfedge_handle() const
Definition: CirculatorsT.hh:587
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator++
GenericCirculatorT_DEPRECATED operator++(int)
Post-increment.
Definition: CirculatorsT.hh:520
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator->
pointer operator->() const
Pointer dereferentiation.
Definition: CirculatorsT.hh:559
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator--
GenericCirculatorT_DEPRECATED operator--(int)
Post-decrement.
Definition: CirculatorsT.hh:532
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::operator*
smart_value_type operator*() const
Standard dereferencing operator.
Definition: CirculatorsT.hh:540
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED::handle
smart_value_type handle() const
Return the handle of the current target.
Definition: CirculatorsT.hh:607
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:121
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:128
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:142
OpenMesh::PolyMesh_ArrayKernelT
Polygonal mesh based on the ArrayKernel.
Definition: PolyMesh_ArrayKernelT.hh:96
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
OpenMesh::PolyMeshT::EdgeHandle
Kernel::EdgeHandle EdgeHandle
Scalar type.
Definition: PolyMeshT.hh:138
OpenMesh::PolyMeshT::FaceHandle
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:139
OpenMesh::PolyMeshT::HalfedgeHandle
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137