From 5759ce49ae1ff163cda54d07062e8488c1326cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 7 Jul 2023 02:04:01 +0200 Subject: [PATCH] Add unique simplex iterators --- .../include/CGAL/Periodic_2_triangulation_2.h | 151 ++++++- .../Periodic_2_triangulation_iterators_2.h | 325 ++++++++------ .../include/interface_test.h | 28 +- .../include/CGAL/Periodic_3_triangulation_3.h | 413 ++++++++++++------ .../Periodic_3_triangulation_iterators_3.h | 327 ++++++-------- .../CGAL/_test_cls_periodic_3_iterator.h | 160 ++++++- .../_test_cls_periodic_3_triangulation_3.h | 8 +- 7 files changed, 906 insertions(+), 506 deletions(-) diff --git a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h index a4ca4e36a30..2ce4755742a 100644 --- a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_2.h @@ -119,6 +119,14 @@ public: /// Unique_vertex_iterator iterates over exactly one representative. typedef Periodic_2_triangulation_unique_vertex_iterator_2 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 + 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 + Unique_face_iterator; /// \name For compatibility with the Triangulation_2 class // \{ @@ -676,6 +684,32 @@ public: Periodic_2_triangulation_2_internal::Domain_tester(this)); } + Unique_edge_iterator unique_edges_begin() const + { + return CGAL::filter_iterator(edges_end(), + Periodic_2_triangulation_2_internal::Domain_tester(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(this)); + } + + Unique_face_iterator unique_faces_begin() const + { + return CGAL::filter_iterator(faces_end(), + Periodic_2_triangulation_2_internal::Domain_tester(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(this)); + } + // \} /// \name Geometric iterators //\{ @@ -972,6 +1006,32 @@ public: 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. int off_to_int(const Offset & off) const { @@ -986,13 +1046,12 @@ public: return Offset((i >> 1) & 1, i & 1); } - // \} - // 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 + /// Tests whether a vertex is a periodic copy of a vertex in the 3-cover. + bool is_virtual(Vertex_handle v) 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. @@ -1007,15 +1066,6 @@ public: 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& periodic_copies(const Vertex_handle v) const { CGAL_precondition(number_of_sheets() != make_array(1, 1) ); @@ -1024,6 +1074,77 @@ public: 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 Stream& draw_triangulation(Stream& os) const { diff --git a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_iterators_2.h b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_iterators_2.h index afa1a55fce5..9b2afd4ba64 100644 --- a/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_iterators_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/Periodic_2_triangulation_iterators_2.h @@ -66,7 +66,7 @@ public: { 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; } } @@ -88,7 +88,7 @@ public: { ++pos; } - while (pos != _t->faces_end() && !is_canonical()); + while (pos != _t->faces_end() && !_t->is_canonical(pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -112,7 +112,7 @@ public: { --pos; } - while (pos != _t->faces_begin() && !is_canonical()); + while (pos != _t->faces_begin() && !_t->is_canonical(pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -172,37 +172,6 @@ private: mutable Periodic_triangle periodic_triangle; // current triangle. 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 // copies into account. void increment_domain() @@ -217,7 +186,7 @@ private: ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN - && pos != _t->faces_end() && !is_canonical()); + && pos != _t->faces_end() && !_t->is_canonical(pos)); } else { @@ -241,7 +210,7 @@ private: { --pos; } - while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); + while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(pos)); _off = get_drawing_offsets(); } 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 // applied to the edge *pos int get_drawing_offsets() @@ -287,7 +237,7 @@ private: // internally stored inside the cell telling us that this cell // wraps around the domain. if (_it == T::UNIQUE_COVER_DOMAIN) - get_edge_offsets(off0, off1, off2); + _t->get_offsets(pos, off0, off1, off2); else { CGAL_assertion(_it == T::STORED_COVER_DOMAIN); @@ -319,7 +269,7 @@ private: { CGAL_assertion(pos != typename T::Face_handle()); 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), (((_off ) & 1) == 1 ? -1 : 0)); if (_it == T::STORED_COVER_DOMAIN) @@ -385,7 +335,7 @@ public: { 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; } } @@ -407,7 +357,7 @@ public: { ++pos; } - while (pos != _t->edges_end() && !is_canonical()); + while (pos != _t->edges_end() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -431,7 +381,7 @@ public: { --pos; } - while (pos != _t->edges_begin() && !is_canonical()); + while (pos != _t->edges_begin() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -490,35 +440,6 @@ private: mutable Periodic_segment periodic_segment; // current segment. 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 // copies into account. void increment_domain() @@ -533,7 +454,7 @@ private: ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN - && pos != _t->edges_end() && !is_canonical()); + && pos != _t->edges_end() && !_t->is_canonical(*pos)); } else { @@ -557,7 +478,7 @@ private: { --pos; } - while (_it == T::UNIQUE_COVER_DOMAIN && !is_canonical()); + while (_it == T::UNIQUE_COVER_DOMAIN && !_t->is_canonical(*pos)); _off = get_drawing_offsets(); } 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 // applied to the edge *pos int get_drawing_offsets() @@ -598,7 +505,7 @@ private: // internally stored inside the cell telling us that this cell // wraps around the domain. if (_it == T::UNIQUE_COVER_DOMAIN) - get_edge_offsets(off0, off1); + _t->get_offsets(*pos, off0, off1); else { CGAL_assertion(_it == T::STORED_COVER_DOMAIN); @@ -618,7 +525,7 @@ private: { CGAL_assertion(pos->first != typename T::Face_handle()); Offset off0, off1; - get_edge_offsets(off0, off1); + _t->get_offsets(*pos, off0, off1); Offset transl_off = Offset((((_off >> 1) & 1) == 1 ? -1 : 0), (( _off & 1) == 1 ? -1 : 0)); if (_it == T::STORED_COVER_DOMAIN) @@ -681,7 +588,7 @@ public: { 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; } } @@ -705,7 +612,7 @@ public: { ++pos; } - while (pos != _t->vertices_end() && !is_canonical()); + while (pos != _t->vertices_end() && !_t->is_canonical(pos)); break; default: CGAL_assertion(false); @@ -727,7 +634,7 @@ public: { --pos; } - while (pos != _t->vertices_begin() && !is_canonical()); + while (pos != _t->vertices_begin() && !_t->is_canonical(pos)); break; default: CGAL_assertion(false); @@ -785,14 +692,6 @@ private: mutable Periodic_point periodic_point; // current point. 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 { 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 Domain_tester { - const T *t; + typedef typename T::Offset Offset; - public: - Domain_tester() {} - Domain_tester(const T *tr) : t(tr) {} + const T *t; - 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 // 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 Periodic_2_triangulation_unique_edge_iterator_2 + : public Filter_iterator > +{ + typedef typename T::Edge Edge; + typedef typename T::Edge_iterator Edge_iterator; + + typedef typename Periodic_2_triangulation_2_internal::Domain_tester Tester; + + typedef Filter_iterator 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 Periodic_2_triangulation_unique_face_iterator_2 + : public Filter_iterator > +{ + typedef typename T::Face_handle Face_handle; + typedef typename T::Face_iterator Face_iterator; + + typedef typename Periodic_2_triangulation_2_internal::Domain_tester Tester; + + typedef Filter_iterator 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 diff --git a/Periodic_2_triangulation_2/test/Periodic_2_triangulation_2/include/interface_test.h b/Periodic_2_triangulation_2/test/Periodic_2_triangulation_2/include/interface_test.h index efbd3cf0be4..7c50e0a4252 100644 --- a/Periodic_2_triangulation_2/test/Periodic_2_triangulation_2/include/interface_test.h +++ b/Periodic_2_triangulation_2/test/Periodic_2_triangulation_2/include/interface_test.h @@ -217,19 +217,19 @@ void test_iterators() } 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()); - size = 0; for (typename T::Vertex_iterator vit = t_const.all_vertices_begin(); vit != t_const.all_vertices_end(); ++vit) { ++size; } 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 size = 0; @@ -246,6 +246,13 @@ void test_iterators() ++size; } 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 size = 0; @@ -262,6 +269,13 @@ void test_iterators() ++size; } 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 for (typename T::Periodic_point_iterator ppit = t_const.periodic_points_begin(); diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h index c6399eeaa0f..19c56b91950 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3.h @@ -169,6 +169,13 @@ public: typedef Facet_iterator All_facets_iterator; typedef Edge_iterator All_edges_iterator; typedef Vertex_iterator All_vertices_iterator; + + typedef Periodic_3_triangulation_unique_cell_iterator_3 + Unique_cell_iterator; + typedef Periodic_3_triangulation_unique_facet_iterator_3 + Unique_facet_iterator; + typedef Periodic_3_triangulation_unique_edge_iterator_3 + Unique_edge_iterator; typedef Periodic_3_triangulation_unique_vertex_iterator_3 Unique_vertex_iterator; @@ -397,26 +404,14 @@ public: } const Covering_sheets& number_of_sheets() const { return _cover; } - const std::pair 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& 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; - void convert_to_1_sheeted_covering(); + virtual void update_cover_data_after_converting_to_27_sheeted_covering() { } void convert_to_27_sheeted_covering(); +public: size_type number_of_cells() const { if(is_1_cover()) return _tds.number_of_cells(); else return _tds.number_of_cells()/27; @@ -460,14 +455,6 @@ public: _cover = cover; } -public: - bool is_virtual(Vertex_handle v) - { - if(is_1_cover()) - return false; - return (virtual_vertices.find(v) != virtual_vertices.end()); - } - public: // Offset converters int off_to_int(const Offset& off) const @@ -549,6 +536,232 @@ public: 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 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& 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: /** @name Wrapping the traits */ // Note that calling functors with "construct_point(p), offset" and not @@ -988,6 +1201,14 @@ public: // end of geometric functions 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 */ bool is_vertex(const Point& p, Vertex_handle& v) const; @@ -1305,6 +1526,14 @@ public: std::vector insert_generic_dummy_points(); protected: + template + Offset get_location_offset(const Conflict_tester& tester, + Cell_handle c) const; + + template + Offset get_location_offset(const Conflict_tester& tester, + Cell_handle c, bool& found) const; + // this is needed for compatibility reasons template @@ -1530,6 +1759,16 @@ public: return _tds.facets_end(); } + // Unique iterators + + Unique_cell_iterator unique_cells_begin() const { + return CGAL::filter_iterator(cells_end(), Domain_tester(this), + cells_begin()); + } + Unique_cell_iterator unique_cells_end() const { + return CGAL::filter_iterator(cells_end(), Domain_tester(this)); + } + Unique_vertex_iterator unique_vertices_begin() const { return CGAL::filter_iterator(vertices_end(), Domain_tester(this), vertices_begin()); @@ -1538,6 +1777,22 @@ public: return CGAL::filter_iterator(vertices_end(), Domain_tester(this)); } + Unique_edge_iterator unique_edges_begin() const { + return CGAL::filter_iterator(edges_end(), Domain_tester(this), + edges_begin()); + } + Unique_edge_iterator unique_edges_end() const { + return CGAL::filter_iterator(edges_end(), Domain_tester(this)); + } + + Unique_facet_iterator unique_facets_begin() const { + return CGAL::filter_iterator(facets_end(), Domain_tester(this), + facets_begin()); + } + Unique_facet_iterator unique_facets_end() const { + return CGAL::filter_iterator(facets_end(), Domain_tester(this)); + } + // Geometric iterators Periodic_tetrahedron_iterator periodic_tetrahedra_begin( 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 - Offset get_location_offset(const Conflict_tester& tester, - Cell_handle c) const; - - template - 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: /** @name Friends */ friend std::istream& operator>> <> @@ -1788,51 +1974,6 @@ protected: 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: template bool canonical_dual_segment(Cell_handle c, int i, Periodic_segment_3& ps, diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3/internal/Periodic_3_triangulation_iterators_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3/internal/Periodic_3_triangulation_iterators_3.h index 947b8b553e5..719060bed29 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3/internal/Periodic_3_triangulation_iterators_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_3/internal/Periodic_3_triangulation_iterators_3.h @@ -63,7 +63,7 @@ public: Iterator_type it = T::STORED) : _t(t), pos(_t->cells_begin()), _it(it), _off(0) { 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; } } @@ -79,7 +79,7 @@ public: ++pos; break; case T::UNIQUE: - do { ++pos; } while (pos != _t->cells_end() && !is_canonical()); + do { ++pos; } while (pos != _t->cells_end() && !_t->is_canonical(pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -97,7 +97,7 @@ public: --pos; break; case T::UNIQUE: - do { --pos; } while (pos != _t->cells_begin() && !is_canonical()); + do { --pos; } while (pos != _t->cells_begin() && !_t->is_canonical(pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -156,42 +156,6 @@ private: mutable Periodic_tetrahedron periodic_tetrahedron; // current tetrahedron. 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 // copies into account. void increment_domain() { @@ -200,7 +164,7 @@ private: if (_off == off) { _off = 0; do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN - && pos != _t->cells_end() && !is_canonical()); + && pos != _t->cells_end() && !_t->is_canonical(pos)); } else { do { ++_off; @@ -214,7 +178,7 @@ private: void decrement_domain() { if (_off == 0) { 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(); } else { 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 // applied to the edge *pos int get_drawing_offsets() { @@ -262,7 +200,7 @@ private: // internally stored inside the cell telling us that this cell // wraps around the domain. if (_it == T::UNIQUE_COVER_DOMAIN) - get_edge_offsets(off0,off1,off2,off3); + _t->get_offsets(pos, off0, off1, off2, off3); else { CGAL_assertion(_it == T::STORED_COVER_DOMAIN); off0 = _t->int_to_off(pos->offset(0)); @@ -303,7 +241,7 @@ private: Periodic_tetrahedron construct_periodic_tetrahedron() const { CGAL_assertion(pos != typename T::Cell_handle()); 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), (((_off>>1)&1)==1 ? -1:0), (( _off &1)==1 ? -1:0)); @@ -369,7 +307,7 @@ public: Iterator_type it = T::STORED) : _t(t), pos(_t->facets_begin()), _it(it), _off(0) { 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; } } @@ -385,7 +323,7 @@ public: ++pos; break; case T::UNIQUE: - do { ++pos; } while (pos != _t->facets_end() && !is_canonical()); + do { ++pos; } while (pos != _t->facets_end() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -403,7 +341,7 @@ public: --pos; break; case T::UNIQUE: - do { --pos; } while (pos != _t->facets_begin() && !is_canonical()); + do { --pos; } while (pos != _t->facets_begin() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -462,39 +400,6 @@ private: mutable Periodic_triangle periodic_triangle; // current segment. 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 // copies into account. void increment_domain() { @@ -503,7 +408,7 @@ private: if (_off == off) { _off = 0; do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN - && pos != _t->facets_end() && !is_canonical()); + && pos != _t->facets_end() && !_t->is_canonical(*pos)); } else { do { ++_off; @@ -517,7 +422,7 @@ private: void decrement_domain() { if (_off == 0) { 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(); } else { 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 // applied to the edge *pos int get_drawing_offsets() { @@ -565,7 +444,7 @@ private: // internally stored inside the cell telling us that this cell // wraps around the domain. if (_it == T::UNIQUE_COVER_DOMAIN) - get_edge_offsets(off0,off1,off2); + _t->get_offsets(*pos, off0, off1, off2); else { CGAL_assertion(_it == T::STORED_COVER_DOMAIN); off0 = _t->int_to_off(pos->first->offset((pos->second+1)&3)); @@ -596,7 +475,7 @@ private: Periodic_triangle construct_periodic_triangle() const { CGAL_assertion(pos->first != typename T::Cell_handle()); 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), (((_off>>1)&1)==1 ? -1:0), (( _off &1)==1 ? -1:0)); @@ -659,7 +538,7 @@ public: Iterator_type it = T::STORED) : _t(t), pos(_t->edges_begin()), _it(it), _off(0) { 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; } } @@ -675,7 +554,7 @@ public: ++pos; break; case T::UNIQUE: - do { ++pos; } while (pos != _t->edges_end() && !is_canonical()); + do { ++pos; } while (pos != _t->edges_end() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -693,7 +572,7 @@ public: --pos; break; case T::UNIQUE: - do { --pos; } while (pos != _t->edges_begin() && !is_canonical()); + do { --pos; } while (pos != _t->edges_begin() && !_t->is_canonical(*pos)); break; case T::STORED_COVER_DOMAIN: case T::UNIQUE_COVER_DOMAIN: @@ -751,36 +630,6 @@ private: mutable Periodic_segment periodic_segment; // current segment. 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 // copies into account. void increment_domain() { @@ -789,7 +638,7 @@ private: if (_off == off) { _off = 0; do { ++pos; } while (_it == T::UNIQUE_COVER_DOMAIN - && pos != _t->edges_end() && !is_canonical()); + && pos != _t->edges_end() && !_t->is_canonical(*pos)); } else { do { ++_off; @@ -803,7 +652,7 @@ private: void decrement_domain() { if (_off == 0) { 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(); } else { 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 // applied to the edge *pos int get_drawing_offsets() { @@ -839,7 +674,7 @@ private: // internally stored inside the cell telling us that this cell // wraps around the domain. if (_it == T::UNIQUE_COVER_DOMAIN) - get_edge_offsets(off0,off1); + _t->get_offsets(*pos, off0, off1); else { CGAL_assertion(_it == T::STORED_COVER_DOMAIN); off0 = _t->int_to_off(pos->first->offset(pos->second)); @@ -859,7 +694,7 @@ private: Periodic_segment construct_periodic_segment() const { CGAL_assertion(pos->first != typename T::Cell_handle()); Offset off0, off1; - get_edge_offsets(off0, off1); + _t->get_offsets(*pos, off0, off1); Offset transl_off = Offset((((_off>>2)&1)==1 ? -1:0), (((_off>>1)&1)==1 ? -1:0), (( _off &1)==1 ? -1:0)); @@ -918,7 +753,7 @@ public: Iterator_type it = T::STORED) : _t(t), pos(_t->vertices_begin()), _it(it) { 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; } } @@ -936,7 +771,7 @@ public: break; case T::UNIQUE: 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; default: CGAL_assertion(false); @@ -952,7 +787,7 @@ public: break; case T::UNIQUE: 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; default: CGAL_assertion(false); @@ -1009,13 +844,6 @@ private: mutable Periodic_point periodic_point; // current point. 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 { CGAL_assertion(pos != typename T::Vertex_handle()); Offset off = _t->get_offset(pos); @@ -1031,9 +859,54 @@ public: Domain_tester() {} Domain_tester(const T *tr) : t(tr) {} - bool operator()(const typename T::Vertex_iterator & v) const { - return (t->get_offset(v) != typename T::Offset(0,0,0)); + bool operator()(const typename T::Cell_iterator c) const + { + 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 Periodic_3_triangulation_unique_cell_iterator_3 + : public Filter_iterator > +{ + typedef typename T::Cell_handle Cell_handle; + typedef typename T::Cell_iterator Cell_iterator; + + typedef Filter_iterator > 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 @@ -1065,6 +938,62 @@ public: 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 Periodic_3_triangulation_unique_edge_iterator_3 + : public Filter_iterator > +{ + typedef typename T::Edge Edge; + typedef typename T::Edge_iterator Edge_iterator; + + typedef Filter_iterator > 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 Periodic_3_triangulation_unique_facet_iterator_3 + : public Filter_iterator > +{ + typedef typename T::Facet Facet; + typedef typename T::Facet_iterator Facet_iterator; + + typedef Filter_iterator > 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 diff --git a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_iterator.h b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_iterator.h index a77afb5fbc0..49bdfff51cd 100644 --- a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_iterator.h +++ b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_iterator.h @@ -86,32 +86,158 @@ _test_unique_vertex_iterator( const Triangulation &T ) size_type n = 0; for (Unique_vertex_iterator ovit = T.unique_vertices_begin(); - ovit != T.unique_vertices_end(); ++ovit) - { - Vertex_handle vh = ovit; // Test the conversion. - n++; - const Vertex & v = *ovit; // Test operator*; - Cell_handle c = ovit->cell(); // Test operator->; - (void) vh; - (void) v; - (void) c; - } + ovit != T.unique_vertices_end(); ++ovit) + { + Vertex_handle vh = ovit; // Test the conversion. + ++n; + const Vertex & v = *ovit; // Test operator*; + Cell_handle c = ovit->cell(); // Test operator->; + (void) vh; + (void) v; + (void) c; + } assert( n == T.number_of_vertices() ); // Test Backward-ness of the iterators. - n=0; + n = 0; for (Unique_vertex_iterator ovit = T.unique_vertices_end(); - ovit != T.unique_vertices_begin(); --ovit) - { - Vertex_handle vh = ovit; // Test the conversion. - (void) vh; - n++; - } + ovit != T.unique_vertices_begin(); --ovit) + { + Vertex_handle vh = ovit; // Test the conversion. + (void) vh; + ++n; + } assert( n == T.number_of_vertices() ); 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 > typename Triangulation::size_type _test_triangulation_iterator( const Triangulation &T ) diff --git a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_triangulation_3.h b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_triangulation_3.h index 0cb56c38824..b5d08b90ec6 100644 --- a/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_triangulation_3.h +++ b/Periodic_3_triangulation_3/test/Periodic_3_triangulation_3/include/CGAL/_test_cls_periodic_3_triangulation_3.h @@ -479,10 +479,10 @@ _test_cls_periodic_3_triangulation_3(const PeriodicTriangulation &, _test_vertex_iterator(PT3_deg); _test_vertex_iterator(PT1_deg); - _test_unique_vertex_iterator(PT3); - _test_unique_vertex_iterator(PT1); - _test_unique_vertex_iterator(PT3_deg); - _test_unique_vertex_iterator(PT1_deg); + _test_triangulation_unique_iterator(PT3); + _test_triangulation_unique_iterator(PT1); + _test_triangulation_unique_iterator(PT3_deg); + _test_triangulation_unique_iterator(PT1_deg); _test_triangulation_iterator(PT3); _test_triangulation_iterator(PT1);