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