Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __ADD_EDGE_VISITORS_HPP__
#define __ADD_EDGE_VISITORS_HPP__
#include <boost/property_map/property_map.hpp>
namespace boost
{
struct default_add_edge_visitor
{
template <typename Graph, typename Vertex>
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
{
add_edge(u,v,g);
}
};
template<typename EdgeIndexMap>
struct edge_index_update_visitor
{
typedef typename
property_traits<EdgeIndexMap>::value_type edge_index_value_t;
edge_index_update_visitor(EdgeIndexMap em,
edge_index_value_t next_index_available
) :
m_em(em),
m_next_index(next_index_available)
{}
template <typename Graph, typename Vertex>
void visit_vertex_pair(Vertex u, Vertex v, Graph& g)
{
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
std::pair<edge_t, bool> return_value = add_edge(u,v,g);
if (return_value.second)
put( m_em, return_value.first, m_next_index++);
}
private:
EdgeIndexMap m_em;
edge_index_value_t m_next_index;
};
} // namespace boost
#endif //__ADD_EDGE_VISITORS_HPP__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,144 @@
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __BUCKET_SORT_HPP__
#define __BUCKET_SORT_HPP__
#include <vector>
#include <algorithm>
#include <boost/property_map/property_map.hpp>
namespace boost
{
template <typename ItemToRankMap>
struct rank_comparison
{
rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {}
template <typename Item>
bool operator() (Item x, Item y) const
{
return get(itrm, x) < get(itrm, y);
}
private:
ItemToRankMap itrm;
};
template <typename TupleType,
int N,
typename PropertyMapWrapper = identity_property_map>
struct property_map_tuple_adaptor :
public put_get_helper< typename PropertyMapWrapper::value_type,
property_map_tuple_adaptor
<TupleType, N, PropertyMapWrapper>
>
{
typedef typename PropertyMapWrapper::reference reference;
typedef typename PropertyMapWrapper::value_type value_type;
typedef TupleType key_type;
typedef readable_property_map_tag category;
property_map_tuple_adaptor() {}
property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) :
m_wrapper_map(wrapper_map)
{}
inline value_type operator[](const key_type& x) const
{
return get(m_wrapper_map, get<n>(x));
}
static const int n = N;
PropertyMapWrapper m_wrapper_map;
};
// This function sorts a sequence of n items by their ranks in linear time,
// given that all ranks are in the range [0, range). This sort is stable.
template <typename ForwardIterator,
typename ItemToRankMap,
typename SizeType>
void bucket_sort(ForwardIterator begin,
ForwardIterator end,
ItemToRankMap rank,
SizeType range = 0)
{
#ifdef BOOST_GRAPH_PREFER_STD_LIB
std::stable_sort(begin, end, rank_comparison<ItemToRankMap>(rank));
#else
typedef std::vector
< typename boost::property_traits<ItemToRankMap>::key_type >
vector_of_values_t;
typedef std::vector< vector_of_values_t > vector_of_vectors_t;
if (!range)
{
rank_comparison<ItemToRankMap> cmp(rank);
ForwardIterator max_by_rank = std::max_element(begin, end, cmp);
if (max_by_rank == end)
return;
range = get(rank, *max_by_rank) + 1;
}
vector_of_vectors_t temp_values(range);
for(ForwardIterator itr = begin; itr != end; ++itr)
{
temp_values[get(rank, *itr)].push_back(*itr);
}
ForwardIterator orig_seq_itr = begin;
typename vector_of_vectors_t::iterator itr_end = temp_values.end();
for(typename vector_of_vectors_t::iterator itr = temp_values.begin();
itr != itr_end; ++itr
)
{
typename vector_of_values_t::iterator jtr_end = itr->end();
for(typename vector_of_values_t::iterator jtr = itr->begin();
jtr != jtr_end; ++jtr
)
{
*orig_seq_itr = *jtr;
++orig_seq_itr;
}
}
#endif
}
template <typename ForwardIterator, typename ItemToRankMap>
void bucket_sort(ForwardIterator begin,
ForwardIterator end,
ItemToRankMap rank)
{
bucket_sort(begin, end, rank, 0);
}
template <typename ForwardIterator>
void bucket_sort(ForwardIterator begin,
ForwardIterator end
)
{
bucket_sort(begin, end, identity_property_map());
}
} //namespace boost
#endif //__BUCKET_SORT_HPP__

View File

