File: Param_mesh_patch_circulators.h

package info (click to toggle)
cgal 3.2.1-2
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 47,752 kB
  • ctags: 72,510
  • sloc: cpp: 397,707; ansic: 10,393; sh: 4,232; makefile: 3,713; perl: 394; sed: 9
file content (635 lines) | stat: -rw-r--r-- 23,728 bytes parent folder | download
1
2
3
4
5
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
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
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
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
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
// Copyright (c) 2005  INRIA (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.2-branch/Surface_mesh_parameterization/include/CGAL/Param_mesh_patch_circulators.h $
// $Id: Param_mesh_patch_circulators.h 31402 2006-06-02 14:29:41Z lsaboret $
//
//
// Author(s)     : Laurent Saboret, Pierre Alliez, Bruno Levy


#ifndef CGAL_PARAM_MESH_PATCH_CIRCULATORS_H
#define CGAL_PARAM_MESH_PATCH_CIRCULATORS_H

#include <CGAL/iterator.h>
#include <CGAL/circulator.h>
#include <CGAL/Convertible_iterator_project.h>
#include <CGAL/Convertible_circulator_project.h>
#include <CGAL/function_objects.h>
#include <CGAL/HalfedgeDS_iterator.h>
#include <CGAL/Param_mesh_patch_vertex.h>

#include <CGAL/surface_mesh_parameterization_assertions.h>

CGAL_BEGIN_NAMESPACE


/// Class Mesh_patch_vertex_around_vertex_cir
/// represents a (clockwise) circulator around a vertex
/// of a Parameterization_mesh_patch_3<ParameterizationPatchableMesh_3> mesh
template<class MeshPatchType,    ///< = [const] Parameterization_mesh_patch_3
         class VertexHandleType, ///< = Parameterization_mesh_patch_3::Vertex_[const_]handle
         class AdaptorVertexAroundVertexCirculatorType,
                                 ///< = Adaptor::Vertex_around_vertex_[const_]circulator
         class AdaptorVertexHandleType>
                                 ///< = Adaptor::Vertex_[const_]handle
