You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
375 lines
11 KiB
375 lines
11 KiB
//======================================================================= |
|
// 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__
|
|
|