|
BWAPI
|
00001 // Copyright (c) 2003,2004,2005 INRIA Sophia-Antipolis (France) and 00002 // Notre Dame University (U.S.A.). All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2/edge_list.h $ 00015 // $Id: edge_list.h 28567 2006-02-16 14:30:13Z lsaboret $ 00016 // 00017 // 00018 // Author(s) : Menelaos Karavelas <mkaravel@cse.nd.edu> 00019 00020 #ifndef CGAL_SEGMENT_DELAUNAY_GRAPH_2_EDGE_LIST_H 00021 #define CGAL_SEGMENT_DELAUNAY_GRAPH_2_EDGE_LIST_H 00022 00023 00024 #include <CGAL/Unique_hash_map.h> 00025 #include <CGAL/Edge_hash_function.h> 00026 #include <CGAL/circulator_bases.h> 00027 00028 CGAL_BEGIN_NAMESPACE 00029 00030 00031 namespace CGALi { 00032 00033 template<class Edge_t> 00034 class Edge_list_item 00035 { 00036 public: 00037 typedef Edge_t Edge; 00038 00039 private: 00040 typedef typename Edge::first_type Face_handle; 00041 00042 private: 00043 Edge prev_; 00044 Edge next_; 00045 00046 public: 00047 // remove the following method and make SENTINEL_EDGE a static const 00048 // member of the class. 00049 static const Edge& sentinel_edge() { 00050 static Edge SENTINEL_EDGE = Edge(Face_handle(), sentinel_index()); 00051 return SENTINEL_EDGE; 00052 } 00053 00054 private: 00055 static int sentinel_index() { return -1; } 00056 00057 public: 00058 Edge_list_item() 00059 : prev_(sentinel_edge()), next_(sentinel_edge()) {} 00060 Edge_list_item(const Edge& prev, const Edge& next) 00061 : prev_(prev), next_(next) {} 00062 00063 00064 bool is_in_list() const 00065 { 00066 return ( next_.second != sentinel_index() || 00067 prev_.second != sentinel_index() ); 00068 } 00069 00070 void set_next(const Edge& next) 00071 { 00072 next_ = next; 00073 } 00074 00075 void set_previous(const Edge& prev) 00076 { 00077 prev_ = prev; 00078 } 00079 00080 const Edge& next() const { return next_; } 00081 const Edge& previous() const { return prev_; } 00082 00083 void reset() { 00084 Edge SENTINEL_EDGE = sentinel_edge(); 00085 next_ = prev_ = SENTINEL_EDGE; 00086 } 00087 }; 00088 00089 00090 00091 template<class E_t, class ListItem, class USE_STL_MAP_Tag> 00092 struct Edge_list_which_map; 00093 00094 // use STL's map 00095 template<class E_t, class ListItem> 00096 struct Edge_list_which_map<E_t,ListItem,Tag_true> 00097 { 00098 typedef E_t Edge; 00099 typedef ListItem List_item; 00100 typedef std::map<Edge,List_item> Edge_map; 00101 }; 00102 00103 // use CGAL's Unique_hash_map 00104 template<class E_t, class ListItem> 00105 struct Edge_list_which_map<E_t,ListItem,Tag_false> 00106 { 00107 typedef E_t Edge; 00108 typedef ListItem List_item; 00109 typedef CGAL::Edge_hash_function Hash_function; 00110 00111 typedef Unique_hash_map<Edge,List_item,Hash_function> Edge_map; 00112 }; 00113 00114 00115 template<class Edge_list_t> 00116 class Edge_list_circulator 00117 : public CGAL::Bidirectional_circulator_base<typename Edge_list_t::Edge> 00118 { 00119 private: 00120 typedef Edge_list_t List; 00121 typedef typename List::Edge Edge; 00122 typedef Edge_list_item<Edge> List_item; 00123 typedef CGAL::Bidirectional_circulator_base<Edge> Base; 00124 00125 typedef Edge_list_circulator<List> Self; 00126 00127 public: 00128 Edge_list_circulator() 00129 : l_(NULL), c_(List_item::sentinel_edge()) {} 00130 00131 Edge_list_circulator(const List* l, const Edge& c) 00132 : l_(l), c_(/*const_cast<Edge&>(*/c/*)*/) {} 00133 00134 Edge_list_circulator(const Edge_list_circulator& other) 00135 : l_(other.l_), c_(other.c_) {} 00136 00137 Edge_list_circulator& operator=(const Edge_list_circulator& other) { 00138 l_ = other.l_; 00139 c_ = other.c_; 00140 return *this; 00141 } 00142 00143 Self& operator++() { 00144 CGAL_precondition( l_ != NULL ); 00145 // c_ = const_cast<Edge&>(l_->next(c_)); 00146 c_ = l_->next(c_); 00147 return *this; 00148 } 00149 00150 Self& operator--() { 00151 CGAL_precondition( l_ != NULL ); 00152 // c_ = const_cast<Edge&>(l_->previous(c_)); 00153 c_ = l_->previous(c_); 00154 return *this; 00155 } 00156 00157 Self operator++(int) { 00158 Self tmp(*this); 00159 ++tmp; 00160 return tmp; 00161 } 00162 00163 Self operator--(int) { 00164 Self tmp(*this); 00165 --tmp; 00166 return tmp; 00167 } 00168 00169 typename Base::pointer operator->() { return &c_; } 00170 typename Base::reference operator*() { return c_; } 00171 00172 bool operator==(const Self& other) const { 00173 return l_ == other.l_ && c_ == other.c_; 00174 } 00175 00176 bool operator!=(const Self& other) const { 00177 return l_ != other.l_ || c_ != other.c_; 00178 } 00179 00180 protected: 00181 const List* l_; 00182 // Edge& c_; 00183 Edge c_; 00184 }; 00185 00186 00187 } // namespace CGALi 00188 00189 00190 00191 template<class Edge_t, class USE_STL_MAP_Tag = Tag_true> 00192 class Edge_list 00193 { 00194 public: 00195 // TYPES 00196 //====== 00197 typedef std::size_t size_type; 00198 typedef Edge_t Edge; 00199 typedef USE_STL_MAP_Tag Use_stl_map_tag; 00200 00201 private: 00202 typedef CGALi::Edge_list_item<Edge> List_item; 00203 00204 typedef 00205 CGALi::Edge_list_which_map<Edge,List_item,Use_stl_map_tag> 00206 Which_map; 00207 00208 typedef typename Which_map::Edge_map Edge_map; 00209 00210 typedef Edge_list<Edge,Use_stl_map_tag> Self; 00211 00212 public: 00213 typedef CGALi::Edge_list_circulator<Self> circulator; 00214 00215 private: 00216 // PRIVATE DATA MEMBERS 00217 //===================== 00218 Edge_map emap; 00219 Edge front_; 00220 size_type size_; 00221 00222 private: 00223 // PRIVATE METHODS 00224 //================ 00225 void increase_size() { 00226 size_++; 00227 } 00228 00229 void decrease_size() { 00230 size_--; 00231 } 00232 00233 void insert_before_nocheck(const Edge& e, const Edge& new_e) { 00234 List_item& li_e = emap[e]; 00235 00236 const Edge& prev_e = li_e.previous(); 00237 List_item& li_prev_e = emap[prev_e]; 00238 00239 emap[new_e] = List_item(prev_e, e); 00240 li_e.set_previous(new_e); 00241 li_prev_e.set_next(new_e); 00242 increase_size(); 00243 } 00244 00245 // check whether the edge is in the list; 00246 // the map used is STL's map 00247 bool is_in_list_with_tag(const Edge& e, const Tag_true&) const 00248 { 00249 if ( emap.find(e) == emap.end() ) { return false; } 00250 return emap.find(e)->second.is_in_list(); 00251 } 00252 00253 // check whether the edge is in the list; 00254 // the map used is CGAL's Unique_hash_map 00255 bool is_in_list_with_tag(const Edge& e, const Tag_false&) const 00256 { 00257 if ( !emap.is_defined(e) ) { return false; } 00258 return emap[e].is_in_list(); 00259 } 00260 00261 // return the next edge in the list; 00262 // the map used is STL's map 00263 const Edge& next_with_tag(const Edge& e, const Tag_true&) const 00264 { 00265 return emap.find(e)->second.next(); 00266 } 00267 00268 // return the next edge in the list; 00269 // the map used is CGAL's Unique_hash_map 00270 const Edge& next_with_tag(const Edge& e, const Tag_false&) const 00271 { 00272 return emap[e].next(); 00273 } 00274 00275 // return the previous edge in the list; 00276 // the map used is STL's map 00277 const Edge& previous_with_tag(const Edge& e, const Tag_true&) const 00278 { 00279 return emap.find(e)->second.previous(); 00280 } 00281 00282 // return the previous edge in the list; 00283 // the map used is CGAL's Unique_hash_map 00284 const Edge& previous_with_tag(const Edge& e, const Tag_false&) const 00285 { 00286 return emap[e].previous(); 00287 } 00288 00289 public: 00290 // CONSTRUCTOR 00291 //============ 00292 #ifdef _MSC_VER 00293 Edge_list(const Edge& e = Edge(typename Edge::first_type(),-1) ) 00294 : emap(), front_(e), size_(0) {} 00295 #else 00296 Edge_list(const Edge& e = List_item::sentinel_edge() ) 00297 : emap(), front_(e), size_(0) {} 00298 #endif 00299 00300 // PREDICATES 00301 //=========== 00302 bool is_valid() const { return true; } 00303 00304 bool is_in_list(const Edge& e) const { 00305 static Use_stl_map_tag map_tag; 00306 return is_in_list_with_tag(e, map_tag); 00307 } 00308 00309 00310 // ACCESS METHODS 00311 //=============== 00312 size_type size() const { 00313 return size_; 00314 } 00315 00316 const Edge& next(const Edge& e) const { 00317 CGAL_precondition( is_in_list(e) ); 00318 static Use_stl_map_tag map_tag; 00319 return next_with_tag(e, map_tag); 00320 } 00321 00322 const Edge& previous(const Edge& e) const { 00323 CGAL_precondition( is_in_list(e) ); 00324 static Use_stl_map_tag map_tag; 00325 return previous_with_tag(e, map_tag); 00326 } 00327 00328 const Edge& front() const { 00329 CGAL_precondition( size() > 0 ); 00330 return front_; 00331 } 00332 00333 const Edge& back() const { 00334 CGAL_precondition( size() > 0 ); 00335 return previous(front_); 00336 } 00337 00338 00339 // INSERTION 00340 //========== 00341 void push_front(const Edge& e) { 00342 push_back(e); 00343 front_ = e; 00344 } 00345 00346 void push_back(const Edge& e) { 00347 CGAL_precondition( !is_in_list(e) ); 00348 00349 if ( size() == 0 ) { 00350 emap[e] = List_item(e,e); 00351 front_ = e; 00352 increase_size(); 00353 return; 00354 } 00355 00356 insert_before_nocheck(front_, e); 00357 } 00358 00359 void insert_after(const Edge& e, const Edge& new_e) { 00360 CGAL_precondition( is_in_list(e) ); 00361 CGAL_precondition( !is_in_list(new_e) ); 00362 00363 List_item& li_e = emap[e]; 00364 00365 const Edge& next_e = li_e.next(); 00366 List_item& li_next_e = emap[next_e]; 00367 00368 emap[new_e] = List_item(e, next_e); 00369 li_e.set_next(new_e); 00370 li_next_e.set_previous(new_e); 00371 increase_size(); 00372 } 00373 00374 void insert_before(const Edge& e, const Edge& new_e) { 00375 CGAL_precondition( is_in_list(e) ); 00376 CGAL_precondition( !is_in_list(new_e) ); 00377 insert_before_nocheck(e, new_e); 00378 } 00379 00380 00381 // REPLACEMENT 00382 //============ 00383 void replace(const Edge& e, const Edge& new_e) { 00384 CGAL_precondition( is_in_list(e) ); 00385 CGAL_precondition( !is_in_list(new_e) ); 00386 00387 List_item& li_e = emap[e]; 00388 00389 if ( size() == 1 ) { 00390 emap[new_e] = List_item(new_e, new_e); 00391 front_ = new_e; 00392 li_e.reset(); 00393 } 00394 00395 const Edge& next_e = li_e.next(); 00396 const Edge& prev_e = li_e.previous(); 00397 00398 emap[prev_e].set_next(new_e); 00399 emap[next_e].set_previous(new_e); 00400 00401 emap[new_e] = List_item(prev_e, next_e); 00402 00403 li_e.reset(); 00404 00405 if ( e == front_ ) { 00406 front_ = new_e; 00407 } 00408 } 00409 00410 00411 // REMOVAL 00412 //======== 00413 00414 void remove(const Edge& e) { 00415 CGAL_precondition( is_in_list(e) ); 00416 00417 if ( size() == 1 ) { 00418 front_ = List_item::sentinel_edge(); 00419 emap[e].reset(); 00420 decrease_size(); 00421 return; 00422 } 00423 00424 List_item& li_e = emap[e]; 00425 const Edge& next_e = li_e.next(); 00426 const Edge& prev_e = li_e.previous(); 00427 00428 emap[prev_e].set_next(next_e); 00429 emap[next_e].set_previous(prev_e); 00430 00431 if ( e == front_ ) { 00432 // front_ = next_e; 00433 front_ = next_e; 00434 } 00435 00436 li_e.reset(); 00437 00438 decrease_size(); 00439 } 00440 00441 #if 0 00442 // ACCESS TO CIRCULATOR 00443 //===================== 00444 inline circulator start() const { 00445 return start(front()); 00446 } 00447 00448 inline circulator start(const Edge& start) const { 00449 CGAL_precondition( is_in_list(start) ); 00450 return circulator(this, start); 00451 } 00452 #endif 00453 00454 // MISCELLANEOUS 00455 //============== 00456 void clear() { 00457 emap.clear(); 00458 } 00459 }; 00460 00461 CGAL_END_NAMESPACE 00462 00463 00464 #endif // CGAL_SEGMENT_DELAUNAY_GRAPH_2_EDGE_LIST_H
1.7.6.1