CirculatorsT.hh 27.9 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
/* ========================================================================= *
Jan Möbius's avatar
Jan Möbius committed
2 3
 *                                                                           *
 *                               OpenMesh                                    *
Jan Möbius's avatar
Jan Möbius committed
4
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
Jan Möbius's avatar
Typo  
Jan Möbius committed
5
 *           Department of Computer Graphics and Multimedia                  *
Jan Möbius's avatar
Jan Möbius committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39 40
 *                                                                           *
 * ========================================================================= */
41 42 43 44 45

/*===========================================================================*\
 *                                                                           *             
 *   $Revision$                                                         *
 *   $Date$                   *
Jan Möbius's avatar
Jan Möbius committed
46 47
 *                                                                           *
\*===========================================================================*/
48

Jan Möbius's avatar
Jan Möbius committed
49 50 51 52 53 54 55 56 57 58 59 60 61
#ifndef OPENMESH_CIRCULATORS_HH
#define OPENMESH_CIRCULATORS_HH
//=============================================================================
//
//  Vertex and Face circulators for PolyMesh/TriMesh
//
//=============================================================================



//== INCLUDES =================================================================

#include <OpenMesh/Core/System/config.h>
62
#include <cassert>
63
#include <cstddef>
Matthias Möller's avatar
Matthias Möller committed
64
#include <iterator>
Jan Möbius's avatar
Jan Möbius committed
65 66 67 68 69 70

//== NAMESPACES ===============================================================

namespace OpenMesh {
namespace Iterators {

71
template<class Mesh, class CenterEntityHandle, bool CW>
72 73
class GenericCirculator_CenterEntityFnsT {
    public:
74 75
        static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
        static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
76
};
Jan Möbius's avatar
Jan Möbius committed
77

78
template<class Mesh>
79
class 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 88 89 90 91
            heh = mesh->ccw_rotated_halfedge_handle(heh);
        }
};

template<class Mesh>
92
class 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 101 102 103
            heh = mesh->prev_halfedge_handle(heh);
        }
};

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/////////////////////////////////////////////////////////////
// CCW

template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, false> {
    public:
        inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            heh = mesh->ccw_rotated_halfedge_handle(heh);
            if (heh == start) ++lap_counter;
        }
        inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            if (heh == start) --lap_counter;
            heh = mesh->cw_rotated_halfedge_handle(heh);
        }
};

template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, false>  {
    public:
        inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            heh = mesh->prev_halfedge_handle(heh);
            if (heh == start) ++lap_counter;
        }
        inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            if (heh == start) --lap_counter;
            heh = mesh->next_halfedge_handle(heh);
        }
};
/////////////////////////////////////////////////////////////

134 135 136 137 138 139 140 141 142
template<class Mesh, class CenterEntityHandle, class ValueHandle>
class GenericCirculator_DereferenciabilityCheckT {
    public:
        //inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
};

template<class Mesh>
class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
    public:
143
        inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
144 145 146 147 148 149 150
            return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
        }
};

template<class Mesh>
class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
    public:
151
        inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
152 153 154 155
            return mesh->face_handle(heh).is_valid();
        }
};

156
template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
157 158
class GenericCirculator_ValueHandleFnsT {
    public:
159 160
        inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
            return ( heh.is_valid() && (lap_counter == 0 ) );
161
        }
162 163
        inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
        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
        }
};

171 172
template<class Mesh, class CenterEntityHandle, bool CW>
class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
173
    public:
174 175
        typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;

176 177
        inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
            return ( heh.is_valid() &&  (lap_counter == 0));
178
        }
179 180
        inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
181 182
                increment(mesh, heh, start, lap_counter);
        };
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);
Jan Möbius's avatar
Jan Möbius committed
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);
Jan Möbius's avatar
Jan Möbius committed
191
            } while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
192 193
        }
};
Jan Möbius's avatar
Jan Möbius committed
194

195 196 197 198 199 200 201
template<class Mesh>
class GenericCirculatorBaseT {
    public:
        typedef const Mesh* mesh_ptr;
        typedef const Mesh& mesh_ref;

    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 208 209 210 211 212 213

        GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
            mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}

        inline typename Mesh::FaceHandle toFaceHandle() const {
            return mesh_->face_handle(heh_);
        }

