Add unique simplex iterators

This commit is contained in:
Mael Rouxel-Labbé 2023-07-07 02:04:01 +02:00
parent f7a78677fc
commit 5759ce49ae
7 changed files with 906 additions and 506 deletions

View File

@ -119,6 +119,14 @@ public:
/// Unique_vertex_iterator iterates over exactly one representative. /// Unique_vertex_iterator iterates over exactly one representative.
typedef Periodic_2_triangulation_unique_vertex_iterator_2<Self> typedef Periodic_2_triangulation_unique_vertex_iterator_2<Self>
Unique_vertex_iterator; Unique_vertex_iterator;
/// Iterator over the canonical edges, i.e. for each set of periodic copies the
/// Unique_edge_iterator iterates over exactly one representative.
typedef Periodic_2_triangulation_unique_edge_iterator_2<Self>
Unique_edge_iterator;
/// Iterator over the canonical faces, i.e. for each set of periodic copies the
/// Unique_face_iterator iterates over exactly one representative.
typedef Periodic_2_triangulation_unique_face_iterator_2<Self>
Unique_face_iterator;
/// \name For compatibility with the Triangulation_2 class /// \name For compatibility with the Triangulation_2 class
// \{ // \{
@ -676,6 +684,32 @@ public:
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this)); Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
} }
Unique_edge_iterator unique_edges_begin() const
{
return CGAL::filter_iterator(edges_end(),
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this),
edges_begin());
}
/// past-the-end iterator over the canonical edges
Unique_edge_iterator unique_edges_end() const
{
return CGAL::filter_iterator(edges_end(),
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
}
Unique_face_iterator unique_faces_begin() const
{
return CGAL::filter_iterator(faces_end(),
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this),
faces_begin());
}
/// past-the-end iterator over the non-virtual vertices
Unique_face_iterator unique_faces_end() const
{
return CGAL::filter_iterator(faces_end(),
Periodic_2_triangulation_2_internal::Domain_tester<Self>(this));
}
// \} // \}
/// \name Geometric iterators /// \name Geometric iterators
//\{ //\{
@ -972,6 +1006,32 @@ public:
return Offset(); return Offset();
} }
// Gets the canonicalized offsets of a face.
void get_offsets(Face_handle fh,
Offset& off0, Offset& off1, Offset& off2) const
{
Offset face_off0 = int_to_off(fh->offset(0));
Offset face_off1 = int_to_off(fh->offset(1));
Offset face_off2 = int_to_off(fh->offset(2));
Offset diff_off((face_off0.x() == 1 && face_off1.x() == 1 && face_off2.x() == 1) ? -1 : 0,
(face_off0.y() == 1 && face_off1.y() == 1 && face_off2.y() == 1) ? -1 : 0);
off0 = combine_offsets(get_offset(fh, 0), diff_off);
off1 = combine_offsets(get_offset(fh, 1), diff_off);
off2 = combine_offsets(get_offset(fh, 2), diff_off);
}
// Gets the canonicalized offsets of an edge.
void get_offsets(const Edge& e,
Offset& off0, Offset& off1) const
{
Offset edge_off0 = int_to_off(e.first->offset(cw(e.second)));
Offset edge_off1 = int_to_off(e.first->offset(ccw(e.second)));
Offset diff_off((edge_off0.x() == 1 && edge_off1.x() == 1) ? -1 : 0,
(edge_off0.y() == 1 && edge_off1.y() == 1) ? -1 : 0);
off0 = combine_offsets(get_offset(e.first, cw(e.second)), diff_off);
off1 = combine_offsets(get_offset(e.first, ccw(e.second)), diff_off);
}
/// Converts an offset to a bit pattern where bit1==offx and bit0==offy. /// Converts an offset to a bit pattern where bit1==offx and bit0==offy.
int off_to_int(const Offset & off) const int off_to_int(const Offset & off) const
{ {
@ -986,13 +1046,12 @@ public:
return Offset((i >> 1) & 1, i & 1); return Offset((i >> 1) & 1, i & 1);
} }
// \} /// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
// Protected functions of Periodic_2_triangulation_2 bool is_virtual(Vertex_handle v) const
/// Const accessor to the virtual vertices reverse map,
/// used to optimize point location for periodic copies.
const Virtual_vertex_reverse_map &virtual_vertices_reverse() const
{ {
return _virtual_vertices_reverse; if (is_1_cover())
return false;
return (_virtual_vertices.find(v) != _virtual_vertices.end());
} }
/// [Undoc] Returns the non-virtual copy of the vertex. /// [Undoc] Returns the non-virtual copy of the vertex.
@ -1007,15 +1066,6 @@ public:
return vh; return vh;
} }
/// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
bool is_virtual(Vertex_handle v)
{
if (is_1_cover())
return false;
return (_virtual_vertices.find(v) != _virtual_vertices.end());
}
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
{ {
CGAL_precondition(number_of_sheets() != make_array(1, 1) ); CGAL_precondition(number_of_sheets() != make_array(1, 1) );
@ -1024,6 +1074,77 @@ public:
return _virtual_vertices_reverse.find(v)->second; return _virtual_vertices_reverse.find(v)->second;
} }
// Protected functions of Periodic_2_triangulation_2
/// Const accessor to the virtual vertices reverse map,
/// used to optimize point location for periodic copies.
const Virtual_vertex_reverse_map& virtual_vertices_reverse() const
{
return _virtual_vertices_reverse;
}
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical(Face_handle fh) const
{
if(is_1_cover())
return true;
Offset off0, off1, off2;
get_offsets(fh, off0, off1, off2);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off2.x() > 1) return false;
if (off2.y() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
return (offx == 0 && offy == 0);
}
bool is_canonical(const Edge& e) const
{
if(is_1_cover())
return true;
// fetch all offsets
Offset off0, off1;
get_offsets(e, off0, off1);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical edge.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x();
int offy = off0.y() & off1.y();
return (offx == 0 && offy == 0);
}
// checks whether pos points onto a vertex inside the original domain
bool is_canonical(Vertex_handle vh) const
{
return !is_virtual(vh);
}
public:
template<class Stream> template<class Stream>
Stream& draw_triangulation(Stream& os) const Stream& draw_triangulation(Stream& os) const
{ {

View File

@ -66,7 +66,7 @@ public:
{ {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
{ {
while (pos != _t->faces_end() && !is_canonical() ) while (pos != _t->faces_end() && !_t->is_canonical(pos) )
++pos; ++pos;
} }
} }
@ -88,7 +88,7 @@ public:
{ {
++pos; ++pos;
} }
while (pos != _t->faces_end() && !is_canonical()); while (pos != _t->faces_end() && !_t->is_canonical(pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -112,7 +112,7 @@ public:
{ {
--pos; --pos;
} }
while (pos != _t->faces_begin() && !is_canonical()); while (pos != _t->faces_begin() && !_t->is_canonical(pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -172,37 +172,6 @@ private:
mutable Periodic_triangle periodic_triangle; // current triangle. mutable Periodic_triangle periodic_triangle; // current triangle.
private: private:
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical()
{
// fetch all offsets
Offset off0, off1, off2;
get_edge_offsets(off0, off1, off2);
if (_t->number_of_sheets() != make_array(1, 1))
{
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off2.x() > 1) return false;
if (off2.y() > 1) return false;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
return (offx == 0 && offy == 0);
}
// Artificial incrementation function that takes periodic // Artificial incrementation function that takes periodic
// copies into account. // copies into account.
void increment_domain() void increment_domain()
@ -217,7 +186,7 @@ private:
++pos; ++pos;
} }
while (_it == T::UNIQUE_COVER_DOMAIN while (_it == T::UNIQUE_COVER_DOMAIN
&& pos != _t->faces_end() && !is_canonical()); && pos != _t->faces_end() && !_t->is_canonical(pos));
} }
else else
{ {
@ -241,7 +210,7 @@ private:
{ {
--pos; --pos;
} }
while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(pos));
_off = get_drawing_offsets(); _off = get_drawing_offsets();
} }
else else
@ -256,25 +225,6 @@ private:
} }
} }
// Get the canonicalized offsets of an edge.
// This works in any cover that is encoded in _t->combine_offsets
void get_edge_offsets(Offset &off0, Offset &off1,
Offset &off2) const
{
Offset face_off0 = _t->int_to_off(pos->offset(0));
Offset face_off1 = _t->int_to_off(pos->offset(1));
Offset face_off2 = _t->int_to_off(pos->offset(2));
Offset diff_off((face_off0.x() == 1
&& face_off1.x() == 1
&& face_off2.x() == 1) ? -1 : 0,
(face_off0.y() == 1
&& face_off1.y() == 1
&& face_off2.y() == 1) ? -1 : 0);
off0 = _t->combine_offsets(_t->get_offset(pos, 0), diff_off);
off1 = _t->combine_offsets(_t->get_offset(pos, 1), diff_off);
off2 = _t->combine_offsets(_t->get_offset(pos, 2), diff_off);
}
// return an integer that encodes the translations which have to be // return an integer that encodes the translations which have to be
// applied to the edge *pos // applied to the edge *pos
int get_drawing_offsets() int get_drawing_offsets()
@ -287,7 +237,7 @@ private:
// internally stored inside the cell telling us that this cell // internally stored inside the cell telling us that this cell
// wraps around the domain. // wraps around the domain.
if (_it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE_COVER_DOMAIN)
get_edge_offsets(off0, off1, off2); _t->get_offsets(pos, off0, off1, off2);
else else
{ {
CGAL_assertion(_it == T::STORED_COVER_DOMAIN); CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
@ -319,7 +269,7 @@ private:
{ {
CGAL_assertion(pos != typename T::Face_handle()); CGAL_assertion(pos != typename T::Face_handle());
Offset off0, off1, off2; Offset off0, off1, off2;
get_edge_offsets(off0, off1, off2); _t->get_offsets(pos, off0, off1, off2);
Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0), Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0),
(((_off ) & 1) == 1 ? -1 : 0)); (((_off ) & 1) == 1 ? -1 : 0));
if (_it == T::STORED_COVER_DOMAIN) if (_it == T::STORED_COVER_DOMAIN)
@ -385,7 +335,7 @@ public:
{ {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
{ {
while (pos != _t->edges_end() && !is_canonical() ) while (pos != _t->edges_end() && !_t->is_canonical(*pos) )
++pos; ++pos;
} }
} }
@ -407,7 +357,7 @@ public:
{ {
++pos; ++pos;
} }
while (pos != _t->edges_end() && !is_canonical()); while (pos != _t->edges_end() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -431,7 +381,7 @@ public:
{ {
--pos; --pos;
} }
while (pos != _t->edges_begin() && !is_canonical()); while (pos != _t->edges_begin() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -490,35 +440,6 @@ private:
mutable Periodic_segment periodic_segment; // current segment. mutable Periodic_segment periodic_segment; // current segment.
private: private:
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical()
{
// fetch all offsets
Offset off0, off1;
get_edge_offsets(off0, off1);
if (_t->number_of_sheets() != make_array(1, 1))
{
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x();
int offy = off0.y() & off1.y();
return (offx == 0 && offy == 0);
}
// Artificial incrementation function that takes periodic // Artificial incrementation function that takes periodic
// copies into account. // copies into account.
void increment_domain() void increment_domain()
@ -533,7 +454,7 @@ private:
++pos; ++pos;
} }
while (_it == T::UNIQUE_COVER_DOMAIN while (_it == T::UNIQUE_COVER_DOMAIN
&& pos != _t->edges_end() && !is_canonical()); && pos != _t->edges_end() && !_t->is_canonical(*pos));
} }
else else
{ {
@ -557,7 +478,7 @@ private:
{ {
--pos; --pos;
} }
while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
_off = get_drawing_offsets(); _off = get_drawing_offsets();
} }
else else
@ -572,20 +493,6 @@ private:
} }
} }
// Get the canonicalized offsets of an edge.
// This works in any cover that is encoded in _t->combine_offsets
void get_edge_offsets(Offset &off0, Offset &off1) const
{
Offset cell_off0 = _t->int_to_off(pos->first->offset(_t->cw(pos->second)));
Offset cell_off1 = _t->int_to_off(pos->first->offset(_t->ccw(pos->second)));
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1) ? -1 : 0,
(cell_off0.y() == 1 && cell_off1.y() == 1) ? -1 : 0);
off0 = _t->combine_offsets(_t->get_offset(pos->first, _t->cw(pos->second)),
diff_off);
off1 = _t->combine_offsets(_t->get_offset(pos->first, _t->ccw(pos->second)),
diff_off);
}
// return an integer that encodes the translations which have to be // return an integer that encodes the translations which have to be
// applied to the edge *pos // applied to the edge *pos
int get_drawing_offsets() int get_drawing_offsets()
@ -598,7 +505,7 @@ private:
// internally stored inside the cell telling us that this cell // internally stored inside the cell telling us that this cell
// wraps around the domain. // wraps around the domain.
if (_it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE_COVER_DOMAIN)
get_edge_offsets(off0, off1); _t->get_offsets(*pos, off0, off1);
else else
{ {
CGAL_assertion(_it == T::STORED_COVER_DOMAIN); CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
@ -618,7 +525,7 @@ private:
{ {
CGAL_assertion(pos->first != typename T::Face_handle()); CGAL_assertion(pos->first != typename T::Face_handle());
Offset off0, off1; Offset off0, off1;
get_edge_offsets(off0, off1); _t->get_offsets(*pos, off0, off1);
Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0), Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0),
(( _off & 1) == 1 ? -1 : 0)); (( _off & 1) == 1 ? -1 : 0));
if (_it == T::STORED_COVER_DOMAIN) if (_it == T::STORED_COVER_DOMAIN)
@ -681,7 +588,7 @@ public:
{ {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN)
{ {
while (pos != _t->vertices_end() && !is_canonical() ) while (pos != _t->vertices_end() && !_t->is_canonical(pos) )
++pos; ++pos;
} }
} }
@ -705,7 +612,7 @@ public:
{ {
++pos; ++pos;
} }
while (pos != _t->vertices_end() && !is_canonical()); while (pos != _t->vertices_end() && !_t->is_canonical(pos));
break; break;
default: default:
CGAL_assertion(false); CGAL_assertion(false);
@ -727,7 +634,7 @@ public:
{ {
--pos; --pos;
} }
while (pos != _t->vertices_begin() && !is_canonical()); while (pos != _t->vertices_begin() && !_t->is_canonical(pos));
break; break;
default: default:
CGAL_assertion(false); CGAL_assertion(false);
@ -785,14 +692,6 @@ private:
mutable Periodic_point periodic_point; // current point. mutable Periodic_point periodic_point; // current point.
private: private:
// check whether pos points onto a vertex inside the original
// domain. If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical()
{
return (_t->get_offset(pos).is_null());
}
Periodic_point construct_periodic_point() const Periodic_point construct_periodic_point() const
{ {
CGAL_assertion(pos != typename T::Vertex_handle()); CGAL_assertion(pos != typename T::Vertex_handle());
@ -801,23 +700,91 @@ private:
} }
}; };
namespace Periodic_2_triangulation_2_internal namespace Periodic_2_triangulation_2_internal {
{
// returns `true` if the simplex is not canonical, and has to be filtered out
template <class T> template <class T>
class Domain_tester class Domain_tester
{ {
const T *t; typedef typename T::Offset Offset;
public: const T *t;
Domain_tester() {}
Domain_tester(const T *tr) : t(tr) {}
bool operator()(const typename T::Vertex_iterator & v) const public:
Domain_tester() {}
Domain_tester(const T *tr) : t(tr) {}
bool operator()(const typename T::Vertex_iterator v) const
{
return !(t->get_offset(v).is_null());
}
bool operator()(const typename T::Edge_iterator e) const
{
Offset eo_0 = t->int_to_off(e->first->offset(t->cw(e->second)));
Offset eo_1 = t->int_to_off(e->first->offset(t->ccw(e->second)));
Offset diff_off((eo_0.x() == 1 && eo_1.x() == 1) ? -1 : 0,
(eo_0.y() == 1 && eo_1.y() == 1) ? -1 : 0);
Offset off0 = t->combine_offsets(t->get_offset(e->first, t->cw(e->second)), diff_off);
Offset off1 = t->combine_offsets(t->get_offset(e->first, t->ccw(e->second)), diff_off);
if (t->number_of_sheets() != make_array(1, 1))
{ {
return (t->get_offset(v) != typename T::Offset(0, 0)); // If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical edge.
if (off0.x() > 1) return true;
if (off0.y() > 1) return true;
if (off1.x() > 1) return true;
if (off1.y() > 1) return true;
} }
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x();
int offy = off0.y() & off1.y();
return (offx != 0 || offy != 0);
}
bool operator()(const typename T::Face_iterator f) const
{
Offset fo_0 = t->int_to_off(f->offset(0));
Offset fo_1 = t->int_to_off(f->offset(1));
Offset fo_2 = t->int_to_off(f->offset(2));
Offset diff_off((fo_0.x() == 1 && fo_1.x() == 1 && fo_2.x() == 1) ? -1 : 0,
(fo_0.y() == 1 && fo_1.y() == 1 && fo_2.y() == 1) ? -1 : 0);
Offset off0 = t->combine_offsets(t->get_offset(f, 0), diff_off);
Offset off1 = t->combine_offsets(t->get_offset(f, 1), diff_off);
Offset off2 = t->combine_offsets(t->get_offset(f, 2), diff_off);
if (t->number_of_sheets() != make_array(1, 1))
{
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return true;
if (off0.y() > 1) return true;
if (off1.x() > 1) return true;
if (off1.y() > 1) return true;
if (off2.x() > 1) return true;
if (off2.y() > 1) return true;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
return (offx != 0 || offy != 0);
}
}; };
}
} // Periodic_2_triangulation_2_internal
// Iterates over the vertices in a periodic triangulation that are // Iterates over the vertices in a periodic triangulation that are
// located inside the original cube. // located inside the original cube.
@ -872,6 +839,108 @@ public:
} }
}; };
} //namespace CGAL // Iterates over the canonical edges in a periodic triangulation.
// Derives from Filter_iterator in order to add a conversion to handle
//
// Comments:
// When computing in 1-sheeted covering, there will be no difference
// between a normal Edge_iterator and this iterator
template <class T>
class Periodic_2_triangulation_unique_edge_iterator_2
: public Filter_iterator<typename T::Edge_iterator, Periodic_2_triangulation_2_internal::Domain_tester<T> >
{
typedef typename T::Edge Edge;
typedef typename T::Edge_iterator Edge_iterator;
typedef typename Periodic_2_triangulation_2_internal::Domain_tester<T> Tester;
typedef Filter_iterator<Edge_iterator, Tester > Base;
typedef Periodic_2_triangulation_unique_edge_iterator_2 Self;
public:
Periodic_2_triangulation_unique_edge_iterator_2() : Base() {}
Periodic_2_triangulation_unique_edge_iterator_2(const Base &b) : Base(b) {}
Self & operator++()
{
Base::operator++();
return *this;
}
Self & operator--()
{
Base::operator--();
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++(*this);
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
--(*this);
return tmp;
}
operator Edge() const
{
return Base::base();
}
};
// Iterates over the canonical faces in a periodic triangulation.
// Derives from Filter_iterator in order to add a conversion to handle
//
// Comments:
// When computing in 1-sheeted covering, there will be no difference
// between a normal Face_iterator and this iterator
template <class T>
class Periodic_2_triangulation_unique_face_iterator_2
: public Filter_iterator<typename T::Face_iterator, Periodic_2_triangulation_2_internal::Domain_tester<T> >
{
typedef typename T::Face_handle Face_handle;
typedef typename T::Face_iterator Face_iterator;
typedef typename Periodic_2_triangulation_2_internal::Domain_tester<T> Tester;
typedef Filter_iterator<Face_iterator, Tester > Base;
typedef Periodic_2_triangulation_unique_face_iterator_2 Self;
public:
Periodic_2_triangulation_unique_face_iterator_2() : Base() {}
Periodic_2_triangulation_unique_face_iterator_2(const Base &b) : Base(b) {}
Self & operator++()
{
Base::operator++();
return *this;
}
Self & operator--()
{
Base::operator--();
return *this;
}
Self operator++(int)
{
Self tmp(*this);
++(*this);
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
--(*this);
return tmp;
}
operator Face_handle() const
{
return Base::base();
}
};
} // namespace CGAL
#endif // CGAL_PERIODIC_2_TRIANGULATION_ITERATORS_2_H #endif // CGAL_PERIODIC_2_TRIANGULATION_ITERATORS_2_H