@@ -0,0 +1,497 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __FACE_HANDLES_HPP__
#define __FACE_HANDLES_HPP__
#include <list>
#include <boost/graph/graph_traits.hpp>
#include <boost/shared_ptr.hpp>
// A "face handle" is an optimization meant to serve two purposes in
// the implementation of the Boyer-Myrvold planarity test: (1) it holds
// the partial planar embedding of a particular vertex as it's being
// constructed, and (2) it allows for efficient traversal around the
// outer face of the partial embedding at that particular vertex. A face
// handle is lightweight, just a shared pointer to the actual implementation,
// since it is passed around/copied liberally in the algorithm. It consists
// of an "anchor" (the actual vertex it's associated with) as well as a
// sequence of edges. The functions first_vertex/second_vertex and
// first_edge/second_edge allow fast access to the beginning and end of the
// stored sequence, which allows one to traverse the outer face of the partial
// planar embedding as it's being created.
//
// There are some policies below that define the contents of the face handles:
// in the case no embedding is needed (for example, if one just wants to use
// the Boyer-Myrvold algorithm as a true/false test for planarity, the
// no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
// either std_list (which uses as std::list) or recursive_lazy_list can be
// passed as this policy. recursive_lazy_list has the best theoretical
// performance (O(n) for a sequence of interleaved concatenations and reversals
// of the underlying list), but I've noticed little difference between std_list
// and recursive_lazy_list in my tests, even though using std_list changes
// the worst-case complexity of the planarity test to O(n^2)
//
// Another policy is StoreOldHandlesPolicy, which specifies whether or not
// to keep a record of the previous first/second vertex/edge - this is needed
// if a Kuratowski subgraph needs to be isolated.
namespace boost { namespace graph { namespace detail {
//face handle policies
//EmbeddingStorage policy
struct store_embedding {};
struct recursive_lazy_list : public store_embedding {};
struct std_list : public store_embedding {};
struct no_embedding {};
//StoreOldHandlesPolicy
struct store_old_handles {};
struct no_old_handles {};
template<typename DataType>
struct lazy_list_node
{
typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
lazy_list_node(const DataType& data) :
m_reversed(false),
m_data(data),
m_has_data(true)
{}
lazy_list_node(ptr_t left_child, ptr_t right_child) :
m_reversed(false),
m_has_data(false),
m_left_child(left_child),
m_right_child(right_child)
{}
bool m_reversed;
DataType m_data;
bool m_has_data;
shared_ptr<lazy_list_node> m_left_child;
shared_ptr<lazy_list_node> m_right_child;
};
template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
struct old_handles_storage;
template <typename Vertex, typename Edge>
struct old_handles_storage<store_old_handles, Vertex, Edge>
{
Vertex first_vertex;
Vertex second_vertex;
Edge first_edge;
Edge second_edge;
};
template <typename Vertex, typename Edge>
struct old_handles_storage<no_old_handles, Vertex, Edge>
{};
template <typename StoreEmbeddingPolicy, typename Edge>
struct edge_list_storage;
template <typename Edge>
struct edge_list_storage<no_embedding, Edge>
{
typedef void type;
void push_back(Edge) {}
void push_front(Edge) {}
void reverse() {}
void concat_front(edge_list_storage<no_embedding,Edge>) {}
void concat_back(edge_list_storage<no_embedding,Edge>) {}
template <typename OutputIterator>
void get_list(OutputIterator) {}
};
template <typename Edge>
struct edge_list_storage<recursive_lazy_list, Edge>
{
typedef lazy_list_node<Edge> node_type;
typedef shared_ptr< node_type > type;
type value;
void push_back(Edge e)
{
type new_node(new node_type(e));
value = type(new node_type(value, new_node));
}
void push_front(Edge e)
{
type new_node(new node_type(e));
value = type(new node_type(new_node, value));
}
void reverse()
{
value->m_reversed = !value->m_reversed;
}
void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
{
value = type(new node_type(other.value, value));
}
void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
{
value = type(new node_type(value, other.value));
}
template <typename OutputIterator>
void get_list(OutputIterator out)
{
get_list_helper(out, value);
}
private:
template <typename OutputIterator>
void get_list_helper(OutputIterator o_itr,
type root,
bool flipped = false
)
{
if (!root)
return;
if (root->m_has_data)
*o_itr = root->m_data;
if ((flipped && !root->m_reversed) ||
(!flipped && root->m_reversed)
)
{
get_list_helper(o_itr, root->m_right_child, true);
get_list_helper(o_itr, root->m_left_child, true);
}
else
{
get_list_helper(o_itr, root->m_left_child, false);
get_list_helper(o_itr, root->m_right_child, false);
}
}
};
template <typename Edge>
struct edge_list_storage<std_list, Edge>
{
typedef std::list<Edge> type;
type value;
void push_back(Edge e)
{
value.push_back(e);
}
void push_front(Edge e)
{
value.push_front(e);
}
void reverse()
{
value.reverse();
}
void concat_front(edge_list_storage<std_list,Edge> other)
{
value.splice(value.begin(), other.value);
}
void concat_back(edge_list_storage<std_list, Edge> other)
{
value.splice(value.end(), other.value);
}
template <typename OutputIterator>
void get_list(OutputIterator out)
{
std::copy(value.begin(), value.end(), out);
}
};
template<typename Graph,
typename StoreOldHandlesPolicy,
typename StoreEmbeddingPolicy
>
struct face_handle_impl
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
edge_list_storage_t;
face_handle_impl() :
cached_first_vertex(graph_traits<Graph>::null_vertex()),
cached_second_vertex(graph_traits<Graph>::null_vertex()),
true_first_vertex(graph_traits<Graph>::null_vertex()),
true_second_vertex(graph_traits<Graph>::null_vertex()),
anchor(graph_traits<Graph>::null_vertex())
{
initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
}
void initialize_old_vertices_dispatch(store_old_handles)
{
old_handles.first_vertex = graph_traits<Graph>::null_vertex();
old_handles.second_vertex = graph_traits<Graph>::null_vertex();
}
void initialize_old_vertices_dispatch(no_old_handles) {}
vertex_t cached_first_vertex;
vertex_t cached_second_vertex;
vertex_t true_first_vertex;
vertex_t true_second_vertex;
vertex_t anchor;
edge_t cached_first_edge;
edge_t cached_second_edge;
edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
};
template <typename Graph,
typename StoreOldHandlesPolicy = store_old_handles,
typename StoreEmbeddingPolicy = recursive_lazy_list
>
class face_handle
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef face_handle_impl
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
typedef face_handle
<Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
pimpl(new impl_t())
{
pimpl->anchor = anchor;
}
face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
pimpl(new impl_t())
{
vertex_t s(source(initial_edge,g));
vertex_t t(target(initial_edge,g));
vertex_t other_vertex = s == anchor ? t : s;
pimpl->anchor = anchor;
pimpl->cached_first_edge = initial_edge;
pimpl->cached_second_edge = initial_edge;
pimpl->cached_first_vertex = other_vertex;
pimpl->cached_second_vertex = other_vertex;
pimpl->true_first_vertex = other_vertex;
pimpl->true_second_vertex = other_vertex;
pimpl->edge_list.push_back(initial_edge);
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
}
//default copy construction, assignment okay.
void push_first(edge_t e, const Graph& g)
{
pimpl->edge_list.push_front(e);
pimpl->cached_first_vertex = pimpl->true_first_vertex =
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
pimpl->cached_first_edge = e;
}
void push_second(edge_t e, const Graph& g)
{
pimpl->edge_list.push_back(e);
pimpl->cached_second_vertex = pimpl->true_second_vertex =
source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
pimpl->cached_second_edge = e;
}
inline void store_old_face_handles()
{
store_old_face_handles_dispatch(StoreOldHandlesPolicy());
}
inline vertex_t first_vertex() const
{
return pimpl->cached_first_vertex;
}
inline vertex_t second_vertex() const
{
return pimpl->cached_second_vertex;
}
inline vertex_t true_first_vertex() const
{
return pimpl->true_first_vertex;
}
inline vertex_t true_second_vertex() const
{
return pimpl->true_second_vertex;
}
inline vertex_t old_first_vertex() const
{
return pimpl->old_handles.first_vertex;
}
inline vertex_t old_second_vertex() const
{
return pimpl->old_handles.second_vertex;
}
inline edge_t old_first_edge() const
{
return pimpl->old_handles.first_edge;
}
inline edge_t old_second_edge() const
{
return pimpl->old_handles.second_edge;
}
inline edge_t first_edge() const
{
return pimpl->cached_first_edge;
}
inline edge_t second_edge() const
{
return pimpl->cached_second_edge;
}
inline vertex_t get_anchor() const
{
return pimpl->anchor;
}
void glue_first_to_second
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
{
pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
}
void glue_second_to_first
(face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
{
pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
}
void flip()
{
pimpl->edge_list.reverse();
std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
}
template <typename OutputIterator>
void get_list(OutputIterator o_itr)
{
pimpl->edge_list.get_list(o_itr);
}
void reset_vertex_cache()
{
pimpl->cached_first_vertex = pimpl->true_first_vertex;
pimpl->cached_second_vertex = pimpl->true_second_vertex;
}
inline void set_first_vertex(vertex_t v)
{
pimpl->cached_first_vertex = v;
}
inline void set_second_vertex(vertex_t v)
{
pimpl->cached_second_vertex = v;
}
private:
void store_old_face_handles_dispatch(store_old_handles)
{
pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
pimpl->old_handles.first_edge = pimpl->cached_first_edge;
pimpl->old_handles.second_edge = pimpl->cached_second_edge;
}
void store_old_face_handles_dispatch(no_old_handles) {}
boost::shared_ptr<impl_t> pimpl;
};
} /* namespace detail */ } /* namespace graph */ } /* namespace boost */
#endif //__FACE_HANDLES_HPP__

