// ====================================================================== // // Copyright (c) 1997 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // // release : $CGAL_Revision$ // release_date : $CGAL_Date$ // // file : include/CGAL/Delaunay_triangulation_2.h // source : $RCSfile$ // revision : $Revision$ // revision_date : $Date$ // author(s) : Mariette Yvinec // // coordinator : Mariette Yvinec // // ====================================================================== #ifndef CGAL_DELAUNAY_TRIANGULATION_2_H #define CGAL_DELAUNAY_TRIANGULATION_2_H #include #include CGAL_BEGIN_NAMESPACE template < class Gt, class Tds = Triangulation_data_structure_2 < Triangulation_vertex_base_2 > > class Delaunay_triangulation_2 : public Triangulation_2 { public: typedef Gt Geom_traits; typedef typename Geom_traits::Point_2 Point; typedef typename Geom_traits::Segment_2 Segment; typedef typename Geom_traits::Triangle_2 Triangle; typedef typename Geom_traits::Orientation_2 Orientation_2; typedef typename Geom_traits::Compare_x_2 Compare_x; typedef typename Geom_traits::Compare_y_2 Compare_y; typedef typename Geom_traits::Side_of_oriented_circle_2 Side_of_oriented_circle; typedef Triangulation_2 Triangulation; typedef typename Triangulation::Locate_type Locate_type; typedef typename Triangulation::Face_handle Face_handle; typedef typename Triangulation::Vertex_handle Vertex_handle; typedef typename Triangulation::Edge Edge; typedef typename Triangulation::Edge_circulator Edge_circulator; typedef typename Triangulation::Finite_edges_iterator Finite_edges_iterator; typedef typename Triangulation::Finite_faces_iterator Finite_faces_iterator; typedef typename Triangulation::Finite_vertices_iterator Finite_vertices_iterator; Delaunay_triangulation_2(const Gt& gt = Gt()) : Triangulation_2(gt) {} Delaunay_triangulation_2( const Delaunay_triangulation_2 &tr) : Triangulation_2(tr) { CGAL_triangulation_postcondition( is_valid() ); } // CHECK -QUERY bool is_valid(bool verbose = false, int level = 0) const; Vertex_handle nearest_vertex(const Point& p, Face_handle f= Face_handle(NULL)) const; bool does_conflict(const Point &p, Face_handle fh) const;// deprecated bool test_conflict(const Point &p, Face_handle fh) const; bool find_conflicts(const Point &p, //deprecated std::list& conflicts, Face_handle start= Face_handle(NULL) ) const; // //template member functions, declared and defined at the end // template // bool get_conflicts_and_boundary(const Point &p, // Out_it1 fit, // Out_it2 eit, // Face_handle start) const; // template // bool get_conflicts (const Point &p, // Out_it1 fit, // Face_handle start ) const; // template // bool get_boundary_of_conflicts(const Point &p, // Out_it2 eit, // Face_handle start ) const; // DUAL Point dual (Face_handle f) const; Object dual(const Edge &e) const ; Object dual(const Edge_circulator& ec) const; Object dual(const Finite_edges_iterator& ei) const; //INSERTION-REMOVAL Vertex_handle insert(const Point &p, Face_handle start = Face_handle(NULL) ); Vertex_handle insert(const Point& p, Locate_type lt, Face_handle loc, int li ); Vertex_handle push_back(const Point &p); void remove(Vertex_handle v ); private: void restore_Delaunay(Vertex_handle v); void propagating_flip(Face_handle& f,int i); void remove_2D(Vertex_handle v ); Vertex_handle nearest_vertex_2D(const Point& p, Face_handle f) const; Vertex_handle nearest_vertex_1D(const Point& p) const; void look_nearest_neighbor(const Point& p, Face_handle f, int i, Vertex_handle& nn) const; public: template < class Stream> Stream& draw_dual(Stream & ps) { Finite_edges_iterator eit= finite_edges_begin(); for (; eit != finite_edges_end(); ++eit) { Object o = dual(eit); typename Geom_traits::Line_2 l; typename Geom_traits::Ray_2 r; Segment s; if (CGAL::assign(s,o)) ps << s; if (CGAL::assign(r,o)) ps << r; if (CGAL::assign(l,o)) ps << l; } return ps; } template < class InputIterator > int insert(InputIterator first, InputIterator last) { int n = number_of_vertices(); while(first != last){ insert(*first); ++first; } return number_of_vertices() - n; } template bool get_conflicts_and_boundary (const Point &p, Out_it1 fit, Out_it2 eit, Face_handle start = Face_handle(NULL)) const { CGAL_triangulation_precondition( dimension() == 2); int li; Locate_type lt; Face_handle fh = locate(p,lt,li, start); switch(lt) { case Triangulation::OUTSIDE_AFFINE_HULL: case Triangulation::VERTEX: return false; case Triangulation::FACE: case Triangulation::EDGE: case Triangulation::OUTSIDE_CONVEX_HULL: *fit++ = fh; //put fh in Out_it1 propagate_conflicts(p,fh,0,fit,eit); propagate_conflicts(p,fh,1,fit,eit); propagate_conflicts(p,fh,2,fit,eit); return true; } CGAL_triangulation_assertion(false); return false; } template bool get_conflicts (const Point &p, Out_it1 fit, Face_handle start= Face_handle(NULL)) const { return get_conflicts_and_boundary(p, fit, Emptyset_iterator(), start); } template bool get_boundary_of_conflicts(const Point &p, Out_it2 eit, Face_handle start= Face_handle(NULL)) const { return get_conflicts_and_boundary(p, Emptyset_iterator(), eit, start); } private: template void propagate_conflicts (const Point &p, Face_handle fh, int i, Out_it1 fit, Out_it2 eit) const { Face_handle fn = fh->neighbor(i); if (! test_conflict(p,fn)) { *eit++ = Edge(fn, fn->index(fh)); return; } *fit++ = fn; int j = fn->index(fh); propagate_conflicts(p,fn,ccw(j),fit,eit); propagate_conflicts(p,fn,cw(j),fit,eit); return; } }; template < class Gt, class Tds > inline bool Delaunay_triangulation_2:: test_conflict(const Point &p, Face_handle fh) const { return (side_of_oriented_circle(fh,p) == ON_POSITIVE_SIDE); } template < class Gt, class Tds > inline bool Delaunay_triangulation_2:: does_conflict(const Point &p, Face_handle fh) const { return test_conflict(p,fh); } template < class Gt, class Tds > inline bool Delaunay_triangulation_2:: find_conflicts(const Point &p, std::list& conflicts, Face_handle start ) const { return get_conflicts(p, std::back_inserter(conflicts), start); } template < class Gt, class Tds > bool Delaunay_triangulation_2:: is_valid(bool verbose, int level) const { bool result = Triangulation_2::is_valid(verbose, level); for( Finite_faces_iterator it = finite_faces_begin(); it != finite_faces_end() ; it++) { for(int i=0; i<3; i++) { if ( ! is_infinite( it->mirror_vertex(i))) { result = result && ON_POSITIVE_SIDE != side_of_oriented_circle( it, it->mirror_vertex(i)->point()); } CGAL_triangulation_assertion( result ); } } return result; } template < class Gt, class Tds > typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: nearest_vertex(const Point &p, Face_handle f) const { switch (dimension()) { case 0: if (number_of_vertices() == 0) return NULL; if (number_of_vertices() == 1) return finite_vertex(); //break; case 1: return nearest_vertex_1D(p); //break; case 2: return nearest_vertex_2D(p,f); //break; } return NULL; } template < class Gt, class Tds > typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: nearest_vertex_2D(const Point& p, Face_handle f) const { CGAL_triangulation_precondition(dimension() == 2); if (f == Face_handle(NULL)) f = locate(p); else CGAL_triangulation_precondition(oriented_side(f,p)!=ON_NEGATIVE_SIDE); typename Geom_traits::Compare_distance_2 closer = geom_traits().compare_distance_2_object(); Vertex_handle nn = !is_infinite(f->vertex(0)) ? f->vertex(0):f->vertex(1); if ( !is_infinite(f->vertex(1)) && closer(p, f->vertex(1)->point(), nn->point()) == SMALLER) nn=f->vertex(1); if ( !is_infinite(f->vertex(2)) && closer(p, f->vertex(2)->point(), nn->point()) == SMALLER) nn=f->vertex(2); look_nearest_neighbor(p,f,0,nn); look_nearest_neighbor(p,f,1,nn); look_nearest_neighbor(p,f,2,nn); return nn; } template < class Gt, class Tds > typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: nearest_vertex_1D(const Point& p) const { typename Geom_traits::Compare_distance_2 closer = geom_traits().compare_distance_2_object(); Vertex_handle nn; Finite_vertices_iterator vit=finite_vertices_begin(); nn = vit->handle(); for ( ; vit != finite_vertices_end(); ++vit){ if (closer(p, vit->point(), nn->point()) ) nn=vit->handle(); } return nn; } template < class Gt, class Tds > void Delaunay_triangulation_2:: look_nearest_neighbor(const Point& p, Face_handle f, int i, Vertex_handle& nn) const { Face_handle ni=f->neighbor(i); if ( ON_POSITIVE_SIDE != side_of_oriented_circle(ni,p) ) return; typename Geom_traits::Compare_distance_2 closer = geom_traits().compare_distance_2_object(); i = ni->index(f); if ( !is_infinite(ni->vertex(i)) && closer(p, ni->vertex(i)->point(), nn->point()) == SMALLER) nn=ni->vertex(i); // recursive exploration of triangles whose circumcircle contains p look_nearest_neighbor(p, ni, ccw(i), nn); look_nearest_neighbor(p, ni, cw(i), nn); } //DUALITY template inline typename Delaunay_triangulation_2::Point Delaunay_triangulation_2:: dual (Face_handle f) const { CGAL_triangulation_precondition (dimension()==2); return circumcenter(f); } template < class Gt, class Tds > Object Delaunay_triangulation_2:: dual(const Edge &e) const { typedef typename Geom_traits::Line_2 Line; typedef typename Geom_traits::Ray_2 Ray; typedef typename Geom_traits::Direction_2 Direction; CGAL_triangulation_precondition (!is_infinite(e)); if( dimension()== 1 ){ const Point& p = (e.first)->vertex(cw(e.second))->point(); const Point& q = (e.first)->vertex(ccw(e.second))->point(); Line l = geom_traits().construct_bisector_2_object()(p,q); return make_object(l); } // dimension==2 if( (!is_infinite(e.first)) && (!is_infinite(e.first->neighbor(e.second))) ) { Segment s = geom_traits().construct_segment_2_object() (dual(e.first),dual(e.first->neighbor(e.second))); return make_object(s); } // one of the adjacent face is infinite Face_handle f; int i; if (is_infinite(e.first)) { f=e.first->neighbor(e.second); f->has_neighbor(e.first,i); } else { f=e.first; i=e.second; } const Point& p = f->vertex(cw(i))->point(); const Point& q = f->vertex(ccw(i))->point(); Line l = geom_traits().construct_bisector_2_object()(p,q); Direction d = geom_traits().construct_direction_2_object()(l); Ray r = geom_traits().construct_ray_2_object()(dual(f), d); return make_object(r); } template < class Gt, class Tds > inline Object Delaunay_triangulation_2:: dual(const Edge_circulator& ec) const { return dual(*ec); } template < class Gt, class Tds > inline Object Delaunay_triangulation_2:: dual(const Finite_edges_iterator& ei) const { return dual(*ei); } template < class Gt, class Tds > inline typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: insert(const Point &p, Face_handle start) { Locate_type lt; int li; Face_handle loc = locate (p, lt, li, start); return insert(p, lt, loc, li); } template < class Gt, class Tds > inline typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: push_back(const Point &p) { return insert(p); } template < class Gt, class Tds > inline typename Delaunay_triangulation_2::Vertex_handle Delaunay_triangulation_2:: insert(const Point &p, Locate_type lt, Face_handle loc, int li) { Vertex_handle v = Triangulation_2::insert(p,lt,loc,li); restore_Delaunay(v); return(v); } template < class Gt, class Tds > void Delaunay_triangulation_2:: restore_Delaunay(Vertex_handle v) { if(dimension() <= 1) return; Face_handle f=v->face(); Face_handle next; int i; Face_handle start(f); do { i = f->index(v); next = f->neighbor(ccw(i)); // turn ccw around v propagating_flip(f,i); f=next; } while(next != start); return; } template < class Gt, class Tds > void Delaunay_triangulation_2:: remove(Vertex_handle v ) { CGAL_triangulation_precondition( v != NULL); CGAL_triangulation_precondition( !is_infinite(v)); if ( dimension() <= 1) Triangulation::remove(v); else remove_2D(v); return; } template < class Gt, class Tds > void Delaunay_triangulation_2:: propagating_flip(Face_handle& f,int i) { Face_handle n = f->neighbor(i); if ( ON_POSITIVE_SIDE != side_of_oriented_circle(n, f->vertex(i)->point()) ) { return; } flip(f, i); propagating_flip(f,i); i = n->index(f->vertex(i)); propagating_flip(n,i); } template void Delaunay_triangulation_2:: remove_2D(Vertex_handle v) { if (test_dim_down(v)) { this->_tds.remove_dim_down(v); } else { std::list hole; make_hole(v, hole); fill_hole_delaunay(hole); delete_vertex(v); } return; } CGAL_END_NAMESPACE #endif // CGAL_DELAUNAY_TRIANGULATION_2_H