class Mesh_patch_vertex_around_vertex_cir
    : public VertexHandleType
{
// PRIVATE TYPES
// -------------

    /// Base and self classes
    typedef VertexHandleType                    Base;
    typedef Mesh_patch_vertex_around_vertex_cir Self;

    /// Type of the patched mesh
    typedef typename MeshPatchType::Adaptor     Adaptor;

public:

// PUBLIC TYPES
// ------------

    // Export template parameter types
    typedef MeshPatchType                       Parameterization_mesh_patch_3;
    typedef VertexHandleType                    Vertex_handle;
    typedef AdaptorVertexAroundVertexCirculatorType
                                                Adaptor_vertex_around_vertex_circulator;
    typedef AdaptorVertexHandleType             Adaptor_vertex_handle;

    // Iterator types
    typedef typename Adaptor_vertex_around_vertex_circulator::iterator_category
                                                iterator_category;
    typedef typename Vertex_handle::value_type  value_type;
    typedef std::ptrdiff_t                      difference_type;
    typedef std::size_t                         size_type;
    typedef typename Vertex_handle::reference   reference;
    typedef typename Vertex_handle::pointer     pointer;

/// CREATION
/// --------

    /// Circulator pointing to NULL
    Mesh_patch_vertex_around_vertex_cir()
    {
        m_mesh_patch = NULL;
    }

    /// Get circulator over the vertices incident to 'vertex'
    /// 'start_position' defines the initial position of the circulator [required}
    Mesh_patch_vertex_around_vertex_cir(Parameterization_mesh_patch_3& mesh,
                                        Vertex_handle vertex,
                                        Vertex_handle start_position)
      : Base(start_position),
        m_mesh_patch(&mesh),
        m_center(vertex)
    {
        CGAL_surface_mesh_parameterization_assertion(m_mesh_patch->is_valid(vertex));
        CGAL_surface_mesh_parameterization_assertion(m_mesh_patch->is_valid(start_position));

//#ifdef DEBUG_TRACE
//        std::cerr << "    Mesh_patch_vertex_around_vertex_cir(";
//        std::cerr << "#" << m_mesh_patch->get_vertex_index(vertex) << ",";
//        std::cerr << "#" << m_mesh_patch->get_vertex_index(start_position) << ")\n";
//#endif

        // Construct an adaptor circulator over the vertices
        // incident to vertex->vertex()
        m_adaptor_circulator = m_mesh_patch->m_mesh_adaptor.vertices_around_vertex_begin(
                                    vertex->vertex(), start_position->vertex());
    }

    /// Copy constructor
    Mesh_patch_vertex_around_vertex_cir(const Self& cir)
      : Base(cir),
        m_mesh_patch(cir.m_mesh_patch),
        m_center(cir.m_center),
        m_adaptor_circulator(cir.m_adaptor_circulator)
    {
    }

    /// operator =()
    Self& operator =(const Self& cir)
    {
        Base::operator=(cir);
        m_mesh_patch = cir.m_mesh_patch;
        m_center = cir.m_center;
        m_adaptor_circulator = cir.m_adaptor_circulator;

        return *this;
    }

/// OPERATIONS Forward Category
/// ---------------------------

    bool operator==(const Self& cir)    const { return (const Base&)*this == cir; }
    bool operator!=(const Self& cir)    const { return !(*this == cir); }
    bool operator==(CGAL_NULL_TYPE ptr) const { return (const Base&)*this == ptr; }
    bool operator!=(CGAL_NULL_TYPE ptr) const { return !(*this == ptr); }

    ///  operator*() and operator->() are inherited

    /// Clockwise rotation
    Self& operator++()
    {
//#ifdef DEBUG_TRACE
//        std::cerr << "    Mesh_patch_vertex_around_vertex_cir ++\n";
//#endif

        // Check that the inherited vertex handle is valid
        assert((*this)->vertex() == m_adaptor_circulator);

        // If m_center is an inner vertex, m_adaptor_circulator
        // already circulates over m_center's vertices
        if (m_center->first_cw_neighbor() == NULL)
        {
            m_adaptor_circulator++;

            // Update the inherited vertex handle
            update_inherited_handle();

            return *this;
        }

        // If m_center is a border/seam vertex (except a seam extremity),
        // *this must circulate only from
        // first_cw_neighbor() to last_cw_neighbor() (included)
        if (m_center->last_cw_neighbor() != m_center->first_cw_neighbor())
        {
            // if the previous position m_adaptor_circulator
            // is m_center's last clockwise neighbor
            if (m_center->last_cw_neighbor() == m_adaptor_circulator)
            {
                // Skip the outer part of the seam
                while (m_center->first_cw_neighbor() != m_adaptor_circulator)
                    m_adaptor_circulator++;
            }
            else // if the previous position is inner,
            {    // simply rotate the adaptor circulator
                m_adaptor_circulator++;
            }

            // Update the inherited vertex handle
            update_inherited_handle();

            return *this;
        }

        // Special case: m_center is the extremity of the seam.
        // Its seam adaptor neighbor vertex is "virtually" duplicated.
        assert(m_center->last_cw_neighbor() == m_center->first_cw_neighbor());

        // If the previous position is the last "virtual" clockwise neighbor,
        // move to first "virtual" clockwise neighbor
        // without rotating m_adaptor_circulator.
        if (m_center->last_cw_neighbor() == m_adaptor_circulator
         && (*this)->first_cw_neighbor() == m_center->vertex())
        {
            // Update directly the inherited vertex handle
            // because this case is ambiguous for update_inherited_handle()
            Vertex_handle current_decorated_vertex((*this)->vertex(),
                                                   (*this)->first_cw_neighbor(), // order...
                                                   (*this)->last_cw_neighbor()); // ...inverted!
//#ifdef DEBUG_TRACE
//            std::cerr << "      Mesh_patch_vertex_around_vertex_cir = (";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(m_center) << ",";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(current_decorated_vertex);
//            std::cerr << ")\n";
//#endif
            assert(m_mesh_patch->is_valid(current_decorated_vertex));
            Base::operator=(current_decorated_vertex);

            return *this;
        }

        // If the previous position is NOT the last "virtual" clockwise neighbor,
        // simply rotate the adaptor circulator
        m_adaptor_circulator++;

        // Update the inherited vertex handle
        //
        // If the new position is the last "virtual" clockwise neighbor,
        // update directly the inherited vertex handle
        // because this case is ambiguous for update_inherited_handle()
        if (m_center->last_cw_neighbor() == m_adaptor_circulator)
        {
            Vertex_handle current_decorated_vertex
                    = m_mesh_patch->get_decorated_border_vertex(m_adaptor_circulator,
                                                                NULL,
                                                                m_center->vertex());
//#ifdef DEBUG_TRACE
//            std::cerr << "      Mesh_patch_vertex_around_vertex_cir = (";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(m_center) << ",";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(current_decorated_vertex);
//            std::cerr << ")\n";
//#endif
            assert(m_mesh_patch->is_valid(current_decorated_vertex));
            Base::operator=(current_decorated_vertex);

            return *this;
        }
        else
        {
            update_inherited_handle();

            return *this;
        }

    }
    Self  operator++(int) {
        Self tmp = *this;
        ++*this;
        return tmp;
    }

/// OPERATIONS Bidirectional Category
/// ---------------------------------

    /// Counter-clockwise rotation
    Self& operator--()
    {
//#ifdef DEBUG_TRACE
//        std::cerr << "    Mesh_patch_vertex_around_vertex_cir --\n";
//#endif

        // Check that the inherited vertex handle is valid
        assert((*this)->vertex() == m_adaptor_circulator);

        // If m_center is an inner vertex, m_adaptor_circulator
        // already circulates over m_center's vertices
        if (m_center->first_cw_neighbor() == NULL)
        {
            m_adaptor_circulator--;

            // Update the inherited vertex handle
            update_inherited_handle();

            return *this;
        }

        // If m_center is a border/seam vertex (except a seam extremity),
        // *this must circulate only from
        // last_cw_neighbor() to first_cw_neighbor() (included)
        if (m_center->last_cw_neighbor() != m_center->first_cw_neighbor())
        {
            // if the previous position m_adaptor_circulator
            // is m_center's last counter-clockwise neighbor
            if (m_center->first_cw_neighbor() == m_adaptor_circulator)
            {
                // Skip the outer part of the seam
                while (m_center->last_cw_neighbor() != m_adaptor_circulator)
                    m_adaptor_circulator--;
            }
            else // if the previous position is inner,
            {    // simply rotate the adaptor circulator
                m_adaptor_circulator--;
            }

            // Update the inherited vertex handle
            update_inherited_handle();

            return *this;
        }

        // Special case: m_center is the extremity of the seam.
        // Its seam adaptor neighbor vertex is "virtually" duplicated.
        assert(m_center->last_cw_neighbor() == m_center->first_cw_neighbor());

        // If the previous position is on the last "virtual" counter-clockwise
        // neighbor, move to first "virtual" counter-clockwise neighbor
        // without rotating m_adaptor_circulator.
        if (m_center->last_cw_neighbor() == m_adaptor_circulator
         && (*this)->last_cw_neighbor() == m_center->vertex())
        {
            // Update directly the inherited vertex handle
            // because this case is ambiguous for update_inherited_handle()
            Vertex_handle current_decorated_vertex((*this)->vertex(),
                                                   (*this)->first_cw_neighbor(), // order...
                                                   (*this)->last_cw_neighbor()); // ...inverted!
//#ifdef DEBUG_TRACE
//            std::cerr << "      Mesh_patch_vertex_around_vertex_cir = (";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(m_center) << ",";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(current_decorated_vertex);
//            std::cerr << ")\n";
//#endif
            assert(m_mesh_patch->is_valid(current_decorated_vertex));
            Base::operator=(current_decorated_vertex);

            return *this;
        }

        // If the previous position is NOT the last "virtual" counter-clockwise
        //  neighbor, simply rotate the adaptor circulator
        m_adaptor_circulator--;

        // Update the inherited vertex handle
        //
        // If the new position is the last "virtual" counter-clockwise neighbor,
        // update directly the inherited vertex handle
        // because this case is ambiguous for update_inherited_handle()
        if (m_center->last_cw_neighbor() == m_adaptor_circulator)
        {
            Vertex_handle current_decorated_vertex
                    = m_mesh_patch->get_decorated_border_vertex(m_adaptor_circulator,
                                                                m_center->vertex(),
                                                                NULL);
//#ifdef DEBUG_TRACE
//            std::cerr << "      Mesh_patch_vertex_around_vertex_cir = (";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(m_center) << ",";
//            std::cerr << "#" << m_mesh_patch->get_vertex_index(current_decorated_vertex);
//            std::cerr << ")\n";
//#endif
            assert(m_mesh_patch->is_valid(current_decorated_vertex));
            Base::operator=(current_decorated_vertex);

            return *this;
        }
        else
        {
            update_inherited_handle();

            return *this;
        }

    }
    Self  operator--(int) {
        Self tmp = *this;
        --*this;
        return tmp;
    }

private:
    /// Update the inherited vertex handle
    ///
    /// Precondition: m_adaptor_circulator and m_center are valid
    void update_inherited_handle()
    {
        Vertex_handle current_decorated_vertex = NULL;

        // Easy case: if m_adaptor_circulator is an inner vertex
        if (m_mesh_patch->m_mesh_adaptor.get_vertex_seaming(
                m_adaptor_circulator) != Parameterization_mesh_patch_3::BORDER)
        {
            // No extra information needed if inner vertex
            current_decorated_vertex = Vertex_handle(m_adaptor_circulator);
        }
        else // if seam vertex
        {
            // Ambiguous case: m_center is the extremity of the seam
            //                 and m_adaptor_circulator is on the seam
            assert(m_center->last_cw_neighbor() != m_adaptor_circulator
                || m_center->first_cw_neighbor() != m_adaptor_circulator);

            // Get next vertex on facet
            Adaptor_vertex_handle next_vertex = NULL;
            Adaptor_vertex_around_vertex_circulator ccw_neighbor = m_adaptor_circulator;
            ccw_neighbor--;
            if (m_center->first_cw_neighbor() == NULL) // if inner vertex
            {
                next_vertex = ccw_neighbor;
            }
            else // if border/seam vertex, circulates only from
            {    // first_cw_neighbor() to last_cw_neighbor() (included)
                if (m_center->first_cw_neighbor() == m_adaptor_circulator)
                    next_vertex = m_center->vertex();
                else
                    next_vertex = ccw_neighbor;
            }

            // If (m_adaptor_circulator, next_vertex) isn't a seam (non-oriented) edge
            if (m_mesh_patch->m_mesh_adaptor.get_halfedge_seaming(
                m_adaptor_circulator, next_vertex) != Parameterization_mesh_patch_3::BORDER
            || m_mesh_patch->m_mesh_adaptor.get_halfedge_seaming(
                next_vertex, m_adaptor_circulator) != Parameterization_mesh_patch_3::BORDER)
            {
                current_decorated_vertex
                        = m_mesh_patch->get_decorated_inner_vertex(m_adaptor_circulator,
                                                                   next_vertex);
            }
            // Special case: both vertices belong to the seam
            else
            {
                current_decorated_vertex
                        = m_mesh_patch->get_decorated_border_vertex(m_adaptor_circulator,
                                                                    next_vertex,
                                                                    NULL);
            }
        }

//#ifdef DEBUG_TRACE
//        std::cerr << "      Mesh_patch_vertex_around_vertex_cir = (";
//        std::cerr << "#" << m_mesh_patch->get_vertex_index(m_center) << ",";
//        std::cerr << "#" << m_mesh_patch->get_vertex_index(current_decorated_vertex);
//        std::cerr << ")\n";
//#endif

        // Update the inherited vertex handle
        assert(m_mesh_patch->is_valid(current_decorated_vertex));
        Base::operator=(current_decorated_vertex);
    }

private:
    /// The mesh that we are circulating on:
    Parameterization_mesh_patch_3* m_mesh_patch;

    /// Vertex center of the circulation (+ circulator range for a border vertex)
    Vertex_handle m_center;

    /// Internal circulator
    Adaptor_vertex_around_vertex_circulator m_adaptor_circulator;

}; // Mesh_patch_vertex_around_vertex_cir