214 215 216 217
        inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
            return mesh_->face_handle(toOppositeHalfedgeHandle());
        }

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
        inline typename Mesh::EdgeHandle toEdgeHandle() const {
            return mesh_->edge_handle(heh_);
        }

        inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
            return heh_;
        }

        inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
            return mesh_->opposite_halfedge_handle(heh_);
        }

        inline typename Mesh::VertexHandle toVertexHandle() const {
            return mesh_->to_vertex_handle(heh_);
        }

        inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
            mesh_ = rhs.mesh_;
            start_ = rhs.start_;
            heh_ = rhs.heh_;
            lap_counter_ = rhs.lap_counter_;
            return *this;
        }

        inline bool operator==(const GenericCirculatorBaseT &rhs) const {
            return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
        }

        inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
            return !operator==(rhs);
        }

    protected:
        mesh_ptr mesh_;
        typename Mesh::HalfedgeHandle start_, heh_;
253
        int lap_counter_;
254
};
Jan Möbius's avatar
Jan Möbius committed
255

256
template<class Mesh, class CenterEntityHandle, class ValueHandle,
257
        ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
258 259 260 261 262 263 264 265 266 267
class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
    public:
        typedef std::ptrdiff_t difference_type;
        typedef ValueHandle value_type;
        typedef const value_type& reference;
        typedef const value_type* pointer;
        typedef std::bidirectional_iterator_tag iterator_category;

        typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
        typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
268
        typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, ValueHandle, CW> GenericCirculator_ValueHandleFns;
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

    public:
        GenericCirculatorT() {}
        GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
            GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {

            GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
        }
        GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
            GenericCirculatorBaseT<Mesh>(mesh, heh, end) {

            GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
        }
        GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}

284 285 286 287
        friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
        explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
        :GenericCirculatorBaseT<Mesh>(rhs){}

288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
        GenericCirculatorT& operator++() {
            assert(this->mesh_);
            GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
            return *this;
        }
        GenericCirculatorT& operator--() {
            assert(this->mesh_);
            GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
            return *this;
        }

        /// Post-increment
        GenericCirculatorT operator++(int) {
            assert(this->mesh_);
            GenericCirculatorT cpy(*this);
            ++(*this);
            return cpy;
        }

        /// Post-decrement
        GenericCirculatorT operator--(int) {
            assert(this->mesh_);
            GenericCirculatorT cpy(*this);
            --(*this);
            return cpy;
        }

        /// Standard dereferencing operator.
        value_type operator*() const {
317 318
            // We can't use this due to a GCC6 compiler bug
            const GenericCirculatorBaseT<Mesh>* self = this;
319 320
#ifndef NDEBUG
            assert(this->heh_.is_valid());
321
            value_type res = (self->*Handle2Value)();
322 323 324
            assert(res.is_valid());
            return res;
#else
325
            return (self->*Handle2Value)();
326
#endif
327 328
        }

329 330 331 332 333 334 335 336 337 338 339
        /**
         * @brief Pointer dereferentiation.
         *
         * This returns a pointer which points to a handle
         * that loses its validity once this dereferentiation is
         * invoked again. Thus, do not store the result of
         * this operation.
         */
        pointer operator->() const {
            pointer_deref_value = **this;
            return &pointer_deref_value;
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
        }

        GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
            GenericCirculatorBaseT<Mesh>::operator=(rhs);
            return *this;
        };

        bool operator==(const GenericCirculatorT &rhs) const {
            return GenericCirculatorBaseT<Mesh>::operator==(rhs);
        }

        bool operator!=(const GenericCirculatorT &rhs) const {
            return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
        }

        bool is_valid() const {
Jan Möbius's avatar
Jan Möbius committed
356
            return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
357 358
        }

359 360 361 362 363
        template<typename STREAM>
        friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
            return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
        }

364 365
    private:
        mutable value_type pointer_deref_value;
366
};
Jan Möbius's avatar
Jan Möbius committed
367

368 369 370 371 372 373 374 375 376 377 378 379 380 381
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////           OLD           ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OLD CIRCULATORS
// deprecated circulators, will be removed soon
// if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
//
// OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
382 383 384 385 386
// OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
// OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
//

template<class Mesh, class CenterEntityHandle, class ValueHandle>
class GenericCirculator_ValueHandleFnsT_DEPRECATED {
    public:
        inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
            return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
        }
        inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
        inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
        }
        inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
        }
};

template<class Mesh, class CenterEntityHandle>
class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
    public:
        typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;

        inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
            return ( heh.is_valid() &&  ((start != heh) || (lap_counter == 0 )));
        }
        inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
                increment(mesh, heh, start, lap_counter);
        };
        inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            do {
                GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
            } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
        }
        inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
            do {
                GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
            } while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
        }
};

