// Copyright (c) 1998, 2001, 2003 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Olivier Devillers // Sylvain Pion #ifndef CGAL_TRIANGULATION_HIERARCHY_3_H #define CGAL_TRIANGULATION_HIERARCHY_3_H #include #include #include #include #include #include #include namespace CGAL { // This class is deprecated, but must be kept for backward compatibility. // // It would be better to move its content to the Delaunay_triangulation_3 // specializations for Fast_location and make Triangulation_hierarchy_3 the // empty nutshell instead. // // Then, later, maybe merge the Compact/Fast codes in a cleaner factorized way. template < class Tr > class Triangulation_hierarchy_3 : public Tr { // parameterization of the hierarchy // maximal number of points is 30^5 = 24 millions ! enum { ratio = 30 }; enum { minsize = 20}; enum { maxlevel = 5}; public: typedef Tr Tr_Base; typedef Fast_location Location_policy; typedef typename Tr_Base::Geom_traits Geom_traits; typedef typename Tr_Base::Point Point; typedef typename Tr_Base::size_type size_type; typedef typename Tr_Base::Vertex_handle Vertex_handle; typedef typename Tr_Base::Cell_handle Cell_handle; typedef typename Tr_Base::Vertex_iterator Vertex_iterator; typedef typename Tr_Base::Vertex Vertex; typedef typename Tr_Base::Locate_type Locate_type; typedef typename Tr_Base::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr_Base::Finite_cells_iterator Finite_cells_iterator; typedef typename Tr_Base::Finite_facets_iterator Finite_facets_iterator; typedef typename Tr_Base::Finite_edges_iterator Finite_edges_iterator; using Tr_Base::number_of_vertices; using Tr_Base::geom_traits; private: // here is the stack of triangulations which form the hierarchy Tr_Base* hierarchy[maxlevel]; boost::rand48 random; void set_up_down(Vertex_handle up, Vertex_handle down) { up->set_down(down); down->set_up(up); } public: Triangulation_hierarchy_3(const Geom_traits& traits = Geom_traits()); Triangulation_hierarchy_3(const Triangulation_hierarchy_3& tr); template < typename InputIterator > Triangulation_hierarchy_3(InputIterator first, InputIterator last, const Geom_traits& traits = Geom_traits()) : Tr_Base(traits) { hierarchy[0] = this; for(int i=1; iinfinite_cell() : hint->cell()); } Vertex_handle insert(const Point &p, Cell_handle start = Cell_handle ()); Vertex_handle insert(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj); template < class InputIterator > int insert(InputIterator first, InputIterator last) { int n = number_of_vertices(); std::vector points (first, last); spatial_sort (points.begin(), points.end(), geom_traits()); // hints[i] is the vertex of the previously inserted point in level i. // Thanks to spatial sort, they are better hints than what the hierarchy // would give us. Vertex_handle hints[maxlevel]; for (typename std::vector::const_iterator p = points.begin(), end = points.end(); p != end; ++p) { int vertex_level = random_level(); Vertex_handle v = hints[0] = hierarchy[0]->insert (*p, hints[0]); Vertex_handle prev = v; for (int level = 1; level <= vertex_level; ++level) { v = hints[level] = hierarchy[level]->insert (*p, hints[level]); set_up_down(v, prev); prev = v; } } return number_of_vertices() - n; } void remove(Vertex_handle v); template < typename InputIterator > int remove(InputIterator first, InputIterator beyond) { int n = number_of_vertices(); while (first != beyond) { remove(*first); ++first; } return n - number_of_vertices(); } #ifndef CGAL_NO_DEPRECATED_CODE CGAL_DEPRECATED Vertex_handle move_point(Vertex_handle v, const Point & p); #endif Vertex_handle move_if_no_collision(Vertex_handle v, const Point &p); Vertex_handle move(Vertex_handle v, const Point &p); public: // some internal methods // INSERT REMOVE DISPLACEMENT // GIVING NEW FACES template Vertex_handle insert_and_give_new_cells(const Point &p, OutputItCells fit, Cell_handle start = Cell_handle() ); template Vertex_handle insert_and_give_new_cells(const Point& p, OutputItCells fit, Vertex_handle hint) { return insert_and_give_new_cells(p, hint == Vertex_handle() ? this->infinite_cell() : hint->cell()); } template Vertex_handle insert_and_give_new_cells(const Point& p, Locate_type lt, Cell_handle c, int li, int lj, OutputItCells fit); template void remove_and_give_new_cells(Vertex_handle v, OutputItCells fit); template Vertex_handle move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point &p, OutputItCells fit); public: //LOCATE Cell_handle locate(const Point& p, Locate_type& lt, int& li, int& lj, Vertex_handle hint) const { return locate(p, lt, li, lj, hint == Vertex_handle() ? this->infinite_cell() : hint->cell()); } Cell_handle locate(const Point& p, Vertex_handle hint) const { return locate(p, hint == Vertex_handle() ? this->infinite_cell() : hint->cell()); } Cell_handle locate(const Point& p, Locate_type& lt, int& li, int& lj, Cell_handle start = Cell_handle ()) const; Cell_handle locate(const Point& p, Cell_handle start = Cell_handle ()) const; Vertex_handle nearest_vertex(const Point& p, Cell_handle start = Cell_handle()) const; protected: struct locs { Cell_handle pos; int li, lj; Locate_type lt; }; void locate(const Point& p, Locate_type& lt, int& li, int& lj, locs pos[maxlevel], Cell_handle start = Cell_handle ()) const; int random_level(); }; template Triangulation_hierarchy_3:: Triangulation_hierarchy_3(const Geom_traits& traits) : Tr_Base(traits) { hierarchy[0] = this; for(int i=1;i Triangulation_hierarchy_3:: Triangulation_hierarchy_3(const Triangulation_hierarchy_3 &tr) : Tr_Base(tr) { hierarchy[0] = this; for(int i=1; i V; for( Finite_vertices_iterator it = hierarchy[0]->finite_vertices_begin(), end = hierarchy[0]->finite_vertices_end(); it != end; ++it) if (it->up() != Vertex_handle()) V[ it->up()->down() ] = it; for(int j=1; jfinite_vertices_begin(), end = hierarchy[j]->finite_vertices_end(); it != end; ++it) { // current it->down() pointer goes in original instead in copied triangulation set_up_down(it, V[it->down()]); // make map for next level if (it->up() != Vertex_handle()) V[ it->up()->down() ] = it; } } } template void Triangulation_hierarchy_3:: swap(Triangulation_hierarchy_3 &tr) { Tr_Base::swap(tr); for(int i=1; i Triangulation_hierarchy_3:: ~Triangulation_hierarchy_3() { clear(); for(int i=1; i void Triangulation_hierarchy_3:: clear() { for(int i=0;iclear(); } template bool Triangulation_hierarchy_3:: is_valid(bool verbose, int level) const { bool result = true; // verify correctness of triangulation at all levels for(int i=0; iis_valid(verbose, level); // verify that lower level has no down pointers for( Finite_vertices_iterator it = hierarchy[0]->finite_vertices_begin(), end = hierarchy[0]->finite_vertices_end(); it != end; ++it) result = result && (it->down() == Vertex_handle()); // verify that other levels has down pointer and reciprocal link is fine for(int j=1; jfinite_vertices_begin(), end = hierarchy[j]->finite_vertices_end(); it != end; ++it) result = result && &*(it) == &*(it->down()->up()); // verify that other levels has down pointer and reciprocal link is fine for(int k=0; kfinite_vertices_begin(), end = hierarchy[k]->finite_vertices_end(); it != end; ++it) result = result && ( it->up() == Vertex_handle() || &*it == &*(it->up())->down() ); return result; } template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: insert(const Point &p, Cell_handle start) { int vertex_level = random_level(); Locate_type lt; int i, j; // locate using hierarchy locs positions[maxlevel]; locate(p, lt, i, j, positions, start); // insert at level 0 Vertex_handle vertex = hierarchy[0]->insert(p, positions[0].lt, positions[0].pos, positions[0].li, positions[0].lj); Vertex_handle previous = vertex; Vertex_handle first = vertex; int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) vertex = hierarchy[level]->insert(p); else vertex = hierarchy[level]->insert(p, positions[level].lt, positions[level].pos, positions[level].li, positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; } return first; } template template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: insert_and_give_new_cells(const Point &p, OutputItCells fit, Cell_handle start) { int vertex_level = random_level(); Locate_type lt; int i, j; // locate using hierarchy locs positions[maxlevel]; locate(p, lt, i, j, positions, start); // insert at level 0 Vertex_handle vertex = hierarchy[0]->insert_and_give_new_cells(p, positions[0].lt, positions[0].pos, positions[0].li, positions[0].lj,fit); Vertex_handle previous = vertex; Vertex_handle first = vertex; int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) vertex = hierarchy[level]->insert(p); else vertex = hierarchy[level]->insert(p, positions[level].lt, positions[level].pos, positions[level].li, positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; } return first; } template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: insert(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj) { int vertex_level = random_level(); // insert at level 0 Vertex_handle vertex = hierarchy[0]->insert(p,lt,loc,li,lj); Vertex_handle previous = vertex; Vertex_handle first = vertex; if (vertex_level > 0) { Locate_type lt; int i, j; // locate using hierarchy locs positions[maxlevel]; locate(p, lt, i, j, positions, vertex->cell()); int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) vertex = hierarchy[level]->insert(p); else vertex = hierarchy[level]->insert(p, positions[level].lt, positions[level].pos, positions[level].li, positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; } } return first; } template template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: insert_and_give_new_cells(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj, OutputItCells fit) { int vertex_level = random_level(); // insert at level 0 Vertex_handle vertex = hierarchy[0]->insert_and_give_new_cells(p,lt,loc,li,lj,fit); Vertex_handle previous = vertex; Vertex_handle first = vertex; if (vertex_level > 0) { Locate_type lt; int i, j; // locate using hierarchy locs positions[maxlevel]; locate(p, lt, i, j, positions, vertex->cell()); int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) vertex = hierarchy[level]->insert(p); else vertex = hierarchy[level]->insert(p, positions[level].lt, positions[level].pos, positions[level].li, positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; } } return first; } template void Triangulation_hierarchy_3:: remove(Vertex_handle v) { CGAL_triangulation_precondition(v != Vertex_handle()); for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); hierarchy[l]->remove(v); if (u == Vertex_handle()) break; v = u; } } template template void Triangulation_hierarchy_3:: remove_and_give_new_cells(Vertex_handle v, OutputItCells fit) { CGAL_triangulation_precondition(v != Vertex_handle()); CGAL_triangulation_precondition(!is_infinite(v)); for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); if(l) hierarchy[l]->remove(v); else hierarchy[l]->remove_and_give_new_cells(v, fit); if (u == Vertex_handle()) break; v = u; } } #ifndef CGAL_NO_DEPRECATED_CODE template < class Tr > typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: move_point(Vertex_handle v, const Point & p) { CGAL_triangulation_precondition(v != Vertex_handle()); Vertex_handle old, ret; for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); Vertex_handle w = hierarchy[l]->move_point(v, p); if (l == 0) { ret = w; } else { set_up_down(w, old); } if (u == Vertex_handle()) break; old = w; v = u; } return ret; } #endif template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: move_if_no_collision(Vertex_handle v, const Point & p) { CGAL_triangulation_precondition(!this->is_infinite(v)); if(v->point() == p) return v; Vertex_handle ans; for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); if(l) hierarchy[l]->move_if_no_collision(v, p); else ans = hierarchy[l]->move_if_no_collision(v, p); if(ans != v) return ans; if (u == Vertex_handle()) break; v = u; } return ans; } template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: move(Vertex_handle v, const Point & p) { CGAL_triangulation_precondition(!this->is_infinite(v)); if(v->point() == p) return v; Vertex_handle w = move_if_no_collision(v,p); if(w != v) { remove(v); return w; } return v; } template template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: move_if_no_collision_and_give_new_cells( Vertex_handle v, const Point & p, OutputItCells fit) { CGAL_triangulation_precondition(!is_infinite(v)); if(v->point() == p) return v; Vertex_handle ans; for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); if(l) hierarchy[l]->move_if_no_collision(v, p); else ans = hierarchy[l]->move_if_no_collision_and_give_new_cells(v, p, fit); if(ans != v) return ans; if (u == Vertex_handle()) break; v = u; } return ans; } template inline typename Triangulation_hierarchy_3::Cell_handle Triangulation_hierarchy_3:: locate(const Point& p, Locate_type& lt, int& li, int& lj, Cell_handle start) const { if (start != Cell_handle ()) return Tr_Base::locate (p, lt, li, lj, start); locs positions[maxlevel]; locate(p, lt, li, lj, positions); return positions[0].pos; } template inline typename Triangulation_hierarchy_3::Cell_handle Triangulation_hierarchy_3:: locate(const Point& p, Cell_handle start) const { if (start != Cell_handle ()) return Tr_Base::locate (p, start); Locate_type lt; int li, lj; return locate(p, lt, li, lj); } template void Triangulation_hierarchy_3:: locate(const Point& p, Locate_type& lt, int& li, int& lj, locs pos[maxlevel], Cell_handle start) const { int level = maxlevel; // find the highest level with enough vertices while (hierarchy[--level]->number_of_vertices() < (size_type) minsize) { if ( ! level) break; // do not go below 0 } for (int i=level+1; i 0) { // locate at that level from "position" // result is stored in "position" for the next level pos[level].pos = position = hierarchy[level]->locate(p, pos[level].lt, pos[level].li, pos[level].lj, position); // find the nearest vertex. Vertex_handle nearest = hierarchy[level]->nearest_vertex_in_cell(p, position); // go at the same vertex on level below nearest = nearest->down(); position = nearest->cell(); // incident cell --level; } if (start != Cell_handle()) position = start; pos[0].pos = hierarchy[0]->locate(p, lt, li, lj, position); // at level 0 pos[0].lt = lt; pos[0].li = li; pos[0].lj = lj; } template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: nearest_vertex(const Point& p, Cell_handle start) const { return Tr_Base::nearest_vertex(p, start != Cell_handle() ? start : locate(p)); } template int Triangulation_hierarchy_3:: random_level() { boost::geometric_distribution<> proba(1.0/ratio); boost::variate_generator > die(random, proba); return (std::min)(die(), (int)maxlevel)-1; } } //namespace CGAL #endif // CGAL_TRIANGULATION_HIERARCHY_3_H