/// Class Mesh_patch_vertex_around_facet_cir
/// represents a (clockwise) circulator around a facet
/// of a Parameterization_mesh_patch_3<ParameterizationPatchableMesh_3> mesh

template<class MeshPatchType,    ///< = [const] Parameterization_mesh_patch_3
         class VertexHandleType, ///< = Parameterization_mesh_patch_3::Vertex_[const_]handle
         class AdaptorVertexAroundFacetCirculatorType>
                                 ///< = Adaptor::Vertex_around_facet_[const_]circulator
class Mesh_patch_vertex_around_facet_cir
    : public VertexHandleType
{
// PRIVATE TYPES
// -------------

    /// Base and self classes
    typedef VertexHandleType                    Base;
    typedef Mesh_patch_vertex_around_facet_cir  Self;

    /// Type of the patched mesh
    typedef typename MeshPatchType::Adaptor     Adaptor;

public:

// PUBLIC TYPES
// ------------

    // Export template parameter types
    typedef MeshPatchType                       Parameterization_mesh_patch_3;
    typedef VertexHandleType                    Vertex_handle;
    typedef AdaptorVertexAroundFacetCirculatorType
                                                Adaptor_vertex_around_facet_circulator;

    // Iterator types
    typedef typename Adaptor_vertex_around_facet_circulator::iterator_category
                                                iterator_category;
    typedef typename Vertex_handle::value_type  value_type;
    typedef std::ptrdiff_t                      difference_type;
    typedef std::size_t                         size_type;
    typedef typename Vertex_handle::reference   reference;
    typedef typename Vertex_handle::pointer     pointer;

/// CREATION
/// --------

    /// Circulator pointing to NULL
    Mesh_patch_vertex_around_facet_cir()
    {
        m_mesh_patch = NULL;
    }

    Mesh_patch_vertex_around_facet_cir(Parameterization_mesh_patch_3& mesh,
                                       Adaptor_vertex_around_facet_circulator adaptor_circulator)
        : m_mesh_patch(&mesh),
          m_adaptor_circulator(adaptor_circulator)
    {
        CGAL_surface_mesh_parameterization_assertion(adaptor_circulator != NULL);

        // Update the inherited vertex handle
        update_inherited_handle();
    }

    /// Copy constructor
    Mesh_patch_vertex_around_facet_cir(const Self& cir)
      : Base(cir),
        m_mesh_patch(cir.m_mesh_patch),
        m_adaptor_circulator(cir.m_adaptor_circulator)
    {
        // Update the inherited vertex handle
        update_inherited_handle();
    }

    /// operator =()
    Self& operator =(const Self& cir)
    {
        Base::operator=(cir);
        m_mesh_patch = cir.m_mesh_patch;
        m_adaptor_circulator = cir.m_adaptor_circulator;

        // Update the inherited vertex handle
        update_inherited_handle();

        return *this;
    }

/// OPERATIONS Forward Category
/// ---------------------------

    bool operator==(CGAL_NULL_TYPE ptr) const { return (const Base&)*this == ptr; }
    bool operator!=(CGAL_NULL_TYPE ptr) const { return !(*this == ptr); }
    bool operator==(const Self& cir)    const { return (const Base&)*this == cir; }
    bool operator!=(const Self& cir)    const { return !(*this == cir); }

    ///  operator*() and operator->() are inherited

    /// Clockwise rotation
    Self& operator++()
    {
        // Increment m_adaptor_circulator
        m_adaptor_circulator++;

        // Update the inherited vertex handle
        update_inherited_handle();

        return *this;
    }
    Self  operator++(int) {
        Self tmp = *this;
        ++*this;
        return tmp;
    }

/// OPERATIONS Bidirectional Category
/// ---------------------------------

    /// Counterclockwise rotation
    Self& operator--()
    {
        // Decrement m_adaptor_circulator
        m_adaptor_circulator--;

        // Update the inherited vertex handle
        update_inherited_handle();

        return *this;
    }
    Self  operator--(int) {
        Self tmp = *this;
        --*this;
        return tmp;
    }

private:
    /// Update the inherited vertex handle
    ///
    /// Precondition: m_adaptor_circulator is valid
    void update_inherited_handle()
    {
        Vertex_handle current_decorated_vertex = NULL;

        // Get next vertex on facet
        Adaptor_vertex_around_facet_circulator next_vertex = m_adaptor_circulator;
        next_vertex++;

        // If (m_adaptor_circulator, next_vertex) isn't a seam (non-oriented) edge
        if (m_mesh_patch->m_mesh_adaptor.get_halfedge_seaming(
                m_adaptor_circulator, next_vertex) != Parameterization_mesh_patch_3::BORDER
         || m_mesh_patch->m_mesh_adaptor.get_halfedge_seaming(
                next_vertex, m_adaptor_circulator) != Parameterization_mesh_patch_3::BORDER)
        {
            current_decorated_vertex
                    = m_mesh_patch->get_decorated_inner_vertex(m_adaptor_circulator,
                                                               next_vertex);
        }
        // Special case: both vertices belong to the seam
        else
        {
            current_decorated_vertex
                    = m_mesh_patch->get_decorated_border_vertex(m_adaptor_circulator,
                                                                next_vertex,
                                                                NULL);
        }

        // Update the inherited vertex handle
        assert(m_mesh_patch->is_valid(current_decorated_vertex));
        Base::operator=(current_decorated_vertex);
    }

private:
    /// The mesh that we are circulating on:
    Parameterization_mesh_patch_3* m_mesh_patch;

    /// Internal circulator
    Adaptor_vertex_around_facet_circulator m_adaptor_circulator;

}; // Mesh_patch_vertex_around_facet_cir


CGAL_END_NAMESPACE

#endif //CGAL_PARAM_MESH_PATCH_CIRCULATORS_H