1 // Copyright (c) 2003,2004,2005 INRIA Sophia-Antipolis (France). 2 // All rights reserved. 3 // 4 // This file is part of CGAL (www.cgal.org). 5 // 6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/TDS_2/include/CGAL/internal/TDS_2/edge_list.h $ 7 // $Id: edge_list.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot 8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial 9 // 10 // 11 // Author(s) : Menelaos Karavelas <mkaravel@iacm.forth.gr> 12 13 #ifndef CGAL_INTERNAL_TDS_2_EDGE_LIST_H 14 #define CGAL_INTERNAL_TDS_2_EDGE_LIST_H 15 16 #include <CGAL/license/TDS_2.h> 17 18 #include <CGAL/Unique_hash_map.h> 19 #include <CGAL/internal/TDS_2/Edge_hash_function.h> 20 #include <CGAL/circulator_bases.h> 21 22 namespace CGAL { 23 24 25 namespace internal { 26 27 template<class Edge_t> 28 class Edge_list_item 29 { 30 public: 31 typedef Edge_t Edge; 32 33 private: 34 typedef typename Edge::first_type Face_handle; 35 36 private: 37 Edge prev_; 38 Edge next_; 39 40 public: 41 // remove the following method and make SENTINEL_EDGE a static const 42 // member of the class. sentinel_edge()43 static Edge sentinel_edge() { 44 return Edge(Face_handle(), sentinel_index()); 45 } 46 47 private: sentinel_index()48 static int sentinel_index() { return -1; } 49 50 public: Edge_list_item()51 Edge_list_item() 52 : prev_(sentinel_edge()), next_(sentinel_edge()) {} Edge_list_item(const Edge & prev,const Edge & next)53 Edge_list_item(const Edge& prev, const Edge& next) 54 : prev_(prev), next_(next) {} 55 56 is_in_list()57 bool is_in_list() const 58 { 59 return ( next_.second != sentinel_index() || 60 prev_.second != sentinel_index() ); 61 } 62 set_next(const Edge & next)63 void set_next(const Edge& next) 64 { 65 next_ = next; 66 } 67 set_previous(const Edge & prev)68 void set_previous(const Edge& prev) 69 { 70 prev_ = prev; 71 } 72 next()73 const Edge& next() const { return next_; } previous()74 const Edge& previous() const { return prev_; } 75 reset()76 void reset() { 77 Edge SENTINEL_EDGE = sentinel_edge(); 78 next_ = prev_ = SENTINEL_EDGE; 79 } 80 }; 81 82 83 84 template<class E_t, class ListItem, class USE_STL_MAP_Tag> 85 struct Edge_list_which_map; 86 87 // use STL's map 88 template<class E_t, class ListItem> 89 struct Edge_list_which_map<E_t,ListItem,Tag_true> 90 { 91 typedef E_t Edge; 92 typedef ListItem List_item; 93 typedef std::map<Edge,List_item> Edge_map; 94 }; 95 96 // use CGAL's Unique_hash_map 97 template<class E_t, class ListItem> 98 struct Edge_list_which_map<E_t,ListItem,Tag_false> 99 { 100 typedef E_t Edge; 101 typedef ListItem List_item; 102 typedef CGAL::Edge_hash_function Hash_function; 103 104 typedef Unique_hash_map<Edge,List_item,Hash_function> Edge_map; 105 }; 106 107 108 template<class Edge_list_t> 109 class Edge_list_circulator 110 : public CGAL::Bidirectional_circulator_base<typename Edge_list_t::Edge> 111 { 112 private: 113 typedef Edge_list_t List; 114 typedef typename List::Edge Edge; 115 typedef Edge_list_item<Edge> List_item; 116 typedef CGAL::Bidirectional_circulator_base<Edge> Base; 117 118 typedef Edge_list_circulator<List> Self; 119 120 public: 121 typedef typename Base::pointer pointer; 122 typedef typename Base::reference reference; 123 124 public: 125 Edge_list_circulator() 126 : l_(nullptr), c_(List_item::sentinel_edge()) {} 127 128 Edge_list_circulator(const List* l, const Edge& c) 129 : l_(l), c_(/*const_cast<Edge&>(*/c/*)*/) {} 130 131 Edge_list_circulator(const Edge_list_circulator& other) 132 : l_(other.l_), c_(other.c_) {} 133 134 Edge_list_circulator& operator=(const Edge_list_circulator& other) { 135 l_ = other.l_; 136 c_ = other.c_; 137 return *this; 138 } 139 140 Self& operator++() { 141 CGAL_precondition( l_ != nullptr ); 142 // c_ = const_cast<Edge&>(l_->next(c_)); 143 c_ = l_->next(c_); 144 return *this; 145 } 146 147 Self& operator--() { 148 CGAL_precondition( l_ != nullptr ); 149 // c_ = const_cast<Edge&>(l_->previous(c_)); 150 c_ = l_->previous(c_); 151 return *this; 152 } 153 154 Self operator++(int) { 155 Self tmp(*this); 156 ++(*this); 157 return tmp; 158 } 159 160 Self operator--(int) { 161 Self tmp(*this); 162 --(*this); 163 return tmp; 164 } 165 166 pointer operator->() { return &c_; } 167 reference operator*() { return c_; } 168 169 bool operator==(const Self& other) const { 170 CGAL_assertion( l_ == other.l_ ); 171 return c_ == other.c_; 172 } 173 174 bool operator!=(const Self& other) const { 175 CGAL_assertion( l_ == other.l_ ); 176 return c_ != other.c_; 177 } 178 179 protected: 180 const List* l_; 181 // Edge& c_; 182 Edge c_; 183 }; 184 185 186 template<class L> 187 class Edge_list_iterator 188 { 189 typedef L Edge_list; 190 typedef typename Edge_list::Edge Edge; 191 typedef Edge_list_iterator<Edge_list> Self; 192 193 public: 194 typedef Edge* pointer; 195 typedef Edge& reference; 196 197 public: 198 Edge_list_iterator() {} 199 200 Edge_list_iterator(const Edge_list* l, const Edge& e, unsigned int idx) 201 : l(l), e(e), idx(idx) {} 202 203 Edge_list_iterator(const Self& other) 204 { 205 l = other.l; 206 e = other.e; 207 idx = other.idx; 208 } 209 210 Self& operator=(const Self& other) 211 { 212 l = other.l; 213 e = other.e; 214 idx = other.idx; 215 return *this; 216 } 217 218 // pre-increment 219 Self& operator++() { 220 ++idx; 221 e = l->next(e); 222 return *this; 223 } 224 225 // post-increment 226 Self operator++(int) { 227 Self tmp(*this); 228 ++(*this); 229 return tmp; 230 } 231 232 Self& operator--() { 233 --idx; 234 e = l->previous(e); 235 return *this; 236 } 237 238 Self operator--(int) { 239 Self tmp(*this); 240 --(*this); 241 return tmp; 242 } 243 244 pointer operator->() { return &e; } 245 reference operator*() { return e; } 246 247 248 bool operator==(const Self& other) const { 249 CGAL_assertion( l == other.l ); 250 return idx == other.idx; 251 } 252 253 bool operator!=(const Self& other) const { 254 CGAL_assertion( l == other.l ); 255 return idx != other.idx; 256 } 257 258 private: 259 const Edge_list* l; 260 Edge e; 261 unsigned int idx; 262 }; 263 264 265 } // namespace internal 266 267 268 269 template<class Edge_t, class USE_STL_MAP_Tag = Tag_true> 270 class Edge_list 271 { 272 public: 273 // TYPES 274 //====== 275 typedef std::size_t size_type; 276 typedef Edge_t Edge; 277 typedef USE_STL_MAP_Tag Use_stl_map_tag; 278 279 private: 280 typedef internal::Edge_list_item<Edge> List_item; 281 282 typedef 283 internal::Edge_list_which_map<Edge,List_item,Use_stl_map_tag> 284 Which_map; 285 286 typedef typename Which_map::Edge_map Edge_map; 287 288 typedef Edge_list<Edge,Use_stl_map_tag> Self; 289 290 public: 291 typedef internal::Edge_list_circulator<Self> circulator; 292 typedef internal::Edge_list_iterator<Self> iterator; 293 294 private: 295 // PRIVATE DATA MEMBERS 296 //===================== 297 Edge_map emap; 298 Edge front_; 299 size_type size_; 300 301 private: 302 // PRIVATE METHODS 303 //================ 304 void increase_size() { 305 size_++; 306 } 307 308 void decrease_size() { 309 size_--; 310 } 311 312 void insert_before_nocheck(const Edge& e, const Edge& new_e) { 313 List_item& li_e = emap[e]; 314 315 const Edge& prev_e = li_e.previous(); 316 List_item& li_prev_e = emap[prev_e]; 317 318 emap[new_e] = List_item(prev_e, e); 319 li_e.set_previous(new_e); 320 li_prev_e.set_next(new_e); 321 increase_size(); 322 } 323 324 // check whether the edge is in the list; 325 // the map used is STL's map 326 bool is_in_list_with_tag(const Edge& e, const Tag_true&) const 327 { 328 if ( emap.find(e) == emap.end() ) { return false; } 329 return emap.find(e)->second.is_in_list(); 330 } 331 332 // check whether the edge is in the list; 333 // the map used is CGAL's Unique_hash_map 334 bool is_in_list_with_tag(const Edge& e, const Tag_false&) const 335 { 336 if ( !emap.is_defined(e) ) { return false; } 337 return emap[e].is_in_list(); 338 } 339 340 // return the next edge in the list; 341 // the map used is STL's map 342 const Edge& next_with_tag(const Edge& e, const Tag_true&) const 343 { 344 return emap.find(e)->second.next(); 345 } 346 347 // return the next edge in the list; 348 // the map used is CGAL's Unique_hash_map 349 const Edge& next_with_tag(const Edge& e, const Tag_false&) const 350 { 351 return emap[e].next(); 352 } 353 354 // return the previous edge in the list; 355 // the map used is STL's map 356 const Edge& previous_with_tag(const Edge& e, const Tag_true&) const 357 { 358 return emap.find(e)->second.previous(); 359 } 360 361 // return the previous edge in the list; 362 // the map used is CGAL's Unique_hash_map 363 const Edge& previous_with_tag(const Edge& e, const Tag_false&) const 364 { 365 return emap[e].previous(); 366 } 367 368 public: 369 // CONSTRUCTOR 370 //============ 371 #ifdef _MSC_VER 372 Edge_list(const Edge& e = Edge(typename Edge::first_type(),-1) ) 373 : emap(), front_(e), size_(0) {} 374 #else 375 Edge_list(const Edge& e = List_item::sentinel_edge() ) 376 : emap(), front_(e), size_(0) {} 377 #endif 378 379 // PREDICATES 380 //=========== 381 bool is_valid() const { return true; } 382 383 bool is_in_list(const Edge& e) const { 384 Use_stl_map_tag map_tag; 385 return is_in_list_with_tag(e, map_tag); 386 } 387 388 389 // ACCESS METHODS 390 //=============== 391 size_type size() const { 392 return size_; 393 } 394 395 const Edge& next(const Edge& e) const { 396 CGAL_precondition( is_in_list(e) ); 397 Use_stl_map_tag map_tag; 398 return next_with_tag(e, map_tag); 399 } 400 401 const Edge& previous(const Edge& e) const { 402 CGAL_precondition( is_in_list(e) ); 403 Use_stl_map_tag map_tag; 404 return previous_with_tag(e, map_tag); 405 } 406 407 const Edge& front() const { 408 CGAL_precondition( size() > 0 ); 409 return front_; 410 } 411 412 const Edge& back() const { 413 CGAL_precondition( size() > 0 ); 414 return previous(front_); 415 } 416 417 418 // INSERTION 419 //========== 420 void push_front(const Edge& e) { 421 push_back(e); 422 front_ = e; 423 } 424 425 void push_back(const Edge& e) { 426 CGAL_precondition( !is_in_list(e) ); 427 428 if ( size() == 0 ) { 429 emap[e] = List_item(e,e); 430 front_ = e; 431 increase_size(); 432 return; 433 } 434 435 insert_before_nocheck(front_, e); 436 } 437 438 void insert_after(const Edge& e, const Edge& new_e) { 439 CGAL_precondition( is_in_list(e) ); 440 CGAL_precondition( !is_in_list(new_e) ); 441 442 List_item& li_e = emap[e]; 443 444 const Edge& next_e = li_e.next(); 445 List_item& li_next_e = emap[next_e]; 446 447 emap[new_e] = List_item(e, next_e); 448 li_e.set_next(new_e); 449 li_next_e.set_previous(new_e); 450 increase_size(); 451 } 452 453 void insert_before(const Edge& e, const Edge& new_e) { 454 CGAL_precondition( is_in_list(e) ); 455 CGAL_precondition( !is_in_list(new_e) ); 456 insert_before_nocheck(e, new_e); 457 } 458 459 460 // REPLACEMENT 461 //============ 462 void replace(const Edge& e, const Edge& new_e) { 463 CGAL_precondition( is_in_list(e) ); 464 CGAL_precondition( !is_in_list(new_e) ); 465 466 List_item& li_e = emap[e]; 467 468 if ( size() == 1 ) { 469 emap[new_e] = List_item(new_e, new_e); 470 front_ = new_e; 471 li_e.reset(); 472 } 473 474 const Edge& next_e = li_e.next(); 475 const Edge& prev_e = li_e.previous(); 476 477 emap[prev_e].set_next(new_e); 478 emap[next_e].set_previous(new_e); 479 480 emap[new_e] = List_item(prev_e, next_e); 481 482 li_e.reset(); 483 484 if ( e == front_ ) { 485 front_ = new_e; 486 } 487 } 488 489 490 // REMOVAL 491 //======== 492 493 void remove(const Edge& e) { 494 CGAL_precondition( is_in_list(e) ); 495 496 if ( size() == 1 ) { 497 front_ = List_item::sentinel_edge(); 498 emap[e].reset(); 499 decrease_size(); 500 return; 501 } 502 503 List_item& li_e = emap[e]; 504 const Edge& next_e = li_e.next(); 505 const Edge& prev_e = li_e.previous(); 506 507 emap[prev_e].set_next(next_e); 508 emap[next_e].set_previous(prev_e); 509 510 if ( e == front_ ) { 511 // front_ = next_e; 512 front_ = next_e; 513 } 514 515 li_e.reset(); 516 517 decrease_size(); 518 } 519 520 #if 0 521 // ACCESS TO CIRCULATOR 522 //===================== 523 inline circulator start() const { 524 return start(front()); 525 } 526 527 inline circulator start(const Edge& start) const { 528 CGAL_precondition( is_in_list(start) ); 529 return circulator(this, start); 530 } 531 #endif 532 // ACCESS TO ITERATOR 533 //=================== 534 iterator begin() const { 535 return iterator(this, front(), 0); 536 } 537 538 iterator end() const { 539 return iterator(this, front(), size()); 540 } 541 542 543 // MISCELLANEOUS 544 //============== 545 void clear() { 546 emap.clear(); 547 } 548 }; 549 550 } //namespace CGAL 551 552 553 #endif // CGAL_INTERNAL_TDS_2_EDGE_LIST_H 554