cgal/Packages/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h

429 lines
11 KiB
C++

// ======================================================================
//
// 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: CGAL-2.0-I-12 $
// release_date : $CGAL_Date: 1999/04/28 $
//
// file : include/CGAL/Delaunay_triangulation_2.h
// source : $RCSfile$
// revision : $Revision$
// revision_date : $Date$
// author(s) : Mariette Yvinec
//
// coordinator : Mariette Yvinec <Mariette Yvinec@sophia.inria.fr>
//
// ======================================================================
#ifndef CGAL_DELAUNAY_TRIANGULATION_2_H
#define CGAL_DELAUNAY_TRIANGULATION_2_H
#include <CGAL/Triangulation_2.h>
CGAL_BEGIN_NAMESPACE
template < class Gt, class Tds>
class Delaunay_triangulation_2 : public Triangulation_2<Gt,Tds>
{
public:
typedef Gt Geom_traits;
typedef typename Geom_traits::Point Point;
typedef typename Geom_traits::Segment Segment;
typedef typename Geom_traits::Triangle Triangle;
typedef typename Geom_traits::Distance Distance;
typedef typename Geom_traits::Ray Ray;
typedef typename Geom_traits::Line Line;
typedef typename Geom_traits::Direction Direction;
typedef Triangulation_2<Gt,Tds> 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,Tds>(gt) {}
Delaunay_triangulation_2(
const Delaunay_triangulation_2<Gt,Tds> &tr)
: Triangulation_2<Gt,Tds>(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()) 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() );
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,
int& min,
Vertex_handle& nn,
Distance& closer) 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);
Ray r;
Segment s;
Line l;
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 < class Gt, class Tds >
bool
Delaunay_triangulation_2<Gt,Tds>::
is_valid(bool verbose, int level) const
{
bool result = Triangulation_2<Gt,Tds>::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 >
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
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 >
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
nearest_vertex_2D(const Point& p, Face_handle f) const
{
CGAL_triangulation_precondition(dimension() == 2);
Vertex_handle nn;
if (f== Face_handle()) f = locate(p);
else CGAL_triangulation_precondition(oriented_side(f,p) != ON_NEGATIVE_SIDE);
Distance closer(p,&geom_traits());
int min;
int i;
i = ( ! is_infinite(f->vertex(0)) ) ? 0 : 1;
closer.set_point(1,f->vertex(i)->point());
min = 1;
nn = f->vertex(i);
if ( ! is_infinite(f->vertex(ccw(i)))){
closer.set_point( 3-min, f->vertex(ccw(i))->point() );
if ( ( (min==1)? LARGER : SMALLER )
== closer.compare() ) {
min = 3-min;
nn=f->vertex(ccw(i));
}
}
if ( ! is_infinite(f->vertex(cw(i)))){
closer.set_point( 3-min, f->vertex(cw(i))->point() );
if ( ( (min==1)? LARGER : SMALLER )
== closer.compare() ) {
min = 3-min;
nn=f->vertex(cw(i));
}
}
look_nearest_neighbor(p,f,0,min,nn,closer);
look_nearest_neighbor(p,f,1,min,nn,closer);
look_nearest_neighbor(p,f,2,min,nn,closer);
return nn;
}
template < class Gt, class Tds >
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
nearest_vertex_1D(const Point& p) const
{
Vertex_handle nn;
Distance closer(p,&geom_traits());
int min;
Finite_vertices_iterator vit=finite_vertices_begin();
closer.set_point(1,vit->point());
min = 1;
nn = vit->handle();
do {
closer.set_point( 3-min, (++vit)->point());
if ( ( (min==1)? LARGER : SMALLER )
== closer.compare() ) {
min = 3-min;
nn=vit->handle();
}
}while( vit != finite_vertices_end());
return nn;
}
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
look_nearest_neighbor(const Point& p,
Face_handle f,
int i,
int& min,
Vertex_handle& nn,
Distance& closer) const
{
Face_handle ni=f->neighbor(i);
if ( ON_POSITIVE_SIDE != side_of_oriented_circle(ni,p) ) {
return;
}
i = ni->index(f);
if ( ! is_infinite(ni->vertex(i))){
closer.set_point( 3-min, ni->vertex(i)->point() );
if ( ( (min==1)? LARGER : SMALLER )
== closer.compare() ) {
min = 3-min;
nn=ni->vertex(i);
}
}
// recursive exploration of triangles whose circumcircle contains p
look_nearest_neighbor(p, ni, ccw(i), min, nn, closer);
look_nearest_neighbor(p, ni, cw(i), min, nn, closer);
}
//DUALITY
template<class Gt, class Tds>
Delaunay_triangulation_2<Gt,Tds>::Point
Delaunay_triangulation_2<Gt,Tds>::
dual (Face_handle f) const
{
CGAL_triangulation_precondition (dimension()==2);
return geom_traits().circumcenter(f->vertex(0)->point(),
f->vertex(1)->point(),
f->vertex(2)->point());
}
template < class Gt, class Tds >
Object
Delaunay_triangulation_2<Gt,Tds>::
dual(const Edge &e) const
{
CGAL_triangulation_precondition (!is_infinite(e));
if( dimension()== 1 ){
Line l = geom_traits().bisector(segment(e)).opposite();
return Object(new Wrapper< Line >(l));
}
// dimension==2
if( (!is_infinite(e.first)) &&
(!is_infinite(e.first->neighbor(e.second))) ) {
Segment s(dual(e.first),dual(e.first->neighbor(e.second)));
return Object(new Wrapper< Segment >(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;
}
Line l = geom_traits().bisector(segment(f,i)).opposite();
Ray r(dual(f),l.direction());
return Object(new Wrapper< Ray >(r));
}
template < class Gt, class Tds >
inline Object
Delaunay_triangulation_2<Gt,Tds>::
dual(const Edge_circulator& ec) const
{
return dual(*ec);
}
template < class Gt, class Tds >
inline Object
Delaunay_triangulation_2<Gt,Tds>::
dual(const Finite_edges_iterator& ei) const
{
return dual(*ei);
}
template < class Gt, class Tds >
inline
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
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
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
push_back(const Point &p)
{
return insert(p);
}
template < class Gt, class Tds >
inline
Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
Delaunay_triangulation_2<Gt,Tds>::
insert(const Point &p, Locate_type lt, Face_handle loc, int li)
{
Vertex_handle v = Triangulation_2<Gt,Tds>::insert(p,lt,loc,li);
restore_Delaunay(v);
return(v);
}
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
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<Gt,Tds>::
remove(Vertex_handle v )
{
CGAL_triangulation_precondition( v != Vertex_handle());
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<Gt,Tds>::
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 <class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
remove_2D(Vertex_handle v)
{
if (test_dim_down(v)) { _tds.remove_dim_down(&(*v)); }
else {
std::list<Edge> hole;
make_hole(v, hole);
fill_hole_delaunay(hole);
delete &(*v);
set_number_of_vertices(number_of_vertices()-1);
}
return;
}
CGAL_END_NAMESPACE
#endif // CGAL_DELAUNAY_TRIANGULATION_2_H