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