template<class Mesh, class CenterEntityHandle, class ValueHandle,
        ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
    public:
        typedef std::ptrdiff_t difference_type;
        typedef ValueHandle value_type;
        typedef const value_type& reference;
        typedef const value_type* pointer;
        typedef std::bidirectional_iterator_tag iterator_category;

        typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
        typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
        typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, ValueHandle> GenericCirculator_ValueHandleFns;

    public:
        GenericCirculatorT_DEPRECATED() {}
        GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
            GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {

          GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
        }
        GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
            GenericCirculatorBaseT<Mesh>(mesh, heh, end) {

          GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
        }
        GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}

        GenericCirculatorT_DEPRECATED& operator++() {
            assert(this->mesh_);
            GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
            return *this;
        }
Matthias Möller's avatar
Matthias Möller committed
461 462 463 464 465 466 467 468 469 470 471 472
#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
#define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
    valid when iterating below the start and will visit the first entity\
    twice before getting invalid. Furthermore it gets valid again, if you\
    increment at the end.\
    When you are sure that you don't iterate below the start anywhere in\
    your code or rely on this behaviour, you can disable this warning by\
    setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
    cmake flags).\
    To be save, you can use the CW/CCW circulator definitions, which behave\
    the same as the original ones, without the previously mentioned issues."

473
        OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
Matthias Möller's avatar
Matthias Möller committed
474
#endif // NO_DECREMENT_DEPRECATED_WARNINGS
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
        GenericCirculatorT_DEPRECATED& operator--() {
            assert(this->mesh_);
            GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
            return *this;
        }

        /// Post-increment
        GenericCirculatorT_DEPRECATED operator++(int) {
            assert(this->mesh_);
            GenericCirculatorT_DEPRECATED cpy(*this);
            ++(*this);
            return cpy;
        }

        /// Post-decrement
Matthias Möller's avatar
Matthias Möller committed
490
#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
491
        OM_DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
Matthias Möller's avatar
Matthias Möller committed
492 493
#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
#endif //NO_DECREMENT_DEPRECATED_WARNINGS
494 495 496 497 498 499 500 501 502
        GenericCirculatorT_DEPRECATED operator--(int) {
            assert(this->mesh_);
            GenericCirculatorT_DEPRECATED cpy(*this);
            --(*this);
            return cpy;
        }

        /// Standard dereferencing operator.
        value_type operator*() const {
503 504
            // We can't use this due to a GCC6 compiler bug
            const GenericCirculatorBaseT<Mesh>* self = this;
505 506
#ifndef NDEBUG
            assert(this->heh_.is_valid());
507
            value_type res = (self->*Handle2Value)();
508 509 510
            assert(res.is_valid());
            return res;
#else
511
            return (self->*Handle2Value)();
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
#endif
        }

        /**
         * @brief Pointer dereferentiation.
         *
         * This returns a pointer which points to a handle
         * that loses its validity once this dereferentiation is
         * invoked again. Thus, do not store the result of
         * this operation.
         */
        pointer operator->() const {
            pointer_deref_value = **this;
            return &pointer_deref_value;
        }

        GenericCirculatorT_DEPRECATED &operator=(const GenericCirculatorT_DEPRECATED &rhs) {
            GenericCirculatorBaseT<Mesh>::operator=(rhs);
            return *this;
        };

        bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
            return GenericCirculatorBaseT<Mesh>::operator==(rhs);
        }

        bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
            return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
        }

        bool is_valid() const {
            return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
        }

545
        OM_DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
546 547 548 549 550 551 552 553 554
        /**
         * \deprecated
         * current_halfedge_handle() is an implementation detail and should not
         * be accessed from outside the iterator class.
         */
        const HalfedgeHandle &current_halfedge_handle() const {
            return this->heh_;
        }

555
        OM_DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
556 557 558 559 560 561 562 563 564 565 566 567 568 569
        /**
         * \deprecated
         * Do not use this error prone implicit cast. Compare to the
         * end-iterator or use is_valid() instead.
         */
        operator bool() const {
            return is_valid();
        }

        /**
         * \brief Return the handle of the current target.
         * \deprecated
         * This function clutters your code. Use dereferencing operators -> and * instead.
         */
570
        OM_DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
571 572 573 574 575 576 577 578 579 580
        value_type handle() const {
          return **this;
        }

        /**
         * \brief Cast to the handle of the current target.
         * \deprecated
         * Implicit casts of iterators are unsafe. Use dereferencing operators
         * -> and * instead.
         */
581
        OM_DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
582 583 584 585 586 587 588 589 590 591 592 593 594
        operator value_type() const {
          return **this;
        }

        template<typename STREAM>
        friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
            return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
        }

    private:
        mutable value_type pointer_deref_value;
};

Jan Möbius's avatar
Jan Möbius committed
595 596
} // namespace Iterators
} // namespace OpenMesh
597

Jan Möbius's avatar
Jan Möbius committed
598
#endif