mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-13 10:48:08 +00:00
Added thirdparty: boost library
This commit is contained in:
+54
@@ -0,0 +1,54 @@
|
||||
//=======================================================================
|
||||
// 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__
|
||||
+1813
File diff suppressed because it is too large
Load Diff
+118
@@ -0,0 +1,118 @@
|
||||
//=======================================================================
|
||||
// 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__
|
||||
+453
@@ -0,0 +1,453 @@
|
||||
//=======================================================================
|
||||
// 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__
|
||||
+332
@@ -0,0 +1,332 @@
|
||||
//=======================================================================
|
||||
// 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__
|
||||
Reference in New Issue
Block a user