View File

@ -217,19 +217,19 @@ void test_iterators()
} }
assert(size == t_const.number_of_stored_vertices()); assert(size == t_const.number_of_stored_vertices());
size = 0; size = 0;
for (typename T::Unique_vertex_iterator uvit = t_const.unique_vertices_begin();
uvit != t_const.unique_vertices_end(); ++uvit)
{
++size;
}
assert(size == t_const.number_of_vertices());
size = 0;
for (typename T::Vertex_iterator vit = t_const.all_vertices_begin(); for (typename T::Vertex_iterator vit = t_const.all_vertices_begin();
vit != t_const.all_vertices_end(); ++vit) vit != t_const.all_vertices_end(); ++vit)
{ {
++size; ++size;
} }
assert(size == t_const.number_of_stored_vertices()); assert(size == t_const.number_of_stored_vertices());
size = 0;
for (typename T::Unique_vertex_iterator uvit = t_const.unique_vertices_begin();
uvit != t_const.unique_vertices_end(); ++uvit)
{
++size;
}
assert(size == t_const.number_of_vertices());
// edges // edges
size = 0; size = 0;
@ -246,6 +246,13 @@ void test_iterators()
++size; ++size;
} }
assert(size == t_const.number_of_stored_edges()); assert(size == t_const.number_of_stored_edges());
size = 0;
for (typename T::Unique_edge_iterator uvit = t_const.unique_edges_begin();
uvit != t_const.unique_edges_end(); ++uvit)
{
++size;
}
assert(size == t_const.number_of_edges());
// faces // faces
size = 0; size = 0;
@ -262,6 +269,13 @@ void test_iterators()
++size; ++size;
} }
assert(size == t_const.number_of_stored_faces()); assert(size == t_const.number_of_stored_faces());
size = 0;
for (typename T::Unique_face_iterator uvit = t_const.unique_faces_begin();
uvit != t_const.unique_faces_end(); ++uvit)
{
++size;
}
assert(size == t_const.number_of_faces());
/// Geometric iterators /// Geometric iterators
for (typename T::Periodic_point_iterator ppit = t_const.periodic_points_begin(); for (typename T::Periodic_point_iterator ppit = t_const.periodic_points_begin();

View File

@ -169,6 +169,13 @@ public:
typedef Facet_iterator All_facets_iterator; typedef Facet_iterator All_facets_iterator;
typedef Edge_iterator All_edges_iterator; typedef Edge_iterator All_edges_iterator;
typedef Vertex_iterator All_vertices_iterator; typedef Vertex_iterator All_vertices_iterator;
typedef Periodic_3_triangulation_unique_cell_iterator_3<Self>
Unique_cell_iterator;
typedef Periodic_3_triangulation_unique_facet_iterator_3<Self>
Unique_facet_iterator;
typedef Periodic_3_triangulation_unique_edge_iterator_3<Self>
Unique_edge_iterator;
typedef Periodic_3_triangulation_unique_vertex_iterator_3<Self> typedef Periodic_3_triangulation_unique_vertex_iterator_3<Self>
Unique_vertex_iterator; Unique_vertex_iterator;
@ -397,26 +404,14 @@ public:
} }
const Covering_sheets& number_of_sheets() const { return _cover; } const Covering_sheets& number_of_sheets() const { return _cover; }
const std::pair<Vertex_handle, Offset> original_vertex(const Vertex_handle v) const
{
return (virtual_vertices.find(v) == virtual_vertices.end()) ?
std::make_pair(v,Offset()) : virtual_vertices.find(v)->second;
}
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
{
CGAL_precondition(number_of_sheets() != CGAL::make_array(1,1,1));
CGAL_precondition(virtual_vertices.find(v) == virtual_vertices.end());
CGAL_assertion(
virtual_vertices_reverse.find(v) != virtual_vertices_reverse.end());
return virtual_vertices_reverse.find(v)->second;
}
bool is_triangulation_in_1_sheet() const; bool is_triangulation_in_1_sheet() const;
void convert_to_1_sheeted_covering(); void convert_to_1_sheeted_covering();
virtual void update_cover_data_after_converting_to_27_sheeted_covering() { } virtual void update_cover_data_after_converting_to_27_sheeted_covering() { }
void convert_to_27_sheeted_covering(); void convert_to_27_sheeted_covering();
public:
size_type number_of_cells() const { size_type number_of_cells() const {
if(is_1_cover()) return _tds.number_of_cells(); if(is_1_cover()) return _tds.number_of_cells();
else return _tds.number_of_cells()/27; else return _tds.number_of_cells()/27;
@ -460,14 +455,6 @@ public:
_cover = cover; _cover = cover;
} }
public:
bool is_virtual(Vertex_handle v)
{
if(is_1_cover())
return false;
return (virtual_vertices.find(v) != virtual_vertices.end());
}
public: public:
// Offset converters // Offset converters
int off_to_int(const Offset& off) const int off_to_int(const Offset& off) const
@ -549,6 +536,232 @@ public:
c->set_offsets(o0i,o1i,o2i,o3i); c->set_offsets(o0i,o1i,o2i,o3i);
} }
public:
// undocumented access functions
Offset get_offset(Cell_handle ch, int i) const
{
if(is_1_cover())
return int_to_off(ch->offset(i));
Virtual_vertex_map_it it = virtual_vertices.find(ch->vertex(i));
if(it != virtual_vertices.end())
return combine_offsets(it->second.second, int_to_off(ch->offset(i)));
else
return combine_offsets(Offset(), int_to_off(ch->offset(i)));
}
Offset get_offset(Vertex_handle vh) const
{
if(is_1_cover())
return Offset();
Virtual_vertex_map_it it = virtual_vertices.find(vh);
if(it != virtual_vertices.end())
return it->second.second;
else
return Offset();
}
// Get the canonicalized offsets of a cell.
void get_offsets(Cell_handle ch,
Offset& off0, Offset& off1, Offset& off2, Offset& off3) const
{
Offset cell_off0 = int_to_off(ch->offset(0));
Offset cell_off1 = int_to_off(ch->offset(1));
Offset cell_off2 = int_to_off(ch->offset(2));
Offset cell_off3 = int_to_off(ch->offset(3));
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1 &&
cell_off2.x() == 1 && cell_off3.x() == 1) ? -1 : 0,
(cell_off0.y() == 1 && cell_off1.y() == 1 &&
cell_off2.y() == 1 && cell_off3.y() == 1) ? -1 : 0,
(cell_off0.z() == 1 && cell_off1.z() == 1 &&
cell_off2.z() == 1 && cell_off3.z() == 1) ? -1 : 0);
off0 = combine_offsets(get_offset(ch,0), diff_off);
off1 = combine_offsets(get_offset(ch,1), diff_off);
off2 = combine_offsets(get_offset(ch,2), diff_off);
off3 = combine_offsets(get_offset(ch,3), diff_off);
}
// Gets the canonicalized offsets of a face.
void get_offsets(const Facet& f,
Offset& off0, Offset& off1, Offset& off2) const
{
Offset cell_off0 = int_to_off(f.first->offset((f.second+1)&3));
Offset cell_off1 = int_to_off(f.first->offset((f.second+2)&3));
Offset cell_off2 = int_to_off(f.first->offset((f.second+3)&3));
Offset diff_off((cell_off0.x() == 1 && cell_off1.x() == 1 && cell_off2.x() == 1) ? -1 : 0,
(cell_off0.y() == 1 && cell_off1.y() == 1 && cell_off2.y() == 1) ? -1 : 0,
(cell_off0.z() == 1 && cell_off1.z() == 1 && cell_off2.z() == 1) ? -1 : 0);
off0 = combine_offsets(get_offset(f.first, (f.second+1)&3), diff_off);
off1 = combine_offsets(get_offset(f.first, (f.second+2)&3), diff_off);
off2 = combine_offsets(get_offset(f.first, (f.second+3)&3), diff_off);
}
// Gets the canonicalized offsets of an edge.
void get_offsets(const Edge& e,
Offset& off0, Offset& off1) const
{
Offset cell_off0 = int_to_off(e.first->offset(e.second));
Offset cell_off1 = int_to_off(e.first->offset(e.third));
Offset diff_off((cell_off0.x()==1 && cell_off1.x()==1) ? -1 : 0,
(cell_off0.y()==1 && cell_off1.y()==1) ? -1 : 0,
(cell_off0.z()==1 && cell_off1.z()==1) ? -1 : 0);
off0 = combine_offsets(get_offset(e.first, e.second), diff_off);
off1 = combine_offsets(get_offset(e.first, e.third), diff_off);
}
public:
Offset combine_offsets(const Offset& o_c, const Offset& o_t) const
{
Offset o_ct(_cover[0]*o_t.x(), _cover[1]*o_t.y(), _cover[2]*o_t.z());
return o_c + o_ct;
}
public:
Offset neighbor_offset(Cell_handle ch, int i, Cell_handle nb) const;
Offset neighbor_offset(Cell_handle ch, int i) const
{
return neighbor_offset(ch, i, ch->neighbor(i));
}
public:
/// Tests whether a vertex is a periodic copy of a vertex in the 3-cover.
bool is_virtual(Vertex_handle vh) const
{
if(is_1_cover())
return false;
return (virtual_vertices.find(vh) != virtual_vertices.end());
}
/// Returns the non-virtual (i.e. canonical) copy of the vertex.
Vertex_handle get_original_vertex(Vertex_handle vh) const
{
if(is_1_cover())
return vh;
Virtual_vertex_map_it it = virtual_vertices.find(vh);
if(it != virtual_vertices.end())
return it->second.first;
else
return vh;
}
const std::pair<Vertex_handle, Offset> original_vertex(const Vertex_handle v) const
{
return (virtual_vertices.find(v) == virtual_vertices.end()) ?
std::make_pair(v,Offset()) : virtual_vertices.find(v)->second;
}
const std::vector<Vertex_handle>& periodic_copies(const Vertex_handle v) const
{
CGAL_precondition(number_of_sheets() != CGAL::make_array(1,1,1));
CGAL_precondition(virtual_vertices.find(v) == virtual_vertices.end());
CGAL_assertion(
virtual_vertices_reverse.find(v) != virtual_vertices_reverse.end());
return virtual_vertices_reverse.find(v)->second;
}
public:
bool is_canonical(Cell_handle ch) const
{
if(is_1_cover())
return true;
Offset off0, off1, off2, off3;
get_offsets(ch, off0, off1, off2, off3);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off0.z() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off1.z() > 1) return false;
if (off2.x() > 1) return false;
if (off2.y() > 1) return false;
if (off2.z() > 1) return false;
if (off3.x() > 1) return false;
if (off3.y() > 1) return false;
if (off3.z() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x() & off3.x();
int offy = off0.y() & off1.y() & off2.y() & off3.y();
int offz = off0.z() & off1.z() & off2.z() & off3.z();
return (offx == 0 && offy == 0 && offz == 0);
}
bool is_canonical(const Edge& e) const
{
if(is_1_cover())
return true;
Offset off0, off1;
get_offsets(e, off0, off1);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical edge.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off0.z() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off1.z() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x();
int offy = off0.y() & off1.y();
int offz = off0.z() & off1.z();
return (offx == 0 && offy == 0 && offz == 0);
}
bool is_canonical(const Facet& f) const
{
if(is_1_cover())
return true;
Offset off0, off1, off2;
get_offsets(f, off0, off1, off2);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if(off0.x() > 1) return false;
if(off0.y() > 1) return false;
if(off0.z() > 1) return false;
if(off1.x() > 1) return false;
if(off1.y() > 1) return false;
if(off1.z() > 1) return false;
if(off2.x() > 1) return false;
if(off2.y() > 1) return false;
if(off2.z() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the facet is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
int offz = off0.z() & off1.z() & off2.z();
return (offx == 0 && offy == 0 && offz == 0);
}
/// Tests whether a vertex belongs to the original (canonical) domain.
bool is_canonical(Vertex_handle vh) const
{
return !is_virtual(vh);
}
public: public:
/** @name Wrapping the traits */ /** @name Wrapping the traits */
// Note that calling functors with "construct_point(p), offset" and not // Note that calling functors with "construct_point(p), offset" and not
@ -988,6 +1201,14 @@ public:
// end of geometric functions // end of geometric functions
public: public:
// These functions give the pair (vertex, offset) that corresponds to the
// i-th vertex of cell ch or vertex vh, respectively.
void get_vertex(Cell_handle ch, int i, Vertex_handle& vh, Offset& off) const;
void get_vertex(Vertex_handle vh_i, Vertex_handle& vh, Offset& off) const;
// Auxiliary functions
Cell_handle get_cell(const Vertex_handle* vh) const;
/** @name Queries */ /** @name Queries */
bool is_vertex(const Point& p, Vertex_handle& v) const; bool is_vertex(const Point& p, Vertex_handle& v) const;
@ -1305,6 +1526,14 @@ public:
std::vector<Vertex_handle> insert_generic_dummy_points(); std::vector<Vertex_handle> insert_generic_dummy_points();
protected: protected:
template<class Conflict_tester>
Offset get_location_offset(const Conflict_tester& tester,
Cell_handle c) const;
template<class Conflict_tester>
Offset get_location_offset(const Conflict_tester& tester,
Cell_handle c, bool& found) const;
// this is needed for compatibility reasons // this is needed for compatibility reasons
template <class Conflict_test, class OutputIteratorBoundaryFacets, template <class Conflict_test, class OutputIteratorBoundaryFacets,
class OutputIteratorCells, class OutputIteratorInternalFacets> class OutputIteratorCells, class OutputIteratorInternalFacets>
@ -1530,6 +1759,16 @@ public:
return _tds.facets_end(); return _tds.facets_end();
} }
// Unique iterators
Unique_cell_iterator unique_cells_begin() const {
return CGAL::filter_iterator(cells_end(), Domain_tester<Self>(this),
cells_begin());
}
Unique_cell_iterator unique_cells_end() const {
return CGAL::filter_iterator(cells_end(), Domain_tester<Self>(this));
}
Unique_vertex_iterator unique_vertices_begin() const { Unique_vertex_iterator unique_vertices_begin() const {
return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this), return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this),
vertices_begin()); vertices_begin());
@ -1538,6 +1777,22 @@ public:
return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this)); return CGAL::filter_iterator(vertices_end(), Domain_tester<Self>(this));
} }
Unique_edge_iterator unique_edges_begin() const {
return CGAL::filter_iterator(edges_end(), Domain_tester<Self>(this),
edges_begin());
}
Unique_edge_iterator unique_edges_end() const {
return CGAL::filter_iterator(edges_end(), Domain_tester<Self>(this));
}
Unique_facet_iterator unique_facets_begin() const {
return CGAL::filter_iterator(facets_end(), Domain_tester<Self>(this),
facets_begin());
}
Unique_facet_iterator unique_facets_end() const {
return CGAL::filter_iterator(facets_end(), Domain_tester<Self>(this));
}
// Geometric iterators // Geometric iterators
Periodic_tetrahedron_iterator periodic_tetrahedra_begin( Periodic_tetrahedron_iterator periodic_tetrahedra_begin(
Iterator_type it = STORED) const { Iterator_type it = STORED) const {
@ -1695,75 +1950,6 @@ public:
} }
}; };
public:
// undocumented access functions
Offset get_offset(Cell_handle ch, int i) const
{
if(is_1_cover())
return int_to_off(ch->offset(i));
Virtual_vertex_map_it it = virtual_vertices.find(ch->vertex(i));
if(it != virtual_vertices.end())
return combine_offsets(it->second.second, int_to_off(ch->offset(i)));
else
return combine_offsets(Offset(), int_to_off(ch->offset(i)));
}
Offset get_offset(Vertex_handle vh) const
{
if(is_1_cover())
return Offset();
Virtual_vertex_map_it it = virtual_vertices.find(vh);
if(it != virtual_vertices.end())
return it->second.second;
else
return Offset();
}
Vertex_handle get_original_vertex(Vertex_handle vh) const
{
if(is_1_cover())
return vh;
Virtual_vertex_map_it it = virtual_vertices.find(vh);
if(it != virtual_vertices.end())
return it->second.first;
else
return vh;
}
Offset combine_offsets(const Offset& o_c, const Offset& o_t) const
{
Offset o_ct(_cover[0]*o_t.x(), _cover[1]*o_t.y(), _cover[2]*o_t.z());
return o_c + o_ct;
}
// These functions give the pair (vertex, offset) that corresponds to the
// i-th vertex of cell ch or vertex vh, respectively.
void get_vertex(Cell_handle ch, int i, Vertex_handle& vh, Offset& off) const;
void get_vertex(Vertex_handle vh_i, Vertex_handle& vh, Offset& off) const;
protected:
// Auxiliary functions
Cell_handle get_cell(const Vertex_handle* vh) const;
template<class Conflict_tester>
Offset get_location_offset(const Conflict_tester& tester,
Cell_handle c) const;
template<class Conflict_tester>
Offset get_location_offset(const Conflict_tester& tester,
Cell_handle c, bool& found) const;
Offset neighbor_offset(Cell_handle ch, int i, Cell_handle nb) const;
public:
Offset neighbor_offset(Cell_handle ch, int i) const
{
return neighbor_offset(ch, i, ch->neighbor(i));
}
protected: protected:
/** @name Friends */ /** @name Friends */
friend std::istream& operator>> <> friend std::istream& operator>> <>
@ -1788,51 +1974,6 @@ protected:
return construct_periodic_point(p); return construct_periodic_point(p);
} }
public:
bool is_canonical(const Facet& f) const
{
if(number_of_sheets() == CGAL::make_array(1,1,1))
return true;
Offset cell_off0 = int_to_off(f.first->offset((f.second+1)&3));
Offset cell_off1 = int_to_off(f.first->offset((f.second+2)&3));
Offset cell_off2 = int_to_off(f.first->offset((f.second+3)&3));
Offset diff_off((cell_off0.x() == 1
&& cell_off1.x() == 1
&& cell_off2.x() == 1) ? -1 : 0,
(cell_off0.y() == 1
&& cell_off1.y() == 1
&& cell_off2.y() == 1) ? -1 : 0,
(cell_off0.z() == 1
&& cell_off1.z() == 1
&& cell_off2.z() == 1) ? -1 : 0);
Offset off0 = combine_offsets(get_offset(f.first, (f.second+1)&3), diff_off);
Offset off1 = combine_offsets(get_offset(f.first, (f.second+2)&3), diff_off);
Offset off2 = combine_offsets(get_offset(f.first, (f.second+3)&3), diff_off);
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if(off0.x() > 1) return false;
if(off0.y() > 1) return false;
if(off0.z() > 1) return false;
if(off1.x() > 1) return false;
if(off1.y() > 1) return false;
if(off1.z() > 1) return false;
if(off2.x() > 1) return false;
if(off2.y() > 1) return false;
if(off2.z() > 1) return false;
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
int offz = off0.z() & off1.z() & off2.z();
return (offx == 0 && offy == 0 && offz == 0);
}
protected: protected:
template <class ConstructCircumcenter> template <class ConstructCircumcenter>
bool canonical_dual_segment(Cell_handle c, int i, Periodic_segment_3& ps, bool canonical_dual_segment(Cell_handle c, int i, Periodic_segment_3& ps,

View File

@ -63,7 +63,7 @@ public:
Iterator_type it = T::STORED) Iterator_type it = T::STORED)
: _t(t), pos(_t->cells_begin()), _it(it), _off(0) { : _t(t), pos(_t->cells_begin()), _it(it), _off(0) {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) { if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
while (pos != _t->cells_end() && !is_canonical() ) while (pos != _t->cells_end() && !_t->is_canonical(pos) )
++pos; ++pos;
} }
} }
@ -79,7 +79,7 @@ public:
++pos; ++pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { ++pos; } while (pos != _t->cells_end() && !is_canonical()); do { ++pos; } while (pos != _t->cells_end() && !_t->is_canonical(pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -97,7 +97,7 @@ public:
--pos; --pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { --pos; } while (pos != _t->cells_begin() && !is_canonical()); do { --pos; } while (pos != _t->cells_begin() && !_t->is_canonical(pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -156,42 +156,6 @@ private:
mutable Periodic_tetrahedron periodic_tetrahedron; // current tetrahedron. mutable Periodic_tetrahedron periodic_tetrahedron; // current tetrahedron.
private: private:
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical() {
// fetch all offsets
Offset off0, off1, off2, off3;
get_edge_offsets(off0, off1, off2, off3);
if (_t->number_of_sheets() != make_array(1,1,1)) {
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off0.z() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off1.z() > 1) return false;
if (off2.x() > 1) return false;
if (off2.y() > 1) return false;
if (off2.z() > 1) return false;
if (off3.x() > 1) return false;
if (off3.y() > 1) return false;
if (off3.z() > 1) return false;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x() & off3.x();
int offy = off0.y() & off1.y() & off2.y() & off3.y();
int offz = off0.z() & off1.z() & off2.z() & off3.z();
return (offx == 0 && offy == 0 && offz == 0);
}
// Artificial incrementation function that takes periodic // Artificial incrementation function that takes periodic
// copies into account. // copies into account.
void increment_domain() { void increment_domain() {
@ -200,7 +164,7 @@ private:
if (_off == off) { if (_off == off) {
_off = 0; _off = 0;
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
&& pos != _t->cells_end() && !is_canonical()); && pos != _t->cells_end() && !_t->is_canonical(pos));
} else { } else {
do { do {
++_off; ++_off;
@ -214,7 +178,7 @@ private:
void decrement_domain() { void decrement_domain() {
if (_off == 0) { if (_off == 0) {
if (pos == _t->cells_begin()) return; if (pos == _t->cells_begin()) return;
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(pos));
_off = get_drawing_offsets(); _off = get_drawing_offsets();
} else { } else {
int off = get_drawing_offsets(); int off = get_drawing_offsets();
@ -225,32 +189,6 @@ private:
} }
} }
// Get the canonicalized offsets of an edge.
// This works in any cover that is encoded in _t->combine_offsets
void get_edge_offsets(Offset &off0, Offset &off1,
Offset &off2, Offset &off3) const {
Offset cell_off0 = _t->int_to_off(pos->offset(0));
Offset cell_off1 = _t->int_to_off(pos->offset(1));
Offset cell_off2 = _t->int_to_off(pos->offset(2));
Offset cell_off3 = _t->int_to_off(pos->offset(3));
Offset diff_off((cell_off0.x() == 1
&& cell_off1.x() == 1
&& cell_off2.x() == 1
&& cell_off3.x() == 1)?-1:0,
(cell_off0.y() == 1
&& cell_off1.y() == 1
&& cell_off2.y() == 1
&& cell_off3.y() == 1)?-1:0,
(cell_off0.z() == 1
&& cell_off1.z() == 1
&& cell_off2.z() == 1
&& cell_off3.z() == 1)?-1:0);
off0 = _t->combine_offsets(_t->get_offset(pos,0), diff_off);
off1 = _t->combine_offsets(_t->get_offset(pos,1), diff_off);
off2 = _t->combine_offsets(_t->get_offset(pos,2), diff_off);
off3 = _t->combine_offsets(_t->get_offset(pos,3), diff_off);
}
// return an integer that encodes the translations which have to be // return an integer that encodes the translations which have to be
// applied to the edge *pos // applied to the edge *pos
int get_drawing_offsets() { int get_drawing_offsets() {
@ -262,7 +200,7 @@ private:
// internally stored inside the cell telling us that this cell // internally stored inside the cell telling us that this cell
// wraps around the domain. // wraps around the domain.
if (_it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE_COVER_DOMAIN)
get_edge_offsets(off0,off1,off2,off3); _t->get_offsets(pos, off0, off1, off2, off3);
else { else {
CGAL_assertion(_it == T::STORED_COVER_DOMAIN); CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
off0 = _t->int_to_off(pos->offset(0)); off0 = _t->int_to_off(pos->offset(0));
@ -303,7 +241,7 @@ private:
Periodic_tetrahedron construct_periodic_tetrahedron() const { Periodic_tetrahedron construct_periodic_tetrahedron() const {
CGAL_assertion(pos != typename T::Cell_handle()); CGAL_assertion(pos != typename T::Cell_handle());
Offset off0, off1, off2, off3; Offset off0, off1, off2, off3;
get_edge_offsets(off0, off1, off2, off3); _t->get_offsets(pos, off0, off1, off2, off3);
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0), Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
(((_off>>1)&1)==1 ? -1:0), (((_off>>1)&1)==1 ? -1:0),
(( _off &1)==1 ? -1:0)); (( _off &1)==1 ? -1:0));
@ -369,7 +307,7 @@ public:
Iterator_type it = T::STORED) Iterator_type it = T::STORED)
: _t(t), pos(_t->facets_begin()), _it(it), _off(0) { : _t(t), pos(_t->facets_begin()), _it(it), _off(0) {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) { if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
while (pos != _t->facets_end() && !is_canonical() ) while (pos != _t->facets_end() && !_t->is_canonical(*pos) )
++pos; ++pos;
} }
} }
@ -385,7 +323,7 @@ public:
++pos; ++pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { ++pos; } while (pos != _t->facets_end() && !is_canonical()); do { ++pos; } while (pos != _t->facets_end() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -403,7 +341,7 @@ public:
--pos; --pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { --pos; } while (pos != _t->facets_begin() && !is_canonical()); do { --pos; } while (pos != _t->facets_begin() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -462,39 +400,6 @@ private:
mutable Periodic_triangle periodic_triangle; // current segment. mutable Periodic_triangle periodic_triangle; // current segment.
private: private:
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical() {
// fetch all offsets
Offset off0, off1, off2;
get_edge_offsets(off0, off1, off2);
if (_t->number_of_sheets() != make_array(1,1,1)) {
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off0.z() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off1.z() > 1) return false;
if (off2.x() > 1) return false;
if (off2.y() > 1) return false;
if (off2.z() > 1) return false;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x() & off2.x();
int offy = off0.y() & off1.y() & off2.y();
int offz = off0.z() & off1.z() & off2.z();
return (offx == 0 && offy == 0 && offz == 0);
}
// Artificial incrementation function that takes periodic // Artificial incrementation function that takes periodic
// copies into account. // copies into account.
void increment_domain() { void increment_domain() {
@ -503,7 +408,7 @@ private:
if (_off == off) { if (_off == off) {
_off = 0; _off = 0;
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
&& pos != _t->facets_end() && !is_canonical()); && pos != _t->facets_end() && !_t->is_canonical(*pos));
} else { } else {
do { do {
++_off; ++_off;
@ -517,7 +422,7 @@ private:
void decrement_domain() { void decrement_domain() {
if (_off == 0) { if (_off == 0) {
if (pos == _t->facets_begin()) return; if (pos == _t->facets_begin()) return;
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
_off = get_drawing_offsets(); _off = get_drawing_offsets();
} else { } else {
int off = get_drawing_offsets(); int off = get_drawing_offsets();
@ -528,32 +433,6 @@ private:
} }
} }
// Get the canonicalized offsets of an edge.
// This works in any cover that is encoded in _t->combine_offsets
void get_edge_offsets(Offset &off0, Offset &off1, Offset &off2) const {
Offset cell_off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3));
Offset cell_off1 = _t->int_to_off(pos->first->offset((pos->second+2)&3));
Offset cell_off2 = _t->int_to_off(pos->first->offset((pos->second+3)&3));
Offset diff_off((cell_off0.x() == 1
&& cell_off1.x() == 1
&& cell_off2.x() == 1)?-1:0,
(cell_off0.y() == 1
&& cell_off1.y() == 1
&& cell_off2.y() == 1)?-1:0,
(cell_off0.z() == 1
&& cell_off1.z() == 1
&& cell_off2.z() == 1)?-1:0);
off0 = _t->combine_offsets(_t->get_offset(pos->first,
(pos->second+1)&3),
diff_off);
off1 = _t->combine_offsets(_t->get_offset(pos->first,
(pos->second+2)&3),
diff_off);
off2 = _t->combine_offsets(_t->get_offset(pos->first,
(pos->second+3)&3),
diff_off);
}
// return an integer that encodes the translations which have to be // return an integer that encodes the translations which have to be
// applied to the edge *pos // applied to the edge *pos
int get_drawing_offsets() { int get_drawing_offsets() {
@ -565,7 +444,7 @@ private:
// internally stored inside the cell telling us that this cell // internally stored inside the cell telling us that this cell
// wraps around the domain. // wraps around the domain.
if (_it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE_COVER_DOMAIN)
get_edge_offsets(off0,off1,off2); _t->get_offsets(*pos, off0, off1, off2);
else { else {
CGAL_assertion(_it == T::STORED_COVER_DOMAIN); CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3)); off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3));
@ -596,7 +475,7 @@ private:
Periodic_triangle construct_periodic_triangle() const { Periodic_triangle construct_periodic_triangle() const {
CGAL_assertion(pos->first != typename T::Cell_handle()); CGAL_assertion(pos->first != typename T::Cell_handle());
Offset off0, off1, off2; Offset off0, off1, off2;
get_edge_offsets(off0, off1, off2); _t->get_offsets(*pos, off0, off1, off2);
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0), Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
(((_off>>1)&1)==1 ? -1:0), (((_off>>1)&1)==1 ? -1:0),
(( _off &1)==1 ? -1:0)); (( _off &1)==1 ? -1:0));
@ -659,7 +538,7 @@ public:
Iterator_type it = T::STORED) Iterator_type it = T::STORED)
: _t(t), pos(_t->edges_begin()), _it(it), _off(0) { : _t(t), pos(_t->edges_begin()), _it(it), _off(0) {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) { if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
while (pos != _t->edges_end() && !is_canonical() ) while (pos != _t->edges_end() && !_t->is_canonical(*pos) )
++pos; ++pos;
} }
} }
@ -675,7 +554,7 @@ public:
++pos; ++pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { ++pos; } while (pos != _t->edges_end() && !is_canonical()); do { ++pos; } while (pos != _t->edges_end() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -693,7 +572,7 @@ public:
--pos; --pos;
break; break;
case T::UNIQUE: case T::UNIQUE:
do { --pos; } while (pos != _t->edges_begin() && !is_canonical()); do { --pos; } while (pos != _t->edges_begin() && !_t->is_canonical(*pos));
break; break;
case T::STORED_COVER_DOMAIN: case T::STORED_COVER_DOMAIN:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
@ -751,36 +630,6 @@ private:
mutable Periodic_segment periodic_segment; // current segment. mutable Periodic_segment periodic_segment; // current segment.
private: private:
// check whether pos points onto a unique edge or not.
// If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical() {
// fetch all offsets
Offset off0, off1;
get_edge_offsets(off0, off1);
if (_t->number_of_sheets() != make_array(1,1,1)) {
// If there is one offset with entries larger than 1 then we are
// talking about a vertex that is too far away from the original
// domain to belong to a canonical triangle.
if (off0.x() > 1) return false;
if (off0.y() > 1) return false;
if (off0.z() > 1) return false;
if (off1.x() > 1) return false;
if (off1.y() > 1) return false;
if (off1.z() > 1) return false;
}
// If there is one direction of space for which all offsets are
// non-zero then the edge is not canonical because we can
// take the copy closer towards the origin in that direction.
int offx = off0.x() & off1.x();
int offy = off0.y() & off1.y();
int offz = off0.z() & off1.z();
return (offx == 0 && offy == 0 && offz == 0);
}
// Artificial incrementation function that takes periodic // Artificial incrementation function that takes periodic
// copies into account. // copies into account.
void increment_domain() { void increment_domain() {
@ -789,7 +638,7 @@ private:
if (_off == off) { if (_off == off) {
_off = 0; _off = 0;
do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN
&& pos != _t->edges_end() && !is_canonical()); && pos != _t->edges_end() && !_t->is_canonical(*pos));
} else { } else {
do { do {
++_off; ++_off;
@ -803,7 +652,7 @@ private:
void decrement_domain() { void decrement_domain() {
if (_off == 0) { if (_off == 0) {
if (pos == _t->edges_begin()) return; if (pos == _t->edges_begin()) return;
do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); do { --pos; } while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos));
_off = get_drawing_offsets(); _off = get_drawing_offsets();
} else { } else {
int off = get_drawing_offsets(); int off = get_drawing_offsets();
@ -814,20 +663,6 @@ private:
} }
} }
// Get the canonicalized offsets of an edge.
// This works in any cover that is encoded in _t->combine_offsets
void get_edge_offsets(Offset &off0, Offset &off1) const {
Offset cell_off0 = _t->int_to_off(pos->first->offset(pos->second));
Offset cell_off1 = _t->int_to_off(pos->first->offset(pos->third));
Offset diff_off((cell_off0.x()==1 && cell_off1.x()==1)?-1:0,
(cell_off0.y()==1 && cell_off1.y()==1)?-1:0,
(cell_off0.z()==1 && cell_off1.z()==1)?-1:0);
off0 = _t->combine_offsets(_t->get_offset(pos->first,pos->second),
diff_off);
off1 = _t->combine_offsets(_t->get_offset(pos->first,pos->third),
diff_off);
}
// return an integer that encodes the translations which have to be // return an integer that encodes the translations which have to be
// applied to the edge *pos // applied to the edge *pos
int get_drawing_offsets() { int get_drawing_offsets() {
@ -839,7 +674,7 @@ private:
// internally stored inside the cell telling us that this cell // internally stored inside the cell telling us that this cell
// wraps around the domain. // wraps around the domain.
if (_it == T::UNIQUE_COVER_DOMAIN) if (_it == T::UNIQUE_COVER_DOMAIN)
get_edge_offsets(off0,off1); _t->get_offsets(*pos, off0, off1);
else { else {
CGAL_assertion(_it == T::STORED_COVER_DOMAIN); CGAL_assertion(_it == T::STORED_COVER_DOMAIN);
off0 = _t->int_to_off(pos->first->offset(pos->second)); off0 = _t->int_to_off(pos->first->offset(pos->second));
@ -859,7 +694,7 @@ private:
Periodic_segment construct_periodic_segment() const { Periodic_segment construct_periodic_segment() const {
CGAL_assertion(pos->first != typename T::Cell_handle()); CGAL_assertion(pos->first != typename T::Cell_handle());
Offset off0, off1; Offset off0, off1;
get_edge_offsets(off0, off1); _t->get_offsets(*pos, off0, off1);
Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0), Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0),
(((_off>>1)&1)==1 ? -1:0), (((_off>>1)&1)==1 ? -1:0),
(( _off &1)==1 ? -1:0)); (( _off &1)==1 ? -1:0));
@ -918,7 +753,7 @@ public:
Iterator_type it = T::STORED) Iterator_type it = T::STORED)
: _t(t), pos(_t->vertices_begin()), _it(it) { : _t(t), pos(_t->vertices_begin()), _it(it) {
if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) { if (_it == T::UNIQUE || _it == T::UNIQUE_COVER_DOMAIN) {
while (pos != _t->vertices_end() && !is_canonical() ) while (pos != _t->vertices_end() && !_t->is_canonical(pos) )
++pos; ++pos;
} }
} }
@ -936,7 +771,7 @@ public:
break; break;
case T::UNIQUE: case T::UNIQUE:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
do { ++pos; } while (pos != _t->vertices_end() && !is_canonical()); do { ++pos; } while (pos != _t->vertices_end() && !_t->is_canonical(pos));
break; break;
default: default:
CGAL_assertion(false); CGAL_assertion(false);
@ -952,7 +787,7 @@ public:
break; break;
case T::UNIQUE: case T::UNIQUE:
case T::UNIQUE_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN:
do { --pos; } while (pos != _t->vertices_begin() && !is_canonical()); do { --pos; } while (pos != _t->vertices_begin() && !_t->is_canonical(pos));
break; break;
default: default:
CGAL_assertion(false); CGAL_assertion(false);
@ -1009,13 +844,6 @@ private:
mutable Periodic_point periodic_point; // current point. mutable Periodic_point periodic_point; // current point.
private: private:
// check whether pos points onto a vertex inside the original
// domain. If we are computing in 1-sheeted covering this should
// always be true.
bool is_canonical() {
return (_t->get_offset(pos) == Offset(0,0,0));
}
Periodic_point construct_periodic_point() const { Periodic_point construct_periodic_point() const {
CGAL_assertion(pos != typename T::Vertex_handle()); CGAL_assertion(pos != typename T::Vertex_handle());
Offset off = _t->get_offset(pos); Offset off = _t->get_offset(pos);
@ -1031,9 +859,54 @@ public:
Domain_tester() {} Domain_tester() {}
Domain_tester(const T *tr) : t(tr) {} Domain_tester(const T *tr) : t(tr) {}
bool operator()(const typename T::Vertex_iterator & v) const { bool operator()(const typename T::Cell_iterator c) const
return (t->get_offset(v) != typename T::Offset(0,0,0)); {
return !t->is_canonical(c);
} }
bool operator()(const typename T::Facet_iterator f) const
{
return !t->is_canonical(*f);
}
bool operator()(const typename T::Edge_iterator e) const
{
return !t->is_canonical(*e);
}
bool operator()(const typename T::Vertex_iterator v) const
{
return !t->is_canonical(v);
}
};
// Iterates over the canonical cells in a periodic triangulation.
// Derives from Filter_iterator in order to add a conversion to handle
//
// Comments:
// When computing in 1-sheeted covering, there will be no difference
// between a normal Cell_iterator and this iterator
template <class T>
class Periodic_3_triangulation_unique_cell_iterator_3
: public Filter_iterator<typename T::Cell_iterator, Domain_tester<T> >
{
typedef typename T::Cell_handle Cell_handle;
typedef typename T::Cell_iterator Cell_iterator;
typedef Filter_iterator<Cell_iterator, Domain_tester<T> > Base;
typedef Periodic_3_triangulation_unique_cell_iterator_3 Self;
public:
Periodic_3_triangulation_unique_cell_iterator_3() : Base() {}
Periodic_3_triangulation_unique_cell_iterator_3(const Base &b) : Base(b) {}
Self & operator++() { Base::operator++(); return *this; }
Self & operator--() { Base::operator--(); return *this; }
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
operator Cell_handle() const { return Base::base(); }
}; };
// Iterates over the vertices in a periodic triangulation that are // Iterates over the vertices in a periodic triangulation that are
@ -1065,6 +938,62 @@ public:
operator Vertex_handle() const { return Base::base(); } operator Vertex_handle() const { return Base::base(); }
}; };
} //namespace CGAL // Iterates over the canonical edges in a periodic triangulation.
// Derives from Filter_iterator in order to add a conversion to handle
//
// Comments:
// When computing in 1-sheeted covering, there will be no difference
// between a normal Edge_iterator and this iterator
template <class T>
class Periodic_3_triangulation_unique_edge_iterator_3
: public Filter_iterator<typename T::Edge_iterator, Domain_tester<T> >
{
typedef typename T::Edge Edge;
typedef typename T::Edge_iterator Edge_iterator;
typedef Filter_iterator<Edge_iterator, Domain_tester<T> > Base;
typedef Periodic_3_triangulation_unique_edge_iterator_3 Self;
public:
Periodic_3_triangulation_unique_edge_iterator_3() : Base() {}
Periodic_3_triangulation_unique_edge_iterator_3(const Base &b) : Base(b) {}
Self & operator++() { Base::operator++(); return *this; }
Self & operator--() { Base::operator--(); return *this; }
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
operator Edge() const { return Base::base(); }
};
// Iterates over the canonical facets in a periodic triangulation.
// Derives from Filter_iterator in order to add a conversion to handle
//
// Comments:
// When computing in 1-sheeted covering, there will be no difference
// between a normal Facet_iterator and this iterator
template <class T>
class Periodic_3_triangulation_unique_facet_iterator_3
: public Filter_iterator<typename T::Facet_iterator, Domain_tester<T> >
{
typedef typename T::Facet Facet;
typedef typename T::Facet_iterator Facet_iterator;
typedef Filter_iterator<Facet_iterator, Domain_tester<T> > Base;
typedef Periodic_3_triangulation_unique_facet_iterator_3 Self;
public:
Periodic_3_triangulation_unique_facet_iterator_3() : Base() {}
Periodic_3_triangulation_unique_facet_iterator_3(const Base &b) : Base(b) {}
Self & operator++() { Base::operator++(); return *this; }
Self & operator--() { Base::operator--(); return *this; }
Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
operator Facet() const { return Base::base(); }
};
} // namespace CGAL
#endif // CGAL_PERIODIC_3_TRIANGULATION_ITERATORS_3_H #endif // CGAL_PERIODIC_3_TRIANGULATION_ITERATORS_3_H

View File

@ -86,32 +86,158 @@ _test_unique_vertex_iterator( const Triangulation &T )
size_type n = 0; size_type n = 0;
for (Unique_vertex_iterator ovit = T.unique_vertices_begin(); for (Unique_vertex_iterator ovit = T.unique_vertices_begin();
ovit != T.unique_vertices_end(); ++ovit) ovit != T.unique_vertices_end(); ++ovit)
{ {
Vertex_handle vh = ovit; // Test the conversion. Vertex_handle vh = ovit; // Test the conversion.
n++; ++n;
const Vertex & v = *ovit; // Test operator*; const Vertex & v = *ovit; // Test operator*;
Cell_handle c = ovit->cell(); // Test operator->; Cell_handle c = ovit->cell(); // Test operator->;
(void) vh; (void) vh;
(void) v; (void) v;
(void) c; (void) c;
} }
assert( n == T.number_of_vertices() ); assert( n == T.number_of_vertices() );
// Test Backward-ness of the iterators. // Test Backward-ness of the iterators.
n=0; n = 0;
for (Unique_vertex_iterator ovit = T.unique_vertices_end(); for (Unique_vertex_iterator ovit = T.unique_vertices_end();
ovit != T.unique_vertices_begin(); --ovit) ovit != T.unique_vertices_begin(); --ovit)
{ {
Vertex_handle vh = ovit; // Test the conversion. Vertex_handle vh = ovit; // Test the conversion.
(void) vh; (void) vh;
n++; ++n;
} }
assert( n == T.number_of_vertices() ); assert( n == T.number_of_vertices() );
return n; return n;
} }
template < class Triangulation >
typename Triangulation::size_type
_test_unique_edge_iterator( const Triangulation &T )
{
typedef typename Triangulation::size_type size_type;
typedef typename Triangulation::Edge Edge;
typedef typename Triangulation::Cell_handle Cell_handle;
typedef typename Triangulation::Unique_edge_iterator
Unique_edge_iterator;
size_type n = 0;
for (Unique_edge_iterator oeit = T.unique_edges_begin();
oeit != T.unique_edges_end(); ++oeit)
{
++n;
const Edge& e = *oeit; // Test operator*;
Cell_handle c = oeit->first; // Test operator->;
assert(c != Cell_handle());
(void) e;
(void) c;
}
assert( n == T.number_of_edges() );
// Test Backward-ness of the iterators.
n = 0;
for (Unique_edge_iterator oeit = T.unique_edges_end();
oeit != T.unique_edges_begin(); --oeit)
{
++n;
}
assert( n == T.number_of_edges() );
return n;
}
template < class Triangulation >
typename Triangulation::size_type
_test_unique_facet_iterator( const Triangulation &T )
{
typedef typename Triangulation::size_type size_type;
typedef typename Triangulation::Facet Facet;
typedef typename Triangulation::Cell_handle Cell_handle;
typedef typename Triangulation::Unique_facet_iterator
Unique_facet_iterator;
size_type n = 0;
for (Unique_facet_iterator ofit = T.unique_facets_begin();
ofit != T.unique_facets_end(); ++ofit)
{
++n;
const Facet& f = *ofit; // Test operator*;
Cell_handle c = ofit->first; // Test operator->;
assert(c != Cell_handle());
(void) f;
(void) c;
}
assert( n == T.number_of_facets() );
// Test Backward-ness of the iterators.
n = 0;
for (Unique_facet_iterator ofit = T.unique_facets_end();
ofit != T.unique_facets_begin(); --ofit)
{
++n;
}
assert( n == T.number_of_facets() );
return n;
}
template < class Triangulation >
typename Triangulation::size_type
_test_unique_cell_iterator( const Triangulation &T )
{
typedef typename Triangulation::size_type size_type;
typedef typename Triangulation::Cell Cell;
typedef typename Triangulation::Vertex_handle Vertex_handle;
typedef typename Triangulation::Cell_handle Cell_handle;
typedef typename Triangulation::Unique_cell_iterator
Unique_cell_iterator;
size_type n = 0;
for (Unique_cell_iterator ocit = T.unique_cells_begin();
ocit != T.unique_cells_end(); ++ocit)
{
Cell_handle ch = ocit; // Test the conversion.
n++;
const Cell& c = *ocit; // Test operator*;
Vertex_handle vh = ocit->vertex(0); // Test operator->;
(void) ch;
(void) c;
(void) vh;
}
assert( n == T.number_of_cells() );
// Test Backward-ness of the iterators.
n=0;
for (Unique_cell_iterator ocit = T.unique_cells_end();
ocit != T.unique_cells_begin(); --ocit)
{
Cell_handle ch = ocit; // Test the conversion.
(void) ch;
++n;
}
assert( n == T.number_of_cells() );
return n;
}
template < class Triangulation >
typename Triangulation::size_type
_test_triangulation_unique_iterator( const Triangulation &T )
{
typedef typename Triangulation::size_type size_type;
const size_type nc = _test_unique_cell_iterator(T);
const size_type nf = _test_unique_facet_iterator(T);
const size_type ne = _test_unique_edge_iterator(T);
const size_type nv = _test_unique_vertex_iterator(T);
assert((nv-ne+nf-nc) == 0);
return nv-ne+nf-nc;
}
template < class Triangulation > template < class Triangulation >
typename Triangulation::size_type typename Triangulation::size_type
_test_triangulation_iterator( const Triangulation &T ) _test_triangulation_iterator( const Triangulation &T )

View File

@ -479,10 +479,10 @@ _test_cls_periodic_3_triangulation_3(const PeriodicTriangulation &,
_test_vertex_iterator(PT3_deg); _test_vertex_iterator(PT3_deg);
_test_vertex_iterator(PT1_deg); _test_vertex_iterator(PT1_deg);
_test_unique_vertex_iterator(PT3); _test_triangulation_unique_iterator(PT3);
_test_unique_vertex_iterator(PT1); _test_triangulation_unique_iterator(PT1);
_test_unique_vertex_iterator(PT3_deg); _test_triangulation_unique_iterator(PT3_deg);
_test_unique_vertex_iterator(PT1_deg); _test_triangulation_unique_iterator(PT1_deg);
_test_triangulation_iterator(PT3); _test_triangulation_iterator(PT3);
_test_triangulation_iterator(PT1); _test_triangulation_iterator(PT1);