cgal/Triangulation_3/include/CGAL/Triangulation_ds_iterators_3.h

461 lines
10 KiB
C++

// 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 <Monique.Teillaud@sophia.inria.fr>
#ifndef CGAL_TRIANGULATION_DS_ITERATORS_3_H
#define CGAL_TRIANGULATION_DS_ITERATORS_3_H
#include <utility>
#include <CGAL/Triangulation_short_names_3.h>
#include <CGAL/triangulation_assertions.h>
#include <CGAL/Triangulation_ds_circulators_3.h>
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<Tds> 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<Tds> Edge_iterator;
typedef typename Tds::Cell_iterator Cell_iterator;
typedef typename Tds::Cell_handle Cell_handle;
typedef Triangulation_ds_cell_circulator_3<Tds> 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;
} while ( pos < ccir );
// 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