1 //=======================================================================
2 // Copyright (c) Aaron Windsor 2007
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
8 
9 #ifndef __FACE_ITERATORS_HPP__
10 #define __FACE_ITERATORS_HPP__
11 
12 #include <boost/iterator/iterator_facade.hpp>
13 #include <boost/mpl/bool.hpp>
14 #include <boost/graph/graph_traits.hpp>
15 
16 namespace boost
17 {
18 
19 // tags for defining traversal properties
20 
21 // VisitorType
22 struct lead_visitor
23 {
24 };
25 struct follow_visitor
26 {
27 };
28 
29 // TraversalType
30 struct single_side
31 {
32 };
33 struct both_sides
34 {
35 };
36 
37 // TraversalSubType
38 struct first_side
39 {
40 }; // for single_side
41 struct second_side
42 {
43 }; // for single_side
44 struct alternating
45 {
46 }; // for both_sides
47 
48 // Time
49 struct current_iteration
50 {
51 };
52 struct previous_iteration
53 {
54 };
55 
56 // Why TraversalType AND TraversalSubType? TraversalSubType is a function
57 // template parameter passed in to the constructor of the face iterator,
58 // whereas TraversalType is a class template parameter. This lets us decide
59 // at runtime whether to move along the first or second side of a bicomp (by
60 // assigning a face_iterator that has been constructed with TraversalSubType
61 // = first_side or second_side to a face_iterator variable) without any of
62 // the virtual function overhead that comes with implementing this
63 // functionality as a more structured form of type erasure. It also allows
64 // a single face_iterator to be the end iterator of two iterators traversing
65 // both sides of a bicomp.
66 
67 // ValueType is either graph_traits<Graph>::vertex_descriptor
68 // or graph_traits<Graph>::edge_descriptor
69 
70 // forward declaration (defining defaults)
71 template < typename Graph, typename FaceHandlesMap, typename ValueType,
72     typename BicompSideToTraverse = single_side,
73     typename VisitorType = lead_visitor, typename Time = current_iteration >
74 class face_iterator;
75 
76 template < typename Graph, bool StoreEdge > struct edge_storage
77 {
78 };
79 
80 template < typename Graph > struct edge_storage< Graph, true >
81 {
82     typename graph_traits< Graph >::edge_descriptor value;
83 };
84 
85 // specialization for TraversalType = traverse_vertices
86 template < typename Graph, typename FaceHandlesMap, typename ValueType,
87     typename TraversalType, typename VisitorType, typename Time >
88 
89 class face_iterator : public boost::iterator_facade<
90                           face_iterator< Graph, FaceHandlesMap, ValueType,
91                               TraversalType, VisitorType, Time >,
92                           ValueType, boost::forward_traversal_tag, ValueType >
93 {
94 public:
95     typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
96     typedef typename graph_traits< Graph >::edge_descriptor edge_t;
97     typedef face_iterator< Graph, FaceHandlesMap, ValueType, TraversalType,
98         VisitorType, Time >
99         self;
100     typedef typename FaceHandlesMap::value_type face_handle_t;
101 
face_iterator()102     face_iterator()
103     : m_lead(graph_traits< Graph >::null_vertex())
104     , m_follow(graph_traits< Graph >::null_vertex())
105     {
106     }
107 
108     template < typename TraversalSubType >
face_iterator(face_handle_t anchor_handle,FaceHandlesMap face_handles,TraversalSubType traversal_type)109     face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles,
110         TraversalSubType traversal_type)
111     : m_follow(anchor_handle.get_anchor()), m_face_handles(face_handles)
112     {
113         set_lead_dispatch(anchor_handle, traversal_type);
114     }
115 
116     template < typename TraversalSubType >
face_iterator(vertex_t anchor,FaceHandlesMap face_handles,TraversalSubType traversal_type)117     face_iterator(vertex_t anchor, FaceHandlesMap face_handles,
118         TraversalSubType traversal_type)
119     : m_follow(anchor), m_face_handles(face_handles)
120     {
121         set_lead_dispatch(m_face_handles[anchor], traversal_type);
122     }
123 
124 private:
125     friend class boost::iterator_core_access;
126 
get_first_vertex(face_handle_t anchor_handle,current_iteration)127     inline vertex_t get_first_vertex(
128         face_handle_t anchor_handle, current_iteration)
129     {
130         return anchor_handle.first_vertex();
131     }
132 
get_second_vertex(face_handle_t anchor_handle,current_iteration)133     inline vertex_t get_second_vertex(
134         face_handle_t anchor_handle, current_iteration)
135     {
136         return anchor_handle.second_vertex();
137     }
138 
get_first_vertex(face_handle_t anchor_handle,previous_iteration)139     inline vertex_t get_first_vertex(
140         face_handle_t anchor_handle, previous_iteration)
141     {
142         return anchor_handle.old_first_vertex();
143     }
144 
get_second_vertex(face_handle_t anchor_handle,previous_iteration)145     inline vertex_t get_second_vertex(
146         face_handle_t anchor_handle, previous_iteration)
147     {
148         return anchor_handle.old_second_vertex();
149     }
150 
set_lead_dispatch(face_handle_t anchor_handle,first_side)151     inline void set_lead_dispatch(face_handle_t anchor_handle, first_side)
152     {
153         m_lead = get_first_vertex(anchor_handle, Time());
154         set_edge_to_first_dispatch(anchor_handle, ValueType(), Time());
155     }
156 
set_lead_dispatch(face_handle_t anchor_handle,second_side)157     inline void set_lead_dispatch(face_handle_t anchor_handle, second_side)
158     {
159         m_lead = get_second_vertex(anchor_handle, Time());
160         set_edge_to_second_dispatch(anchor_handle, ValueType(), Time());
161     }
162 
set_edge_to_first_dispatch(face_handle_t anchor_handle,edge_t,current_iteration)163     inline void set_edge_to_first_dispatch(
164         face_handle_t anchor_handle, edge_t, current_iteration)
165     {
166         m_edge.value = anchor_handle.first_edge();
167     }
168 
set_edge_to_second_dispatch(face_handle_t anchor_handle,edge_t,current_iteration)169     inline void set_edge_to_second_dispatch(
170         face_handle_t anchor_handle, edge_t, current_iteration)
171     {
172         m_edge.value = anchor_handle.second_edge();
173     }
174 
set_edge_to_first_dispatch(face_handle_t anchor_handle,edge_t,previous_iteration)175     inline void set_edge_to_first_dispatch(
176         face_handle_t anchor_handle, edge_t, previous_iteration)
177     {
178         m_edge.value = anchor_handle.old_first_edge();
179     }
180 
set_edge_to_second_dispatch(face_handle_t anchor_handle,edge_t,previous_iteration)181     inline void set_edge_to_second_dispatch(
182         face_handle_t anchor_handle, edge_t, previous_iteration)
183     {
184         m_edge.value = anchor_handle.old_second_edge();
185     }
186 
187     template < typename T >
set_edge_to_first_dispatch(face_handle_t,vertex_t,T)188     inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T)
189     {
190     }
191 
192     template < typename T >
set_edge_to_second_dispatch(face_handle_t,vertex_t,T)193     inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T)
194     {
195     }
196 
increment()197     void increment()
198     {
199         face_handle_t curr_face_handle(m_face_handles[m_lead]);
200         vertex_t first = get_first_vertex(curr_face_handle, Time());
201         vertex_t second = get_second_vertex(curr_face_handle, Time());
202         if (first == m_follow)
203         {
204             m_follow = m_lead;
205             set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time());
206             m_lead = second;
207         }
208         else if (second == m_follow)
209         {
210             m_follow = m_lead;
211             set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time());
212             m_lead = first;
213         }
214         else
215             m_lead = m_follow = graph_traits< Graph >::null_vertex();
216     }
217 
equal(self const & other) const218     bool equal(self const& other) const
219     {
220         return m_lead == other.m_lead && m_follow == other.m_follow;
221     }
222 
dereference() const223     ValueType dereference() const
224     {
225         return dereference_dispatch(VisitorType(), ValueType());
226     }
227 
dereference_dispatch(lead_visitor,vertex_t) const228     inline ValueType dereference_dispatch(lead_visitor, vertex_t) const
229     {
230         return m_lead;
231     }
232 
dereference_dispatch(follow_visitor,vertex_t) const233     inline ValueType dereference_dispatch(follow_visitor, vertex_t) const
234     {
235         return m_follow;
236     }
237 
dereference_dispatch(lead_visitor,edge_t) const238     inline ValueType dereference_dispatch(lead_visitor, edge_t) const
239     {
240         return m_edge.value;
241     }
242 
dereference_dispatch(follow_visitor,edge_t) const243     inline ValueType dereference_dispatch(follow_visitor, edge_t) const
244     {
245         return m_edge.value;
246     }
247 
248     vertex_t m_lead;
249     vertex_t m_follow;
250     edge_storage< Graph, boost::is_same< ValueType, edge_t >::value > m_edge;
251     FaceHandlesMap m_face_handles;
252 };
253 
254 template < typename Graph, typename FaceHandlesMap, typename ValueType,
255     typename VisitorType, typename Time >
256 class face_iterator< Graph, FaceHandlesMap, ValueType, both_sides, VisitorType,
257     Time >
258 : public boost::iterator_facade< face_iterator< Graph, FaceHandlesMap,
259                                      ValueType, both_sides, VisitorType, Time >,
260       ValueType, boost::forward_traversal_tag, ValueType >
261 {
262 public:
263     typedef face_iterator< Graph, FaceHandlesMap, ValueType, both_sides,
264         VisitorType, Time >
265         self;
266     typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
267     typedef typename FaceHandlesMap::value_type face_handle_t;
268 
face_iterator()269     face_iterator() {}
270 
face_iterator(face_handle_t anchor_handle,FaceHandlesMap face_handles)271     face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles)
272     : first_itr(anchor_handle, face_handles, first_side())
273     , second_itr(anchor_handle, face_handles, second_side())
274     , first_is_active(true)
275     , first_increment(true)
276     {
277     }
278 
face_iterator(vertex_t anchor,FaceHandlesMap face_handles)279     face_iterator(vertex_t anchor, FaceHandlesMap face_handles)
280     : first_itr(face_handles[anchor], face_handles, first_side())
281     , second_itr(face_handles[anchor], face_handles, second_side())
282     , first_is_active(true)
283     , first_increment(true)
284     {
285     }
286 
287 private:
288     friend class boost::iterator_core_access;
289 
290     typedef face_iterator< Graph, FaceHandlesMap, ValueType, single_side,
291         follow_visitor, Time >
292         inner_itr_t;
293 
increment()294     void increment()
295     {
296         if (first_increment)
297         {
298             ++first_itr;
299             ++second_itr;
300             first_increment = false;
301         }
302         else if (first_is_active)
303             ++first_itr;
304         else
305             ++second_itr;
306         first_is_active = !first_is_active;
307     }
308 
equal(self const & other) const309     bool equal(self const& other) const
310     {
311         // Want this iterator to be equal to the "end" iterator when at least
312         // one of the iterators has reached the root of the current bicomp.
313         // This isn't ideal, but it works.
314 
315         return (first_itr == other.first_itr || second_itr == other.second_itr);
316     }
317 
dereference() const318     ValueType dereference() const
319     {
320         return first_is_active ? *first_itr : *second_itr;
321     }
322 
323     inner_itr_t first_itr;
324     inner_itr_t second_itr;
325     inner_itr_t face_end;
326     bool first_is_active;
327     bool first_increment;
328 };
329 
330 } /* namespace boost */
331 
332 #endif //__FACE_ITERATORS_HPP__
333