1101 lines
36 KiB
C++
1101 lines
36 KiB
C++
// Copyright (c) 1997
|
|
// Utrecht University (The Netherlands),
|
|
// ETH Zurich (Switzerland),
|
|
// INRIA Sophia-Antipolis (France),
|
|
// Max-Planck-Institute Saarbruecken (Germany),
|
|
// and Tel-Aviv University (Israel). All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org)
|
|
//
|
|
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Circulator/include/CGAL/circulator.h $
|
|
// $Id: circulator.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
|
|
//
|
|
//
|
|
// Author(s) : Lutz Kettner <kettner@inf.ethz.ch>
|
|
|
|
#ifndef CGAL_CIRCULATOR_H
|
|
#define CGAL_CIRCULATOR_H
|
|
|
|
#include <CGAL/config.h>
|
|
#include <CGAL/circulator_bases.h>
|
|
#include <CGAL/assertions.h>
|
|
#include <CGAL/use.h>
|
|
#include <CGAL/tags.h>
|
|
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <iterator>
|
|
|
|
#include <boost/type_traits/is_convertible.hpp>
|
|
|
|
// These are name redefinitions for backwards compatibility
|
|
// with the pre iterator-traits style adaptors.
|
|
|
|
#define Forward_container_from_circulator \
|
|
Container_from_circulator
|
|
#define Bidirectional_container_from_circulator \
|
|
Container_from_circulator
|
|
#define Random_access_container_from_circulator \
|
|
Container_from_circulator
|
|
|
|
#define Forward_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
#define Forward_const_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
#define Bidirectional_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
#define Bidirectional_const_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
#define Random_access_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
#define Random_access_const_circulator_from_iterator \
|
|
Circulator_from_iterator
|
|
|
|
#define Forward_circulator_from_container \
|
|
Circulator_from_container
|
|
#define Bidirectional_circulator_from_container \
|
|
Circulator_from_container
|
|
#define Random_access_circulator_from_container \
|
|
Circulator_from_container
|
|
|
|
#define Forward_const_circulator_from_container \
|
|
Const_circulator_from_container
|
|
#define Bidirectional_const_circulator_from_container \
|
|
Const_circulator_from_container
|
|
#define Random_access_const_circulator_from_container \
|
|
Const_circulator_from_container
|
|
|
|
|
|
|
|
namespace CGAL {
|
|
|
|
namespace internal {
|
|
|
|
// default to Iterator_tag, special case Circulator tags
|
|
template<typename Tag>
|
|
struct Get_category
|
|
{ typedef Iterator_tag type; };
|
|
|
|
template<>
|
|
struct Get_category<CGAL::Forward_circulator_tag>
|
|
{ typedef Circulator_tag type; };
|
|
|
|
template<>
|
|
struct Get_category<CGAL::Bidirectional_circulator_tag>
|
|
{ typedef Circulator_tag type; };
|
|
|
|
template<>
|
|
struct Get_category<CGAL::Random_access_circulator_tag>
|
|
{ typedef Circulator_tag type; };
|
|
|
|
} // internal
|
|
|
|
|
|
// Circulator_size_traits are used by general adaptors for
|
|
// iterators and circulators. For example the N_step_adaptor
|
|
// works for iterators as well as for circulators. Circulators
|
|
// need a local type called size_type which is not needed for
|
|
// iterators. But a general adaptor has to declare this type
|
|
// in any case and the following Circulator_size_traits helps
|
|
// in this case. It declares size_type to be std::size_t for
|
|
// iterators and to be C::size_type for any circulator C.
|
|
template <class Tag, class IC>
|
|
struct I_Circulator_size_traits {
|
|
typedef std::size_t size_type;
|
|
};
|
|
|
|
template <class C>
|
|
struct I_Circulator_size_traits< Forward_circulator_tag, C> {
|
|
typedef typename C::size_type size_type;
|
|
};
|
|
template <class C>
|
|
struct I_Circulator_size_traits< Bidirectional_circulator_tag, C> {
|
|
typedef typename C::size_type size_type;
|
|
};
|
|
template <class C>
|
|
struct I_Circulator_size_traits< Random_access_circulator_tag, C> {
|
|
typedef typename C::size_type size_type;
|
|
};
|
|
|
|
template <class CCtg>
|
|
struct I_Iterator_from_circulator_traits {
|
|
typedef CCtg iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Iterator_from_circulator_traits< Forward_circulator_tag> {
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Iterator_from_circulator_traits<
|
|
Bidirectional_circulator_tag> {
|
|
typedef std::bidirectional_iterator_tag iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Iterator_from_circulator_traits<
|
|
Random_access_circulator_tag> {
|
|
typedef std::random_access_iterator_tag iterator_category;
|
|
};
|
|
|
|
template <class ICtg>
|
|
struct I_Circulator_from_iterator_traits {
|
|
typedef ICtg iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Circulator_from_iterator_traits< std::forward_iterator_tag> {
|
|
typedef Forward_circulator_tag iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Circulator_from_iterator_traits<std::bidirectional_iterator_tag> {
|
|
typedef Bidirectional_circulator_tag iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct I_Circulator_from_iterator_traits<std::random_access_iterator_tag> {
|
|
typedef Random_access_circulator_tag iterator_category;
|
|
};
|
|
|
|
template <class C>
|
|
struct Circulator_traits {
|
|
private:
|
|
typedef std::iterator_traits<C> iterator_traits;
|
|
public:
|
|
// the ardent reader might wonder: why redirect through
|
|
// iterator_traits? That way we don't miss specializations and
|
|
// can save us our own specializations.
|
|
typedef typename internal::Get_category<
|
|
typename iterator_traits::iterator_category
|
|
>::type category;
|
|
|
|
typedef typename iterator_traits::value_type value_type;
|
|
typedef typename iterator_traits::reference reference;
|
|
typedef typename iterator_traits::pointer pointer;
|
|
typedef typename iterator_traits::difference_type difference_type;
|
|
typedef typename iterator_traits::iterator_category iterator_category;
|
|
|
|
typedef typename I_Circulator_size_traits<
|
|
category, C>::size_type size_type;
|
|
};
|
|
|
|
template <class C>
|
|
typename Circulator_traits<C>::category
|
|
query_circulator_or_iterator( const C&) {
|
|
typedef typename Circulator_traits<C>::category category;
|
|
return category();
|
|
}
|
|
|
|
template <class C> inline
|
|
void Assert_circulator( const C &) {
|
|
typedef typename Circulator_traits<C>::category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, Circulator_tag>::value));
|
|
}
|
|
|
|
template <class I> inline
|
|
void Assert_iterator( const I &) {
|
|
typedef typename Circulator_traits<I>::category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, Iterator_tag>::value));
|
|
}
|
|
template <class I> inline
|
|
void Assert_input_category( const I &/*i*/) {
|
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, std::input_iterator_tag>::value));
|
|
}
|
|
|
|
template <class I> inline
|
|
void Assert_output_category( const I &/*i*/) {
|
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, std::output_iterator_tag>::value));
|
|
}
|
|
template <class IC> inline
|
|
void Assert_forward_category( const IC &/*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, std::forward_iterator_tag>::value));
|
|
}
|
|
template <class IC> inline
|
|
void Assert_bidirectional_category( const IC &/*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, std::bidirectional_iterator_tag>::value));
|
|
}
|
|
template <class IC> inline
|
|
void Assert_random_access_category( const IC &/*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
CGAL_USE_TYPE(category);
|
|
CGAL_static_assertion((boost::is_convertible<category, std::random_access_iterator_tag>::value));
|
|
}
|
|
// The assert at-least-category functions use the following
|
|
// functions to resolve properly. Note the proper order of the
|
|
// arguments: 1st is the to be type, 2nd is the actual type.
|
|
inline void I_Has_to_be_at_least( std::input_iterator_tag,
|
|
std::input_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::input_iterator_tag,
|
|
std::forward_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::input_iterator_tag,
|
|
std::bidirectional_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::input_iterator_tag,
|
|
std::random_access_iterator_tag){}
|
|
|
|
inline void I_Has_to_be_at_least( std::output_iterator_tag,
|
|
std::output_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::output_iterator_tag,
|
|
std::forward_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::output_iterator_tag,
|
|
std::bidirectional_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::output_iterator_tag,
|
|
std::random_access_iterator_tag){}
|
|
|
|
inline void I_Has_to_be_at_least( std::forward_iterator_tag,
|
|
std::forward_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::forward_iterator_tag,
|
|
std::bidirectional_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::forward_iterator_tag,
|
|
std::random_access_iterator_tag){}
|
|
|
|
inline void I_Has_to_be_at_least( std::bidirectional_iterator_tag,
|
|
std::bidirectional_iterator_tag){}
|
|
inline void I_Has_to_be_at_least( std::bidirectional_iterator_tag,
|
|
std::random_access_iterator_tag){}
|
|
|
|
inline void I_Has_to_be_at_least( std::random_access_iterator_tag,
|
|
std::random_access_iterator_tag){}
|
|
|
|
// The is-at-least assertions.
|
|
template <class I> inline
|
|
void Assert_is_at_least_input_category( const I& /*i*/) {
|
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
|
I_Has_to_be_at_least( std::input_iterator_tag(),
|
|
category());
|
|
}
|
|
template <class I> inline
|
|
void Assert_is_at_least_output_category( const I& /*i*/) {
|
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
|
I_Has_to_be_at_least( std::output_iterator_tag(),
|
|
category());
|
|
}
|
|
template <class IC> inline
|
|
void Assert_is_at_least_forward_category( const IC& /*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
I_Has_to_be_at_least( std::forward_iterator_tag(),
|
|
category());
|
|
}
|
|
template <class IC> inline
|
|
void Assert_is_at_least_bidirectional_category( const IC& /*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
I_Has_to_be_at_least( std::bidirectional_iterator_tag(),
|
|
category());
|
|
}
|
|
template <class IC> inline
|
|
void Assert_is_at_least_random_access_category( const IC& /*ic*/) {
|
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
|
I_Has_to_be_at_least( std::random_access_iterator_tag(),
|
|
category());
|
|
}
|
|
|
|
template< class C> inline
|
|
bool I_is_empty_range( const C& c1, const C&, Circulator_tag){
|
|
return c1 == nullptr;
|
|
}
|
|
|
|
template< class I> inline
|
|
bool I_is_empty_range( const I& i1, const I& i2, Iterator_tag){
|
|
return i1 == i2;
|
|
}
|
|
|
|
template< class IC> inline
|
|
bool is_empty_range( const IC& ic1, const IC& ic2){
|
|
// is `true' if the range [`ic1, ic2') is empty, `false' otherwise.
|
|
// Precondition: `T' is either a circulator or an iterator type. The
|
|
// range [`ic1, ic2') is valid.
|
|
typedef typename Circulator_traits<IC>::category category;
|
|
return I_is_empty_range( ic1, ic2, category());
|
|
}
|
|
|
|
struct Circulator_or_iterator_tag {}; // any circulator or iterator.
|
|
|
|
inline
|
|
Circulator_or_iterator_tag
|
|
check_circulator_or_iterator( Circulator_tag ){
|
|
return Circulator_or_iterator_tag();
|
|
}
|
|
inline
|
|
Circulator_or_iterator_tag
|
|
check_circulator_or_iterator( Iterator_tag ){
|
|
return Circulator_or_iterator_tag();
|
|
}
|
|
|
|
template< class IC> inline
|
|
void Assert_circulator_or_iterator( const IC &){
|
|
typedef typename Circulator_traits<IC>::category category;
|
|
Assert_compile_time_tag(
|
|
Circulator_or_iterator_tag(),
|
|
check_circulator_or_iterator( category()));
|
|
}
|
|
|
|
#define CGAL_For_all( ic1, ic2) \
|
|
for ( bool _circ_loop_flag = ! ::CGAL::is_empty_range( ic1, ic2); \
|
|
_circ_loop_flag; \
|
|
_circ_loop_flag = ((++ic1) != (ic2)) )
|
|
|
|
#define CGAL_For_all_backwards( ic1, ic2) \
|
|
for ( bool _circ_loop_flag = ! ::CGAL::is_empty_range( ic1, ic2); \
|
|
_circ_loop_flag; \
|
|
_circ_loop_flag = ((ic1) != (--ic2)) )
|
|
|
|
|
|
|
|
template <class C> inline
|
|
typename C::size_type
|
|
I_min_circulator_size( const C& c) {
|
|
Assert_circulator(c);
|
|
Assert_random_access_category(c);
|
|
typedef typename C::size_type size_type;
|
|
size_type n = 0;
|
|
if ( c != nullptr) {
|
|
n = (c-1) - c + 1;
|
|
CGAL_assertion(n > 0);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
template <class C>
|
|
typename C::size_type
|
|
I_circulator_size( const C& c, Forward_circulator_tag) {
|
|
// Simply count.
|
|
if ( c == nullptr)
|
|
return 0;
|
|
typedef typename C::size_type size_type;
|
|
size_type n = 0;
|
|
C d = c;
|
|
do {
|
|
++n;
|
|
++d;
|
|
} while( c != d);
|
|
return n;
|
|
}
|
|
template <class C> inline
|
|
typename C::size_type
|
|
I_circulator_size( const C& c, Bidirectional_circulator_tag) {
|
|
return I_circulator_size( c, Forward_circulator_tag());
|
|
}
|
|
template <class C> inline
|
|
typename C::size_type
|
|
I_circulator_size( const C& c, Random_access_circulator_tag) {
|
|
return I_min_circulator_size( c.min_circulator());
|
|
}
|
|
|
|
template <class C> inline
|
|
typename C::size_type
|
|
circulator_size( const C& c) {
|
|
typedef typename std::iterator_traits<C>::iterator_category category;
|
|
return I_circulator_size( c,
|
|
category());
|
|
}
|
|
template <class C>
|
|
typename C::difference_type
|
|
I_circulator_distance( C c, const C& d, Forward_circulator_tag) {
|
|
// Simply count.
|
|
if ( c == nullptr)
|
|
return 0;
|
|
typedef typename C::difference_type difference_type;
|
|
difference_type n = 0;
|
|
do {
|
|
++n;
|
|
} while( ++c != d);
|
|
return n;
|
|
}
|
|
template <class C> inline
|
|
typename C::difference_type
|
|
I_circulator_distance( const C& c, const C& d,
|
|
Bidirectional_circulator_tag) {
|
|
return I_circulator_distance( c, d, Forward_circulator_tag());
|
|
}
|
|
template <class C> inline
|
|
typename C::difference_type
|
|
I_circulator_distance( const C& c, const C& d,
|
|
Random_access_circulator_tag) {
|
|
typedef typename C::difference_type difference_type;
|
|
typedef typename C::size_type size_type;
|
|
if ( d - c > 0)
|
|
return (d - c);
|
|
return difference_type( size_type( I_min_circulator_size(
|
|
c.min_circulator()))) - (c-d);
|
|
}
|
|
|
|
template <class C> inline
|
|
typename C::difference_type
|
|
circulator_distance( const C& c, const C& d) {
|
|
typedef typename std::iterator_traits<C>::iterator_category category;
|
|
return I_circulator_distance( c, d,
|
|
category());
|
|
}
|
|
template <class C> inline
|
|
typename std::iterator_traits<C>::difference_type
|
|
I_iterator_distance(const C& c1, const C& c2, Circulator_tag) {
|
|
return circulator_distance( c1, c2);
|
|
}
|
|
|
|
template <class I> inline
|
|
typename std::iterator_traits<I>::difference_type
|
|
I_iterator_distance(const I& i1, const I& i2, Iterator_tag) {
|
|
return std::distance( i1, i2);
|
|
}
|
|
|
|
template <class IC> inline
|
|
typename std::iterator_traits<IC>::difference_type
|
|
iterator_distance(const IC& ic1, const IC& ic2) {
|
|
typedef typename Circulator_traits<IC>::category category;
|
|
return I_iterator_distance( ic1, ic2, category());
|
|
}
|
|
template <class C> inline
|
|
C I_get_min_circulator( C c, Forward_circulator_tag) {
|
|
return c;
|
|
}
|
|
template <class C> inline
|
|
C I_get_min_circulator( C c, Bidirectional_circulator_tag) {
|
|
return c;
|
|
}
|
|
template <class C> inline
|
|
C I_get_min_circulator( C c, Random_access_circulator_tag) {
|
|
return c.min_circulator();
|
|
}
|
|
template <class C> inline
|
|
C get_min_circulator( C c) {
|
|
typedef std::iterator_traits<C> Traits;
|
|
typedef typename Traits::iterator_category Category;
|
|
return I_get_min_circulator( c, Category());
|
|
}
|
|
template<class I, class U> inline
|
|
I non_negative_mod(I n, U m) {
|
|
CGAL_precondition( m > 0);
|
|
#if (-1 % 3) > 0
|
|
n = n % m;
|
|
#else
|
|
if (n < 0)
|
|
n = m - 1 - (( - n - 1) % m) ;
|
|
else
|
|
n = n % m;
|
|
#endif
|
|
CGAL_postcondition( n >= 0);
|
|
return n;
|
|
}
|
|
|
|
template < class C, class Ref, class Ptr>
|
|
class Iterator_from_circulator {
|
|
private:
|
|
// The m_anchor is normalized to be a minimal circulator.
|
|
const C* m_anchor;
|
|
C current;
|
|
int m_winding;
|
|
|
|
typedef std::iterator_traits<C> I_traits;
|
|
typedef typename I_traits::iterator_category I_Iter_cat;
|
|
typedef I_Iterator_from_circulator_traits<I_Iter_cat> I__traits;
|
|
|
|
public:
|
|
//
|
|
// TYPES
|
|
|
|
typedef C Circulator;
|
|
typedef Iterator_from_circulator<C,Ref,Ptr> Self;
|
|
|
|
typedef typename I__traits::iterator_category iterator_category;
|
|
|
|
typedef typename C::value_type value_type;
|
|
typedef typename C::difference_type difference_type;
|
|
typedef typename C::size_type size_type;
|
|
typedef typename C::reference reference;
|
|
typedef typename C::pointer pointer;
|
|
|
|
//
|
|
// CREATION
|
|
|
|
Iterator_from_circulator() : m_anchor(0), m_winding(0) {}
|
|
|
|
Iterator_from_circulator( const C* circ, int n)
|
|
: m_anchor( circ), current( *circ), m_winding(n) {}
|
|
|
|
// Allow construction from Iterator_from_circulator with
|
|
// assignment compatible circulator CC:
|
|
template <class CC, class CREF, class CPTR>
|
|
Iterator_from_circulator(
|
|
const Iterator_from_circulator<CC,CREF,CPTR>& c)
|
|
: m_anchor( c.anchor()), current( c.current_circulator()),
|
|
m_winding(c.winding()) {}
|
|
|
|
//
|
|
// OPERATIONS
|
|
|
|
bool operator==( const Self& i) const {
|
|
CGAL_assertion( m_anchor == i.m_anchor); // same anchor?
|
|
return ( current == i.current) && ( m_winding == i.m_winding);
|
|
}
|
|
bool operator!=( const Self& i) const {
|
|
return !(*this == i);
|
|
}
|
|
Ref operator*() const {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
return Ref(*current);
|
|
}
|
|
Ptr operator->() const {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
return Ptr(current.operator->());
|
|
}
|
|
Self& operator++() {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
++current;
|
|
if ( current == *m_anchor)
|
|
++m_winding;
|
|
return *this;
|
|
}
|
|
Self operator++(int) {
|
|
Self tmp = *this;
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
Self& operator--() {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
if ( current == *m_anchor)
|
|
--m_winding;
|
|
--current;
|
|
return *this;
|
|
}
|
|
Self operator--(int) {
|
|
Self tmp = *this;
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
Self& operator+=( difference_type n) {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
if ( n < 0 && current == *m_anchor) // We are leaving the anchor.
|
|
--m_winding;
|
|
current += n;
|
|
if ( n > 0 && current == *m_anchor) // Back again at the anchor.
|
|
++m_winding;
|
|
return *this;
|
|
}
|
|
Self operator+( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += n;
|
|
}
|
|
Self& operator-=( difference_type n) {
|
|
return operator+=( -n);
|
|
}
|
|
Self operator-( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += -n;
|
|
}
|
|
difference_type operator-( const Self& i) const {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
CGAL_assertion( m_anchor == i.m_anchor);
|
|
if ( m_winding != i.m_winding) {
|
|
difference_type s = I_min_circulator_size( *m_anchor);
|
|
return (current - *m_anchor) - (i.current - *m_anchor)
|
|
+ s * (m_winding - i.m_winding);
|
|
}
|
|
return (current - *m_anchor) - (i.current - *m_anchor);
|
|
}
|
|
|
|
Ref operator[](difference_type n) const {
|
|
Self tmp = *this;
|
|
tmp += n;
|
|
return tmp.operator*();
|
|
}
|
|
bool operator<( const Self& i) const {
|
|
CGAL_assertion( m_anchor != nullptr);
|
|
CGAL_assertion( current != nullptr);
|
|
CGAL_assertion( m_anchor == i.m_anchor);
|
|
return ( (m_winding < i.m_winding)
|
|
|| ( (m_winding == i.m_winding)
|
|
&& (current - *m_anchor) < (i.current - *m_anchor)
|
|
)
|
|
);
|
|
}
|
|
bool operator> ( const Self& i) const { return i < *this; }
|
|
bool operator<=( const Self& i) const { return !(i < *this); }
|
|
bool operator>=( const Self& i) const { return !(*this < i); }
|
|
|
|
const C* anchor() const { return m_anchor;}
|
|
int winding() const { return m_winding;}
|
|
Circulator current_circulator() const { return current;}
|
|
};
|
|
|
|
template < class Dist, class C, class Ref, class Ptr>
|
|
Iterator_from_circulator<C,Ref,Ptr>
|
|
operator+( Dist n, const Iterator_from_circulator<C,Ref,Ptr>& circ) {
|
|
Iterator_from_circulator<C,Ref,Ptr> tmp = circ;
|
|
return tmp += n;
|
|
}
|
|
|
|
template < class C >
|
|
class Container_from_circulator {
|
|
private:
|
|
C anchor;
|
|
public:
|
|
//
|
|
// CREATION
|
|
|
|
Container_from_circulator() {}
|
|
// the resulting iterators will have a singular value.
|
|
|
|
Container_from_circulator(const C& c)
|
|
// The anchor is normalized to be a minimal circulator.
|
|
: anchor(get_min_circulator(c)) {}
|
|
// the resulting iterators will have a singular value if the
|
|
// circulator `c' is singular.
|
|
|
|
//
|
|
// TYPES
|
|
|
|
typedef C Circulator;
|
|
|
|
typedef typename C::value_type value_type;
|
|
typedef value_type& reference;
|
|
typedef const value_type& const_reference;
|
|
typedef value_type* pointer;
|
|
typedef const value_type* const_pointer;
|
|
typedef typename C::size_type size_type;
|
|
typedef typename C::difference_type difference_type;
|
|
|
|
typedef Iterator_from_circulator< C, reference, pointer>
|
|
iterator;
|
|
typedef Iterator_from_circulator< C, const_reference, const_pointer>
|
|
const_iterator;
|
|
//
|
|
// OPERATIONS
|
|
|
|
iterator begin() {
|
|
// the start iterator.
|
|
return iterator( &anchor, 0);
|
|
}
|
|
const_iterator begin() const {
|
|
// the start const iterator.
|
|
return const_iterator( &anchor, 0);
|
|
}
|
|
iterator end() {
|
|
// the past-the-end iterator.
|
|
return anchor == nullptr ? iterator( &anchor, 0)
|
|
: iterator( &anchor, 1);
|
|
}
|
|
const_iterator end() const {
|
|
// the past-the-end const iterator.
|
|
return anchor == nullptr ? const_iterator( &anchor, 0)
|
|
: const_iterator( &anchor, 1);
|
|
}
|
|
};
|
|
template <class Container>
|
|
class Circulator_from_container {
|
|
typedef Circulator_from_container<Container> Self;
|
|
typedef typename Container::iterator iterator;
|
|
typedef std::iterator_traits<iterator> iterator_traits;
|
|
public:
|
|
typedef typename iterator_traits::value_type value_type;
|
|
typedef typename iterator_traits::reference reference;
|
|
typedef typename iterator_traits::pointer pointer;
|
|
typedef typename iterator_traits::difference_type difference_type;
|
|
|
|
typedef typename I_Circulator_from_iterator_traits<
|
|
typename iterator_traits::iterator_category
|
|
>::iterator_category iterator_category;
|
|
|
|
typedef typename Container::size_type size_type;
|
|
private:
|
|
Container* ctnr;
|
|
iterator i;
|
|
|
|
public:
|
|
// CREATION
|
|
|
|
Circulator_from_container() : ctnr(nullptr) {}
|
|
Circulator_from_container( Container* c) : ctnr(c), i(c->begin()) {}
|
|
Circulator_from_container( Container* c, iterator j) : ctnr(c), i(j) {}
|
|
|
|
// OPERATIONS
|
|
|
|
bool operator==( std::nullptr_t p) const {
|
|
CGAL_USE(p);
|
|
CGAL_assertion( p == nullptr);
|
|
return (ctnr == nullptr) || (ctnr->begin() == ctnr->end());
|
|
}
|
|
bool operator!=( std::nullptr_t p) const { return !(*this == p); }
|
|
bool operator==( const Self& c) const { return i == c.i; }
|
|
bool operator!=( const Self& c) const { return !(*this == c); }
|
|
reference operator*() const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
return *i;
|
|
}
|
|
pointer operator->() const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
return i.operator->();
|
|
}
|
|
Self& operator++() {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
++i;
|
|
if ( i == ctnr->end())
|
|
i = ctnr->begin();
|
|
return *this;
|
|
}
|
|
Self operator++(int) {
|
|
Self tmp= *this;
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
Self& operator--() {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
if ( i == ctnr->begin())
|
|
i = ctnr->end();
|
|
--i;
|
|
return *this;
|
|
}
|
|
Self operator--(int) {
|
|
Self tmp = *this;
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
Self& operator+=( difference_type n) {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
typename Container::difference_type j = i - ctnr->begin();
|
|
typename Container::difference_type size = ctnr->size();
|
|
CGAL_assertion( j >= 0);
|
|
CGAL_assertion( size >= 0);
|
|
j = non_negative_mod( j + n, size);
|
|
CGAL_assertion( j >= 0);
|
|
CGAL_assertion( j < size);
|
|
i = ctnr->begin() + j;
|
|
return *this;
|
|
}
|
|
Self operator+( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += n;
|
|
}
|
|
Self& operator-=( difference_type n) { return operator+=( -n); }
|
|
Self operator-( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += -n;
|
|
}
|
|
difference_type operator-( const Self& c) const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( c.ctnr != nullptr);
|
|
return i - c.i;
|
|
}
|
|
reference operator[]( difference_type n) const {
|
|
Self tmp = *this;
|
|
tmp += n;
|
|
return *tmp;
|
|
}
|
|
iterator current_iterator() const { return i;}
|
|
Self min_circulator() const { return Self(ctnr); }
|
|
Container* container() const { return ctnr; }
|
|
};
|
|
|
|
template <class Ctnr>
|
|
inline
|
|
Circulator_from_container<Ctnr>
|
|
operator+( typename Circulator_from_container<Ctnr>::difference_type n,
|
|
const Circulator_from_container<Ctnr>& c) {
|
|
Circulator_from_container<Ctnr> tmp = c;
|
|
return tmp += n;
|
|
}
|
|
|
|
template < class Ctnr>
|
|
class Const_circulator_from_container {
|
|
public:
|
|
// TYPES
|
|
|
|
typedef Const_circulator_from_container<Ctnr> Self;
|
|
typedef Circulator_from_container<Ctnr> Mutable;
|
|
typedef Ctnr Container;
|
|
typedef typename Ctnr::const_iterator const_iterator;
|
|
typedef typename Ctnr::value_type value_type;
|
|
typedef typename Ctnr::const_reference reference;
|
|
typedef const value_type* pointer;
|
|
typedef typename Ctnr::size_type size_type;
|
|
typedef typename Ctnr::difference_type difference_type;
|
|
|
|
typedef std::iterator_traits<const_iterator> ITraits;
|
|
typedef typename ITraits::iterator_category Icategory;
|
|
typedef I_Circulator_from_iterator_traits<Icategory> CTraits;
|
|
typedef typename CTraits::iterator_category iterator_category;
|
|
|
|
private:
|
|
const Ctnr* ctnr;
|
|
const_iterator i;
|
|
|
|
public:
|
|
// CREATION
|
|
|
|
Const_circulator_from_container() : ctnr(nullptr) {}
|
|
Const_circulator_from_container( const Ctnr* c)
|
|
: ctnr(c), i(c->begin()) {}
|
|
Const_circulator_from_container( const Ctnr* c, const_iterator j)
|
|
: ctnr(c), i(j) {}
|
|
Const_circulator_from_container( const Mutable& c)
|
|
: ctnr( c.container()), i( c.current_iterator()) {}
|
|
|
|
// OPERATIONS
|
|
|
|
bool operator==( std::nullptr_t p) const {
|
|
CGAL_USE(p);
|
|
CGAL_assertion( p == nullptr);
|
|
return (ctnr == nullptr) || (ctnr->begin() == ctnr->end());
|
|
}
|
|
bool operator!=( std::nullptr_t p) const { return !(*this == p); }
|
|
bool operator==( const Self& c) const { return i == c.i; }
|
|
bool operator!=( const Self& c) const { return !(*this == c); }
|
|
reference operator*() const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
return *i;
|
|
}
|
|
pointer operator->() const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
return i.operator->();
|
|
}
|
|
Self& operator++() {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
++i;
|
|
if ( i == ctnr->end())
|
|
i = ctnr->begin();
|
|
return *this;
|
|
}
|
|
Self operator++(int) {
|
|
Self tmp= *this;
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
Self& operator--() {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
if ( i == ctnr->begin())
|
|
i = ctnr->end();
|
|
--i;
|
|
return *this;
|
|
}
|
|
Self operator--(int) {
|
|
Self tmp = *this;
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
Self& operator+=( difference_type n) {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( i != ctnr->end());
|
|
typename Ctnr::difference_type j = i - ctnr->begin();
|
|
typename Ctnr::difference_type size = ctnr->size();
|
|
CGAL_assertion( j >= 0);
|
|
CGAL_assertion( size >= 0);
|
|
j = non_negative_mod( j + n, size);
|
|
CGAL_assertion( j >= 0);
|
|
CGAL_assertion( j < size);
|
|
i = ctnr->begin() + j;
|
|
return *this;
|
|
}
|
|
Self operator+( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += n;
|
|
}
|
|
Self& operator-=( difference_type n) { return operator+=( -n); }
|
|
Self operator-( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += -n;
|
|
}
|
|
difference_type operator-( const Self& c) const {
|
|
CGAL_assertion( ctnr != nullptr);
|
|
CGAL_assertion( c.ctnr != nullptr);
|
|
return i - c.i;
|
|
}
|
|
reference operator[]( difference_type n) const {
|
|
Self tmp = *this;
|
|
tmp += n;
|
|
return *tmp;
|
|
}
|
|
const_iterator current_iterator() const { return i;}
|
|
Self min_circulator() const { return Self(ctnr); }
|
|
const Ctnr* container() const { return ctnr; }
|
|
};
|
|
|
|
template <class Ctnr>
|
|
inline
|
|
Const_circulator_from_container<Ctnr>
|
|
operator+( typename Const_circulator_from_container<Ctnr>::difference_type n,
|
|
const Const_circulator_from_container<Ctnr>& c) {
|
|
Const_circulator_from_container<Ctnr> tmp = c;
|
|
return tmp += n;
|
|
}
|
|
|
|
|
|
// Note: Tt, Ss, and Dd are here for backwards compatibility, they are
|
|
// not used.
|
|
template < class I, class Tt = int, class Ss = int, class Dd = int>
|
|
class Circulator_from_iterator {
|
|
public:
|
|
// TYPES
|
|
|
|
typedef Circulator_from_iterator<I,Tt,Ss,Dd> Self;
|
|
typedef I iterator;
|
|
typedef std::iterator_traits<iterator> Traits;
|
|
|
|
typedef typename Traits::value_type value_type;
|
|
typedef std::size_t size_type;
|
|
typedef typename Traits::difference_type difference_type;
|
|
typedef typename Traits::reference reference;
|
|
typedef typename Traits::pointer pointer;
|
|
|
|
typedef typename Traits::iterator_category Icategory;
|
|
typedef I_Circulator_from_iterator_traits<Icategory> CTraits;
|
|
typedef typename CTraits::iterator_category iterator_category;
|
|
|
|
private:
|
|
I m_begin;
|
|
I m_end;
|
|
I current;
|
|
bool empty;
|
|
|
|
// The following static iterator is needed so that we have a value
|
|
// that can be uniquely compared (the default constructed one can be
|
|
// different each time).
|
|
//static I null_iterator;
|
|
|
|
public:
|
|
// CREATION
|
|
|
|
Circulator_from_iterator() : m_begin(),
|
|
m_end(),
|
|
current(),
|
|
empty( true)
|
|
{}
|
|
|
|
Circulator_from_iterator( const I& bgn, const I& end)
|
|
: m_begin(bgn), m_end(end), current(bgn), empty(bgn==end) {}
|
|
|
|
Circulator_from_iterator( const I& bgn, const I& end, const I& cur)
|
|
: m_begin(bgn), m_end(end), current(cur), empty(bgn==end) {}
|
|
|
|
Circulator_from_iterator( const Self& c, const I& cur)
|
|
: m_begin( c.m_begin), m_end( c.m_end), current(cur), empty(c.empty) {}
|
|
|
|
|
|
template <class II, class A1, class A2, class A3>
|
|
// Allow construction from Circulator_from_iterator with
|
|
// assignment compatible iterator II:
|
|
Circulator_from_iterator(
|
|
const Circulator_from_iterator<II,A1,A2,A3>& ii)
|
|
: m_begin( ii.begin()), m_end( ii.end()),
|
|
current(ii.current_iterator()), empty(ii.begin()==ii.end()) {}
|
|
|
|
//
|
|
// OPERATIONS
|
|
|
|
bool operator==( std::nullptr_t p) const {
|
|
CGAL_USE(p);
|
|
CGAL_assertion( p == nullptr);
|
|
return empty;
|
|
}
|
|
bool operator!=( std::nullptr_t p) const { return !(*this == p); }
|
|
bool operator==( const Self& c) const { return current == c.current;}
|
|
bool operator!=( const Self& c) const { return !(*this == c); }
|
|
reference operator*() const {
|
|
CGAL_assertion( current != m_end);
|
|
return *current;
|
|
}
|
|
pointer operator->() const {
|
|
CGAL_assertion( current != m_end);
|
|
return &(*current);
|
|
}
|
|
Self& operator++() {
|
|
CGAL_assertion( current != m_end);
|
|
++current;
|
|
if ( current == m_end)
|
|
current = m_begin;
|
|
return *this;
|
|
}
|
|
Self operator++(int) {
|
|
Self tmp= *this;
|
|
++*this;
|
|
return tmp;
|
|
}
|
|
Self& operator--() {
|
|
CGAL_assertion( current != m_end);
|
|
if ( current == m_begin)
|
|
current = m_end;
|
|
--current;
|
|
return *this;
|
|
}
|
|
Self operator--(int) {
|
|
Self tmp = *this;
|
|
--*this;
|
|
return tmp;
|
|
}
|
|
Self& operator+=( difference_type n) {
|
|
CGAL_assertion( current != m_end);
|
|
difference_type i = current - m_begin;
|
|
difference_type size = m_end - m_begin;
|
|
CGAL_assertion( i >= 0);
|
|
CGAL_assertion( size >= 0);
|
|
i = non_negative_mod( i + n, size);
|
|
CGAL_assertion( i >= 0);
|
|
CGAL_assertion( i < size);
|
|
current = m_begin + i;
|
|
return *this;
|
|
}
|
|
Self operator+( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += n;
|
|
}
|
|
Self& operator-=( difference_type n) { return operator+=( -n); }
|
|
Self operator-( difference_type n) const {
|
|
Self tmp = *this;
|
|
return tmp += -n;
|
|
}
|
|
difference_type operator-( const Self& i) const {
|
|
CGAL_assertion((m_begin == i.m_begin) && (m_end == i.m_end));
|
|
return current - i.current;
|
|
}
|
|
reference operator[](difference_type n) const {
|
|
Self tmp = *this;
|
|
tmp += n;
|
|
return tmp.operator*();
|
|
}
|
|
iterator begin() const { return m_begin;}
|
|
iterator end() const { return m_end;}
|
|
iterator current_iterator() const { return current;}
|
|
Self min_circulator() const { return Self( m_begin, m_end); }
|
|
};
|
|
|
|
//template < class I, class T, class Size, class Dist>
|
|
//I Circulator_from_iterator< I, T, Size, Dist>::null_iterator = I();
|
|
|
|
template < class D, class I, class T, class Size, class Dist> inline
|
|
Circulator_from_iterator< I, T, Size, Dist>
|
|
operator+( D n, const
|
|
Circulator_from_iterator< I, T, Size, Dist>& circ) {
|
|
Circulator_from_iterator< I, T, Size, Dist>
|
|
tmp = circ;
|
|
return tmp += Dist(n);
|
|
}
|
|
|
|
} //namespace CGAL
|
|
|
|
#endif // CGAL_CIRCULATOR_H //
|