View File

@@ -0,0 +1,375 @@
//=======================================================================
// Copyright (c) Aaron Windsor 2007
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef __FACE_ITERATORS_HPP__
#define __FACE_ITERATORS_HPP__
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/graph/graph_traits.hpp>
namespace boost
{
//tags for defining traversal properties
//VisitorType
struct lead_visitor {};
struct follow_visitor {};
//TraversalType
struct single_side {};
struct both_sides {};
//TraversalSubType
struct first_side {}; //for single_side
struct second_side {}; //for single_side
struct alternating {}; //for both_sides
//Time
struct current_iteration {};
struct previous_iteration {};
// Why TraversalType AND TraversalSubType? TraversalSubType is a function
// template parameter passed in to the constructor of the face iterator,
// whereas TraversalType is a class template parameter. This lets us decide
// at runtime whether to move along the first or second side of a bicomp (by
// assigning a face_iterator that has been constructed with TraversalSubType
// = first_side or second_side to a face_iterator variable) without any of
// the virtual function overhead that comes with implementing this
// functionality as a more structured form of type erasure. It also allows
// a single face_iterator to be the end iterator of two iterators traversing
// both sides of a bicomp.
//ValueType is either graph_traits<Graph>::vertex_descriptor
//or graph_traits<Graph>::edge_descriptor
//forward declaration (defining defaults)
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename BicompSideToTraverse = single_side,
typename VisitorType = lead_visitor,
typename Time = current_iteration
>
class face_iterator;
template <typename Graph, bool StoreEdge>
struct edge_storage
{};
template <typename Graph>
struct edge_storage <Graph, true>
{
typename graph_traits<Graph>::edge_descriptor value;
};
//specialization for TraversalType = traverse_vertices
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename TraversalType,
typename VisitorType,
typename Time
>
class face_iterator
: public boost::iterator_facade < face_iterator<Graph,
FaceHandlesMap,
ValueType,
TraversalType,
VisitorType,
Time
>,
ValueType,
boost::forward_traversal_tag,
ValueType
>
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
typedef face_iterator
<Graph,FaceHandlesMap,ValueType,TraversalType,VisitorType,Time> self;
typedef typename FaceHandlesMap::value_type face_handle_t;
face_iterator() :
m_lead(graph_traits<Graph>::null_vertex()),
m_follow(graph_traits<Graph>::null_vertex())
{}
template <typename TraversalSubType>
face_iterator(face_handle_t anchor_handle,
FaceHandlesMap face_handles,
TraversalSubType traversal_type):
m_follow(anchor_handle.get_anchor()),
m_face_handles(face_handles)
{
set_lead_dispatch(anchor_handle, traversal_type);
}
template <typename TraversalSubType>
face_iterator(vertex_t anchor,
FaceHandlesMap face_handles,
TraversalSubType traversal_type):
m_follow(anchor),
m_face_handles(face_handles)
{
set_lead_dispatch(m_face_handles[anchor], traversal_type);
}
private:
friend class boost::iterator_core_access;
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
current_iteration
)
{
return anchor_handle.first_vertex();
}
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
current_iteration
)
{
return anchor_handle.second_vertex();
}
inline vertex_t get_first_vertex(face_handle_t anchor_handle,
previous_iteration
)
{
return anchor_handle.old_first_vertex();
}
inline vertex_t get_second_vertex(face_handle_t anchor_handle,
previous_iteration
)
{
return anchor_handle.old_second_vertex();
}
inline void set_lead_dispatch(face_handle_t anchor_handle, first_side)
{
m_lead = get_first_vertex(anchor_handle, Time());
set_edge_to_first_dispatch(anchor_handle, ValueType(), Time());
}
inline void set_lead_dispatch(face_handle_t anchor_handle, second_side)
{
m_lead = get_second_vertex(anchor_handle, Time());
set_edge_to_second_dispatch(anchor_handle, ValueType(), Time());
}
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
edge_t,
current_iteration
)
{
m_edge.value = anchor_handle.first_edge();
}
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
edge_t,
current_iteration
)
{
m_edge.value = anchor_handle.second_edge();
}
inline void set_edge_to_first_dispatch(face_handle_t anchor_handle,
edge_t,
previous_iteration
)
{
m_edge.value = anchor_handle.old_first_edge();
}
inline void set_edge_to_second_dispatch(face_handle_t anchor_handle,
edge_t,
previous_iteration
)
{
m_edge.value = anchor_handle.old_second_edge();
}
template<typename T>
inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T)
{}
template<typename T>
inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T)
{}
void increment()
{
face_handle_t curr_face_handle(m_face_handles[m_lead]);
vertex_t first = get_first_vertex(curr_face_handle, Time());
vertex_t second = get_second_vertex(curr_face_handle, Time());
if (first == m_follow)
{
m_follow = m_lead;
set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time());
m_lead = second;
}
else if (second == m_follow)
{
m_follow = m_lead;
set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time());
m_lead = first;
}
else
m_lead = m_follow = graph_traits<Graph>::null_vertex();
}
bool equal(self const& other) const
{
return m_lead == other.m_lead && m_follow == other.m_follow;
}
ValueType dereference() const
{
return dereference_dispatch(VisitorType(), ValueType());
}
inline ValueType dereference_dispatch(lead_visitor, vertex_t) const
{ return m_lead; }
inline ValueType dereference_dispatch(follow_visitor, vertex_t) const
{ return m_follow; }
inline ValueType dereference_dispatch(lead_visitor, edge_t) const
{ return m_edge.value; }
inline ValueType dereference_dispatch(follow_visitor, edge_t) const
{ return m_edge.value; }
vertex_t m_lead;
vertex_t m_follow;
edge_storage<Graph, boost::is_same<ValueType, edge_t>::value > m_edge;
FaceHandlesMap m_face_handles;
};
template <typename Graph,
typename FaceHandlesMap,
typename ValueType,
typename VisitorType,
typename Time
>
class face_iterator
<Graph, FaceHandlesMap, ValueType, both_sides, VisitorType, Time>
: public boost::iterator_facade< face_iterator<Graph,
FaceHandlesMap,
ValueType,
both_sides,
VisitorType,
Time>,
ValueType,
boost::forward_traversal_tag,
ValueType >
{
public:
typedef face_iterator
<Graph,FaceHandlesMap,ValueType,both_sides,VisitorType,Time> self;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef typename FaceHandlesMap::value_type face_handle_t;
face_iterator() {}
face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles):
first_itr(anchor_handle, face_handles, first_side()),
second_itr(anchor_handle, face_handles, second_side()),
first_is_active(true),
first_increment(true)
{}
face_iterator(vertex_t anchor, FaceHandlesMap face_handles):
first_itr(face_handles[anchor], face_handles, first_side()),
second_itr(face_handles[anchor], face_handles, second_side()),
first_is_active(true),
first_increment(true)
{}
private:
friend class boost::iterator_core_access;
typedef face_iterator
<Graph, FaceHandlesMap, ValueType, single_side, follow_visitor, Time>
inner_itr_t;
void increment()
{
if (first_increment)
{
++first_itr;
++second_itr;
first_increment = false;
}
else if (first_is_active)
++first_itr;
else
++second_itr;
first_is_active = !first_is_active;
}
bool equal(self const& other) const
{
//Want this iterator to be equal to the "end" iterator when at least
//one of the iterators has reached the root of the current bicomp.
//This isn't ideal, but it works.
return (first_itr == other.first_itr || second_itr == other.second_itr);
}
ValueType dereference() const
{
return first_is_active ? *first_itr : *second_itr;
}
inner_itr_t first_itr;
inner_itr_t second_itr;
inner_itr_t face_end;
bool first_is_active;
bool first_increment;
};
} /* namespace boost */
#endif //__FACE_ITERATORS_HPP__