// Copyright (c) 1999 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Monique Teillaud #ifndef CGAL_TRIANGULATION_DS_ITERATORS_3_H #define CGAL_TRIANGULATION_DS_ITERATORS_3_H #include #include #include #include CGAL_BEGIN_NAMESPACE template < class Tds > class Triangulation_ds_facet_iterator_3 { // traverses the list of cells and reports all facets. public: typedef typename Tds::Facet value_type; typedef const typename Tds::Facet * pointer; typedef const typename Tds::Facet & reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; typedef typename Tds::Facet Facet; typedef Triangulation_ds_facet_iterator_3 Facet_iterator; typedef typename Tds::Cell_iterator Cell_iterator; Triangulation_ds_facet_iterator_3() {} Triangulation_ds_facet_iterator_3(const Tds * tds) : _tds(tds) { facet.second = 0; switch ( _tds->dimension() ) { case 2: pos = _tds->cell_container().begin(); facet.second = 3; return; case 3: pos = _tds->cell_container().begin(); while (// there must be at least one facet pos->neighbor(facet.second) < pos ) { increment(); } return; default: pos = _tds->cell_container().end(); return; } } // used to initialize the past-the end iterator Triangulation_ds_facet_iterator_3(const Tds* tds, int) : _tds(tds) { facet.second = 0; pos = _tds->cell_container().end(); if (_tds->dimension() == 2) facet.second = 3; } Facet_iterator& operator++() { if (_tds->dimension() < 2) return *this; if (_tds->dimension() == 3) { do { increment(); } while ( pos != _tds->cell_container().end() && pos->neighbor(facet.second) < pos ); // reports a facet when the current cell has a pointer inferior // to the pointer of the neighbor cell return *this; } ++pos; // dimension 2 return *this; } Facet_iterator& operator--() { if (_tds->dimension() < 2) return *this; if ( _tds->dimension() == 2 ) { --pos; // index remains 3 return *this; } // dimension 3 do{ if (facet.second == 0) { // all the facets of the current cell have been examined facet.second = 3; --pos; } else --facet.second; } while ( pos != _tds->cell_container().end() && pos->neighbor(facet.second) < pos ); // reports a facet when the current cell has a pointer inferior // to the pointer of the neighbor cell return *this; } Facet_iterator operator++(int) { Facet_iterator tmp(*this); ++(*this); return tmp; } Facet_iterator operator--(int) { Facet_iterator tmp(*this); --(*this); return tmp; } bool operator==(const Facet_iterator& fi) const { return _tds == fi._tds && pos == fi.pos && facet.second == fi.facet.second; } bool operator!=(const Facet_iterator& fi) const { return !(*this == fi); } reference operator*() const { facet.first = pos; return facet; } pointer operator->() const { facet.first = pos; return &facet; } private: const Tds* _tds; Cell_iterator pos; // current "cell". mutable Facet facet; // current facet. void increment() { if (facet.second == 3) { // all the faces of the current cell have been examined facet.second = 0; ++pos; } // be careful : facet.second should always be 0 when pos = cells_end else ++facet.second; } }; template < class Tds > class Triangulation_ds_edge_iterator_3 { // traverses the list of cells and reports each edge. public: typedef typename Tds::Edge value_type; typedef const typename Tds::Edge * pointer; typedef const typename Tds::Edge & reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; typedef typename Tds::Edge Edge; typedef Triangulation_ds_edge_iterator_3 Edge_iterator; typedef typename Tds::Cell_iterator Cell_iterator; typedef typename Tds::Cell_handle Cell_handle; typedef Triangulation_ds_cell_circulator_3 Cell_circulator; Triangulation_ds_edge_iterator_3() : _tds(NULL) { edge.second = 0; edge.third = 1; } Triangulation_ds_edge_iterator_3(const Tds * tds) : _tds(tds) { edge.second = 0; edge.third = 1; switch ( _tds->dimension() ) { case 1: { pos = _tds->cell_container().begin(); return; } case 2: { pos = _tds->cell_container().begin(); while ( // there must be at least one edge pos->neighbor(3-edge.second-edge.third) < pos ) { increment2(); } return; } case 3: { pos = _tds->cell_container().begin(); bool notfound = true; while ( // there must be at least one edge notfound ) { edge.first = pos; Cell_circulator ccir = _tds->incident_cells(edge); do { ++ccir; #ifdef CGAL_T3_USE_ITERATOR_AS_HANDLE } while ( pos < ccir ); #else } while ( Cell_handle(pos) < Cell_handle(ccir) ); #endif // loop terminates since it stops at least when ccir = pos if ( Cell_handle(ccir) == Cell_handle(pos) ) // pos is the cell with minimal pointer notfound = false; else increment3(); } return; } default: { pos = _tds->cell_container().end(); return; } } } // used to initialize the past-the end iterator Triangulation_ds_edge_iterator_3(const Tds* tds, int) : _tds(tds) { edge.second = 0; edge.third = 1; pos = _tds->cell_container().end(); } Edge_iterator& operator++() { switch ( _tds->dimension() ) { case 1: { ++pos; break; } case 2: { do { increment2(); } while ( pos != _tds->cell_container().end() && pos->neighbor(3-edge.second-edge.third) < pos ); break; } case 3: { bool notfound = true; do { increment3(); if (pos != _tds->cell_container().end()) { edge.first = pos; Cell_circulator ccir = _tds->incident_cells(edge); do { ++ccir; } while ( Cell_handle(pos) < Cell_handle(ccir) ); if ( Cell_handle(ccir) == Cell_handle(pos) ) // pos is the cell with minimal pointer notfound = false; } else { edge.second=0; edge.third=1; } } while ( pos != _tds->cell_container().end() && notfound ); break; } default: { return *this; } } return *this; } Edge_iterator& operator--() { switch ( _tds->dimension() ) { case 1: { --pos; // edge.second, edge.third remain 0, 1 break; } case 2: { do { if (edge.second == 0) { edge.second = 2; edge.third = 0; --pos; } else { --edge.second; edge.third = edge.second+1; // case edge.second==2, edge.third==0 forbids to write edge.third-- } } while ( pos != _tds->cell_container().end() && pos->neighbor(3-edge.second-edge.third) < pos ); break; } case 3: { bool notfound = true; do { if (edge.second == 0) { if (edge.third == 1) { // all the edges of the current cell have been examined edge.second = 2; edge.third = 3; --pos; } else --edge.third; } else { if (edge.third == edge.second+1) { --edge.second; edge.third = 3; } else --edge.third; } if (pos != _tds->cell_container().end()) { edge.first = pos; Cell_circulator ccir = _tds->incident_cells(edge); do { ++ccir; } while ( Cell_handle(pos) < Cell_handle(ccir) ); if ( Cell_handle(pos) == Cell_handle(ccir) ) // pos is the cell with minimum pointer notfound = false; } else { edge.second=0; edge.third=1; } } while ( pos != _tds->cell_container().end() && notfound ); break; } default : return *this; } // reports an edge when the current cell has a pointer inferior // to the pointer of the neighbor cell return *this; } Edge_iterator operator++(int) { Edge_iterator tmp(*this); ++(*this); return tmp; } Edge_iterator operator--(int) { Edge_iterator tmp(*this); --(*this); return tmp; } bool operator==(const Edge_iterator& ei) const { return _tds == ei._tds && pos == ei.pos && edge.second == ei.edge.second && edge.third == ei.edge.third; } bool operator!=(const Edge_iterator& ei) const { return !(*this == ei); } reference operator*() const { edge.first = pos; return edge; } pointer operator->() const { edge.first = pos; return &edge; } private: const Tds* _tds; Cell_iterator pos; // current "cell". Even if the dimension is <3 when // there is no true cell yet. mutable Edge edge; // keeps the indices of the current edge. void increment2() { if (edge.second == 2) { // edge.third == 0 // all the edges of the current cell have been examined edge.second = 0; edge.third = 1; ++pos; } // be careful : index should always be 0 when pos = cells_end else { ++edge.second; if ( edge.second == 2 ) edge.third = 0; else // edge.second==1 edge.third = 2; } } void increment3() { if (edge.second == 2) { // then edge.third == 3 // all the edges of the current cell have been examined edge.second = 0; edge.third = 1; ++pos; } else { if (edge.third == 3) { edge.second++; edge.third = edge.second+1; } else ++edge.third; } } }; CGAL_END_NAMESPACE #endif // CGAL_TRIANGULATION_DS_ITERATORS_3_H