mirror of https://github.com/CGAL/cgal
2590 lines
82 KiB
C++
2590 lines
82 KiB
C++
// Copyright (c) 1997 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) : Mariette Yvinec
|
|
// : Olivier Devillers (remove)
|
|
// : Pedro de Castro (displacement)
|
|
|
|
|
|
|
|
#ifndef CGAL_DELAUNAY_TRIANGULATION_2_H
|
|
#define CGAL_DELAUNAY_TRIANGULATION_2_H
|
|
|
|
#include <CGAL/Triangulation_2.h>
|
|
#include <CGAL/iterator.h>
|
|
|
|
namespace CGAL {
|
|
|
|
template < class Gt,
|
|
class Tds = Triangulation_data_structure_2 <
|
|
Triangulation_vertex_base_2<Gt> > >
|
|
class Delaunay_triangulation_2 : public Triangulation_2<Gt,Tds>
|
|
{
|
|
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<Gt,Tds> Triangulation;
|
|
typedef typename Triangulation::size_type size_type;
|
|
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::Face_circulator Face_circulator;
|
|
typedef typename Triangulation::Vertex_circulator Vertex_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;
|
|
typedef typename Triangulation::All_faces_iterator All_faces_iterator;
|
|
|
|
#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
|
|
using Triangulation::side_of_oriented_circle;
|
|
using Triangulation::circumcenter;
|
|
using Triangulation::collinear_between;
|
|
using Triangulation::test_dim_down;
|
|
using Triangulation::make_hole;
|
|
using Triangulation::fill_hole_delaunay;
|
|
using Triangulation::delete_vertex;
|
|
#endif
|
|
|
|
|
|
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;
|
|
|
|
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<Face_handle>& conflicts,
|
|
Face_handle start= Face_handle() ) const;
|
|
// //template member functions, declared and defined at the end
|
|
// template <class OutputItFaces, class OutputItBoundaryEdges>
|
|
// std::pair<OutputItFaces,OutputItBoundaryEdges>
|
|
// get_conflicts_and_boundary(const Point &p,
|
|
// OutputItFaces fit,
|
|
// OutputItBoundaryEdges eit,
|
|
// Face_handle start) const;
|
|
// template <class OutputItFaces>
|
|
// OutputItFaces
|
|
// get_conflicts (const Point &p,
|
|
// OutputItFaces fit,
|
|
// Face_handle start ) const;
|
|
// template <class OutputItBoundaryEdges>
|
|
// OutputItBoundaryEdges
|
|
// get_boundary_of_conflicts(const Point &p,
|
|
// OutputItBoundaryEdges 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() );
|
|
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 );
|
|
|
|
// DISPLACEMENT
|
|
void restore_Delaunay(Vertex_handle v);
|
|
|
|
Vertex_handle move_if_no_collision(Vertex_handle v, const Point &p);
|
|
Vertex_handle move(Vertex_handle v, const Point &p);
|
|
|
|
protected: // some internal stuffs
|
|
|
|
template <class OutputItFaces>
|
|
Vertex_handle insert_and_give_new_faces(const Point &p,
|
|
OutputItFaces fit,
|
|
Face_handle start = Face_handle() );
|
|
template <class OutputItFaces>
|
|
Vertex_handle insert_and_give_new_faces(const Point& p,
|
|
Locate_type lt,
|
|
Face_handle loc, int li,
|
|
OutputItFaces fit);
|
|
|
|
template <class OutputItFaces>
|
|
Vertex_handle move_if_no_collision_and_give_new_faces(Vertex_handle v,
|
|
const Point &p,
|
|
OutputItFaces fit);
|
|
|
|
template <class OutputItFaces>
|
|
void remove_and_give_new_faces(Vertex_handle v,
|
|
OutputItFaces fit);
|
|
public:
|
|
|
|
bool is_delaunay_after_displacement(Vertex_handle v,
|
|
const Point &p) const;
|
|
|
|
#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
|
|
using Triangulation::cw;
|
|
using Triangulation::ccw;
|
|
using Triangulation::geom_traits;
|
|
#endif
|
|
|
|
private:
|
|
void propagating_flip(Face_handle& f,int i);
|
|
void remove_2D(Vertex_handle v );
|
|
|
|
// auxilliary functions for remove
|
|
void remove_degree_init(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i,int&d,int&maxd);
|
|
void remove_degree_triangulate(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i,int d);
|
|
void remove_degree_d(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i,int d);
|
|
void remove_degree3(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree4(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree5(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i );
|
|
void remove_degree5_star (Vertex_handle &v,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
int ,int ,int ,int ,int );
|
|
void remove_degree6(Vertex_handle v , std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree6_star (Vertex_handle &v,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
int ,int ,int ,
|
|
int ,int ,int );
|
|
void remove_degree6_N (Vertex_handle &v,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
int ,int ,int ,
|
|
int ,int ,int );
|
|
void remove_degree6_antiN (Vertex_handle &v,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
int ,int ,int ,
|
|
int ,int ,int );
|
|
void remove_degree6_diamond(Vertex_handle &v,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Face_handle & ,Face_handle & ,Face_handle & ,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
Vertex_handle&,Vertex_handle&,Vertex_handle&,
|
|
int ,int ,int ,
|
|
int ,int ,int );
|
|
void remove_degree7(Vertex_handle v,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
bool incircle(int x, int j, int k, int l, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i){
|
|
// k is supposed to be j+1 modulo degree, x is supposed to be finite
|
|
//test if w[x] inside circle w[j]w[k]w[l] (f[j] has vertices w[j]w[k])
|
|
// THE FOLLOWING LINE IS TO BE REMOVED. JUST THERE FOR STUPID PRECONDITION
|
|
//if (geom_traits().orientation_2_object()(w[j]->point(),w[k]->point(),w[l]->point())!=POSITIVE) return true;
|
|
f[j]->set_vertex( i[j], w[l]) ; // change vertex v for another one
|
|
return (test_conflict( w[x]->point(), f[j]) );
|
|
}
|
|
void rotate7(int j, std::vector<Vertex_handle> &w,
|
|
std::vector<Face_handle> &f, std::vector<int> &i);
|
|
void remove_degree7_star (Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree7_zigzag (Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree7_leftdelta (Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree7_rightdelta(Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree7_leftfan (Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
void remove_degree7_rightfan (Vertex_handle&,int,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i);
|
|
// end of auxilliary functions for remove
|
|
|
|
|
|
|
|
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= this->finite_edges_begin();
|
|
for (; eit != this->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 >
|
|
std::ptrdiff_t
|
|
insert(InputIterator first, InputIterator last)
|
|
{
|
|
size_type n = this->number_of_vertices();
|
|
|
|
std::vector<Point> points (first, last);
|
|
spatial_sort (points.begin(), points.end(), geom_traits());
|
|
Face_handle f;
|
|
for (typename std::vector<Point>::const_iterator p = points.begin(), end = points.end();
|
|
p != end; ++p)
|
|
f = insert (*p, f)->face();
|
|
|
|
return this->number_of_vertices() - n;
|
|
}
|
|
|
|
template <class OutputItFaces, class OutputItBoundaryEdges>
|
|
std::pair<OutputItFaces,OutputItBoundaryEdges>
|
|
get_conflicts_and_boundary(const Point &p,
|
|
OutputItFaces fit,
|
|
OutputItBoundaryEdges eit,
|
|
Face_handle start = Face_handle()) const {
|
|
CGAL_triangulation_precondition( this->dimension() == 2);
|
|
int li;
|
|
Locate_type lt;
|
|
Face_handle fh = this->locate(p,lt,li, start);
|
|
switch(lt) {
|
|
case Triangulation::OUTSIDE_AFFINE_HULL:
|
|
case Triangulation::VERTEX:
|
|
return std::make_pair(fit,eit);
|
|
case Triangulation::FACE:
|
|
case Triangulation::EDGE:
|
|
case Triangulation::OUTSIDE_CONVEX_HULL:
|
|
*fit++ = fh; //put fh in OutputItFaces
|
|
std::pair<OutputItFaces,OutputItBoundaryEdges>
|
|
pit = std::make_pair(fit,eit);
|
|
pit = propagate_conflicts(p,fh,0,pit);
|
|
pit = propagate_conflicts(p,fh,1,pit);
|
|
pit = propagate_conflicts(p,fh,2,pit);
|
|
return pit;
|
|
}
|
|
CGAL_triangulation_assertion(false);
|
|
return std::make_pair(fit,eit);
|
|
}
|
|
|
|
template <class OutputItFaces>
|
|
OutputItFaces
|
|
get_conflicts (const Point &p,
|
|
OutputItFaces fit,
|
|
Face_handle start= Face_handle()) const {
|
|
std::pair<OutputItFaces,Emptyset_iterator> pp =
|
|
get_conflicts_and_boundary(p,fit,Emptyset_iterator(),start);
|
|
return pp.first;
|
|
}
|
|
|
|
template <class OutputItBoundaryEdges>
|
|
OutputItBoundaryEdges
|
|
get_boundary_of_conflicts(const Point &p,
|
|
OutputItBoundaryEdges eit,
|
|
Face_handle start= Face_handle()) const {
|
|
std::pair<Emptyset_iterator, OutputItBoundaryEdges> pp =
|
|
get_conflicts_and_boundary(p,Emptyset_iterator(),eit,start);
|
|
return pp.second;
|
|
}
|
|
|
|
private:
|
|
template <class OutputItFaces, class OutputItBoundaryEdges>
|
|
std::pair<OutputItFaces,OutputItBoundaryEdges>
|
|
propagate_conflicts (const Point &p,
|
|
Face_handle fh,
|
|
int i,
|
|
std::pair<OutputItFaces,OutputItBoundaryEdges>
|
|
pit) const {
|
|
Face_handle fn = fh->neighbor(i);
|
|
if (! test_conflict(p,fn)) {
|
|
*(pit.second)++ = Edge(fn, fn->index(fh));
|
|
} else {
|
|
*(pit.first)++ = fn;
|
|
int j = fn->index(fh);
|
|
pit = propagate_conflicts(p,fn,ccw(j),pit);
|
|
pit = propagate_conflicts(p,fn,cw(j), pit);
|
|
}
|
|
return pit;
|
|
}
|
|
|
|
protected:
|
|
|
|
void restore_edges(Vertex_handle v)
|
|
{
|
|
std::list<Edge> edges;
|
|
Face_circulator fc = this->incident_faces(v), done(fc);
|
|
int degree = 0;
|
|
do {
|
|
if((++degree) > 3) break;
|
|
} while(++fc != done);
|
|
fc = this->incident_faces(v);
|
|
done = fc;
|
|
if(degree == 3) {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
} while(++fc != done);
|
|
} else {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
edges.push_back(Edge(fc, this->cw(i)));
|
|
} while(++fc != done);
|
|
}
|
|
while(!edges.empty()) {
|
|
const Edge &e = edges.front();
|
|
Face_handle f = e.first;
|
|
int i = e.second;
|
|
edges.pop_front();
|
|
if(this->is_infinite(f->vertex(i))) continue;
|
|
Face_handle fi = f->neighbor(i);
|
|
int mi = this->_tds.mirror_index(f, i);
|
|
Vertex_handle vm = this->_tds.mirror_vertex(f, i);
|
|
if(this->is_infinite(vm)) continue;
|
|
if(this->side_of_oriented_circle(f, vm->point(),true) == ON_POSITIVE_SIDE) {
|
|
this->_tds.flip(f, i);
|
|
edges.push_back(Edge(f, i));
|
|
edges.push_back(Edge(f, this->cw(i)));
|
|
edges.push_back(Edge(fi, this->cw(mi)));
|
|
edges.push_back(Edge(fi, mi));
|
|
}
|
|
}
|
|
}
|
|
|
|
void restore_edges(Vertex_handle v, std::set<Face_handle> &faces)
|
|
{
|
|
typedef std::list<Edge> Edges_list;
|
|
Edges_list edges;
|
|
Face_circulator fc = this->incident_faces(v), done(fc);
|
|
int degree = 0;
|
|
do {
|
|
if((++degree) > 3) break;
|
|
} while(++fc != done);
|
|
fc = this->incident_faces(v);
|
|
done = fc;
|
|
if(degree == 3) {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
} while(++fc != done);
|
|
} else {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
edges.push_back(Edge(fc, this->cw(i)));
|
|
} while(++fc != done);
|
|
}
|
|
while(!edges.empty()) {
|
|
const Edge &e = edges.front();
|
|
Face_handle f = e.first;
|
|
int i = e.second;
|
|
edges.pop_front();
|
|
faces.insert(f);
|
|
if(this->is_infinite(f->vertex(i))) continue;
|
|
Face_handle fi = f->neighbor(i);
|
|
int mi = this->_tds.mirror_index(f, i);
|
|
Vertex_handle vm = this->_tds.mirror_vertex(f, i);
|
|
if(this->is_infinite(vm)) continue;
|
|
if(this->side_of_oriented_circle(f, vm->point()) == ON_POSITIVE_SIDE) {
|
|
this->_tds.flip(f, i);
|
|
edges.push_back(Edge(f, i));
|
|
edges.push_back(Edge(f, this->cw(i)));
|
|
edges.push_back(Edge(fi, this->cw(mi)));
|
|
edges.push_back(Edge(fi, mi));
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
template < class Gt, class Tds >
|
|
inline bool
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
test_conflict(const Point &p, Face_handle fh) const
|
|
{
|
|
// return true if P is inside the circumcircle of fh
|
|
// if fh is infinite, return true when p is in the positive
|
|
// halfspace or on the boundary and in the finite edge of fh
|
|
Oriented_side os = side_of_oriented_circle(fh,p,true);
|
|
if (os == ON_POSITIVE_SIDE) return true;
|
|
|
|
if (os == ON_ORIENTED_BOUNDARY && this->is_infinite(fh)) {
|
|
int i = fh->index(this->infinite_vertex());
|
|
return collinear_between(fh->vertex(cw(i))->point(), p,
|
|
fh->vertex(ccw(i))->point() );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline bool
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
does_conflict(const Point &p, Face_handle fh) const
|
|
{
|
|
return test_conflict(p,fh);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline bool
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
find_conflicts(const Point &p,
|
|
std::list<Face_handle>& conflicts,
|
|
Face_handle start ) const
|
|
{
|
|
get_conflicts(p, std::back_inserter(conflicts), start);
|
|
return (! conflicts.empty());
|
|
}
|
|
|
|
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 = this->finite_faces_begin();
|
|
it != this->finite_faces_end() ; it++) {
|
|
for(int i=0; i<3; i++) {
|
|
if ( ! this->is_infinite( this->mirror_vertex(it,i))) {
|
|
result = result && ON_POSITIVE_SIDE !=
|
|
side_of_oriented_circle( it, this->mirror_vertex(it,i)->point(), false);
|
|
}
|
|
CGAL_triangulation_assertion( result );
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
nearest_vertex(const Point &p, Face_handle f) const
|
|
{
|
|
switch (this->dimension()) {
|
|
case 0:
|
|
if (this->number_of_vertices() == 0) return Vertex_handle();
|
|
if (this->number_of_vertices() == 1) return this->finite_vertex();
|
|
//break;
|
|
case 1:
|
|
return nearest_vertex_1D(p);
|
|
//break;
|
|
case 2:
|
|
return nearest_vertex_2D(p,f);
|
|
//break;
|
|
}
|
|
return Vertex_handle();
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
typename 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(this->dimension() == 2);
|
|
f = this->locate(p,f);
|
|
|
|
typename Geom_traits::Compare_distance_2
|
|
compare_distance = this->geom_traits().compare_distance_2_object();
|
|
Vertex_handle nn = !this->is_infinite(f->vertex(0)) ? f->vertex(0):f->vertex(1);
|
|
if ( !this->is_infinite(f->vertex(1)) && compare_distance(p,
|
|
f->vertex(1)->point(),
|
|
nn->point()) == SMALLER)
|
|
nn=f->vertex(1);
|
|
if ( !this->is_infinite(f->vertex(2)) && compare_distance(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<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
nearest_vertex_1D(const Point& p) const
|
|
{
|
|
typename Geom_traits::Compare_distance_2
|
|
compare_distance = this->geom_traits().compare_distance_2_object();
|
|
Vertex_handle nn;
|
|
|
|
Finite_vertices_iterator vit=this->finite_vertices_begin();
|
|
nn = vit;
|
|
for ( ; vit != this->finite_vertices_end(); ++vit){
|
|
if (compare_distance(p, vit->point(), nn->point()) == SMALLER)
|
|
nn = vit;
|
|
}
|
|
return nn;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
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,true) ) return;
|
|
|
|
typename Geom_traits::Compare_distance_2
|
|
compare_distance = this->geom_traits().compare_distance_2_object();
|
|
i = ni->index(f);
|
|
if ( !this->is_infinite(ni->vertex(i)) &&
|
|
compare_distance(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<class Gt, class Tds>
|
|
inline
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Point
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
dual (Face_handle f) const
|
|
{
|
|
CGAL_triangulation_precondition (this->dimension()==2);
|
|
return circumcenter(f);
|
|
}
|
|
|
|
|
|
template < class Gt, class Tds >
|
|
Object
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
dual(const Edge &e) const
|
|
{
|
|
typedef typename Geom_traits::Line_2 Line;
|
|
typedef typename Geom_traits::Ray_2 Ray;
|
|
|
|
CGAL_triangulation_precondition (!this->is_infinite(e));
|
|
if( this->dimension()== 1 ){
|
|
const Point& p = (e.first)->vertex(cw(e.second))->point();
|
|
const Point& q = (e.first)->vertex(ccw(e.second))->point();
|
|
Line l = this->geom_traits().construct_bisector_2_object()(p,q);
|
|
return make_object(l);
|
|
}
|
|
|
|
// dimension==2
|
|
if( (!this->is_infinite(e.first)) &&
|
|
(!this->is_infinite(e.first->neighbor(e.second))) ) {
|
|
Segment s = this->geom_traits().construct_segment_2_object()
|
|
(dual(e.first),dual(e.first->neighbor(e.second)));
|
|
return make_object(s);
|
|
}
|
|
// one of the adjacent faces is infinite
|
|
Face_handle f; int i;
|
|
if (this->is_infinite(e.first)) {
|
|
f=e.first->neighbor(e.second); i=f->index(e.first);
|
|
}
|
|
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 = this->geom_traits().construct_bisector_2_object()(p,q);
|
|
Ray r = this->geom_traits().construct_ray_2_object()(dual(f), l);
|
|
return make_object(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);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// INSERT
|
|
|
|
template < class Gt, class Tds >
|
|
inline
|
|
typename 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 = this->locate (p, lt, li, start);
|
|
return insert(p, lt, loc, li);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline
|
|
typename 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
|
|
typename 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 >
|
|
template < class OutputItFaces >
|
|
inline
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
insert_and_give_new_faces(const Point &p,
|
|
OutputItFaces oif,
|
|
Face_handle start)
|
|
{
|
|
Vertex_handle v = insert(p, start);
|
|
int dimension = this->dimension();
|
|
if(dimension == 2)
|
|
{
|
|
Face_circulator fc = this->incident_faces(v), done(fc);
|
|
do {
|
|
*oif++ = fc;
|
|
} while(++fc != done);
|
|
}
|
|
else if(dimension == 1)
|
|
{
|
|
Face_handle c = v->face();
|
|
*oif++ = c;
|
|
*oif++ = c->neighbor((~(c->index(v)))&1);
|
|
}
|
|
else *oif++ = v->face(); // dimension == 0
|
|
return v;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
template < class OutputItFaces >
|
|
inline
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
insert_and_give_new_faces(const Point &p,
|
|
Locate_type lt,
|
|
Face_handle loc, int li,
|
|
OutputItFaces oif)
|
|
{
|
|
Vertex_handle v = insert(p, lt, loc, li);
|
|
int dimension = this->dimension();
|
|
if(dimension == 2)
|
|
{
|
|
Face_circulator fc = this->incident_faces(v), done(fc);
|
|
do {
|
|
*oif++ = fc;
|
|
} while(++fc != done);
|
|
}
|
|
else if(dimension == 1)
|
|
{
|
|
Face_handle c = v->face();
|
|
*oif++ = c;
|
|
*oif++ = c->neighbor((~(c->index(v)))&1);
|
|
}
|
|
else *oif++ = v->face(); // dimension == 0
|
|
return v;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
restore_Delaunay(Vertex_handle v)
|
|
{
|
|
if(this->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>::
|
|
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(), true) ) {
|
|
return;
|
|
}
|
|
this->flip(f, i);
|
|
propagating_flip(f,i);
|
|
i = n->index(f->vertex(i));
|
|
propagating_flip(n,i);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// REMOVE see INRIA RResearch Report 7104
|
|
|
|
template < class Gt, class Tds >
|
|
template <class OutputItFaces>
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_and_give_new_faces(Vertex_handle v, OutputItFaces fit)
|
|
{
|
|
CGAL_triangulation_precondition( v != Vertex_handle());
|
|
CGAL_triangulation_precondition( !this->is_infinite(v));
|
|
|
|
if(this->number_of_vertices() == 1) this->remove_first(v);
|
|
else if(this->number_of_vertices() == 2) this->remove_second(v);
|
|
else if( this->dimension() == 1)
|
|
{
|
|
Point p = v->point();
|
|
Triangulation::remove(v);
|
|
*fit++ = this->locate(p);
|
|
}
|
|
else if (this->test_dim_down(v)) {
|
|
this->_tds.remove_dim_down(v);
|
|
for(All_faces_iterator afi = this-> all_faces_begin();
|
|
afi != this->all_faces_end();
|
|
afi++) *fit++ = afi;
|
|
}
|
|
else {
|
|
static int maxd=30;
|
|
static std::vector<Face_handle> f(maxd);
|
|
static std::vector<int> i(maxd);
|
|
static std::vector<Vertex_handle> w(maxd);
|
|
int d;
|
|
remove_degree_init(v,f,w,i,d,maxd);
|
|
remove_degree_triangulate(v,f,w,i,d);
|
|
this->delete_vertex(v);
|
|
Face_circulator fc(v[0]),done;
|
|
do *fit++ = fc++; while (fc!=done);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove(Vertex_handle v)
|
|
{
|
|
int d;
|
|
|
|
CGAL_triangulation_precondition( v != Vertex_handle());
|
|
CGAL_triangulation_precondition( !this->is_infinite(v));
|
|
|
|
if ( this->dimension() <= 1) { Triangulation::remove(v); return; }
|
|
|
|
static int maxd=30;
|
|
static std::vector<Face_handle> f(maxd);
|
|
static std::vector<int> i(maxd);
|
|
static std::vector<Vertex_handle> w(maxd);
|
|
remove_degree_init(v,f,w,i,d,maxd);
|
|
if (d == 0) return; // dim is going down
|
|
remove_degree_triangulate(v,f,w,i,d);
|
|
this->delete_vertex(v);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree_init(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i,
|
|
int &d, int &maxd)
|
|
{
|
|
f[0] = v->face();d=0;
|
|
do{
|
|
i[d] = f[d]->index(v);
|
|
w[d] = f[d]->vertex( ccw(i[d]) );
|
|
if(this->is_infinite(w[d])) {
|
|
f[0] = f[d]; i[0]=i[d]; w[0]=w[d];
|
|
w[0]->set_face( f[0]->neighbor(i[0]));
|
|
f[1] = f[0]->neighbor( ccw(i[0]) );
|
|
i[1] = f[1]->index(v);
|
|
w[1] = f[1]->vertex( ccw(i[1]) );
|
|
if ( this->is_infinite( f[1]->neighbor( i[1] ) ) ){//otherwise dim remains 2
|
|
if ( this->test_dim_down(v) ) {
|
|
d=0;
|
|
this->tds().remove_dim_down(v);
|
|
return;
|
|
}
|
|
}
|
|
d=1;
|
|
}
|
|
w[d]->set_face( f[d]->neighbor(i[d]));//do no longer bother about set_face
|
|
++d;
|
|
if ( d==maxd) { maxd *=2; f.resize(maxd); w.resize(maxd); i.resize(maxd);}
|
|
f[d] = f[d-1]->neighbor( ccw(i[d-1]) );
|
|
} while(f[d]!=f[0]);
|
|
// all vertices finite but possibly w[0]
|
|
}
|
|
|
|
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree_triangulate(Vertex_handle v,
|
|
std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w,
|
|
std::vector<int> &i,int d)
|
|
{
|
|
switch (d) {
|
|
case 3:
|
|
remove_degree3(v,f,w,i); break;
|
|
case 4:
|
|
remove_degree4(v,f,w,i); break;
|
|
case 5:
|
|
remove_degree5(v,f,w,i); break;
|
|
case 6:
|
|
remove_degree6(v,f,w,i); break;
|
|
case 7:
|
|
remove_degree7(v,f,w,i); break;
|
|
default:
|
|
remove_degree_d(v,f,w,i,d); break;
|
|
}
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree_d(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w,
|
|
std::vector<int> &i,int d)
|
|
{
|
|
// removing a degree d vertex, d>4 needed, used if d is big
|
|
// only w[0] can be infinite
|
|
enum type_of_edge{ boundary, locally_delaunay, unknown};
|
|
std::map<Face_handle, int> type[3];
|
|
std::list<Edge> to_be_checked;
|
|
int j=1;
|
|
Face_handle nn;
|
|
|
|
// process pentagon by pentagon
|
|
// next pentagon is w[0] w[j] w[j+1] w[j+2] w[j+3]
|
|
Face_handle last=f[0]->neighbor(i[0]);
|
|
int ilast = last->index(f[0]);
|
|
int typelast = boundary;
|
|
type[ ilast][last]= typelast;
|
|
|
|
while(j<=d-4){
|
|
if( incircle(j+2,j,j+1,0,f,w,i) ) {
|
|
if( incircle(j,j+2,j+3,0,f,w,i) ) {
|
|
if( incircle(j+3,j,j+1,j+2,f,w,i) ) { // star from j+3/////////////////
|
|
f[j ]->set_vertex( i[j ], w[j+3]) ;
|
|
f[j+1]->set_vertex( i[j+1], w[j+3]) ;
|
|
f[j+2]->set_vertex( i[j+2], w[0 ]) ;
|
|
f[j+2]->set_vertex(ccw(i[j+2]), w[j ]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast , f[j+2], cw(i[j+2]));
|
|
type[ cw(i[j+2])][f[j+2]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j+2], cw(i[j+2])));
|
|
|
|
// edge w[j] w[j+1]
|
|
type[i[j]][f[j]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
type[i[j+1]][f[j+1]] = boundary;
|
|
|
|
// edge w[j+2] w[j+3]
|
|
nn = f[j+2]->neighbor( i[j+2] );
|
|
this->tds().set_adjacency(f[j+1], ccw(i[j+1]) ,
|
|
nn, cw(nn->index(w[j+3])) );
|
|
type[ccw(i[j+1])][f[j+1]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j+2];
|
|
ilast = ccw(i[j+2]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[j] w[j+3]
|
|
this->tds().set_adjacency(f[j+2], i[j+2] , f[j], cw(i[j ]));
|
|
type[ i[j+2] ][f[j+2]] = locally_delaunay;
|
|
type[ cw(i[j ])][f[j ]] = locally_delaunay;
|
|
// edge w[j+1] w[j+3]
|
|
type[ cw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ccw(i[j ])][f[j ]] = locally_delaunay;
|
|
}else{ //star from j/////////////////
|
|
f[j ]->set_vertex( i[j ] , w[0 ]) ;
|
|
f[j ]->set_vertex( cw(i[j ]), w[j+3]) ;
|
|
f[j+1]->set_vertex( i[j+1] , w[j ]) ;
|
|
f[j+2]->set_vertex( i[j+2] , w[j ]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast , f[j], cw(i[j]) );
|
|
type[ cw(i[j])][f[j]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j], cw(i[j])));
|
|
|
|
// edge w[j] w[j+1]
|
|
nn = f[j]->neighbor( i[j] );
|
|
this->tds().set_adjacency(f[j+1], cw(i[j+1]),
|
|
nn, cw(nn->index(w[j+1])) );
|
|
type[cw(i[j+1])][f[j+1]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
type[i[j+1]][f[j+1]] = boundary;
|
|
|
|
// edge w[j+2] w[j+3]
|
|
type[i[j+2]][f[j+2]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j];
|
|
ilast = ccw(i[j]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[j] w[j+3]
|
|
this->tds().set_adjacency(f[j+2], ccw(i[j+2]), f[j], i[j]);
|
|
type[ i[j ] ][f[j ]] = locally_delaunay;
|
|
type[ccw(i[j+2])][f[j+2]] = locally_delaunay;
|
|
// edge w[j] w[j+2]
|
|
type[ccw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ cw(i[j+2])][f[j+2]] = locally_delaunay;
|
|
}}else{ // star from j+2///////////////////
|
|
f[j ]->set_vertex( i[j ] , w[j+2]) ;
|
|
f[j+1]->set_vertex( i[j+1] , w[0 ]) ;
|
|
f[j+1]->set_vertex(ccw(i[j+1]), w[j ]) ;
|
|
f[j+2]->set_vertex( i[j+2] , w[0 ]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast, f[j+1], cw(i[j+1]));
|
|
type[cw(i[j+1])][f[j+1]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j+1], cw(i[j+1])));
|
|
|
|
// edge w[j] w[j+1]
|
|
type[i[j]][f[j]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
nn = f[j+1]->neighbor( i[j+1] );
|
|
this->tds().set_adjacency(f[j], ccw(i[j]), nn, cw(nn->index(w[j+2])));
|
|
type[ccw(i[j])][f[j]] = boundary;
|
|
|
|
// edge w[j+2] w[j+3]
|
|
type[i[j+2]][f[j+2]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j+2];
|
|
ilast = ccw(i[j+2]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[0] w[j+2]
|
|
this->tds().set_adjacency(f[j+2], cw(i[j+2]), f[j+1], ccw(i[j+1]));
|
|
type[ccw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ cw(i[j+2])][f[j+2]] = locally_delaunay;
|
|
// edge w[j] w[j+2]
|
|
this->tds().set_adjacency(f[j], cw(i[j]), f[j+1], i[j+1]);
|
|
type[ cw(i[j ])][f[j ]] = locally_delaunay;
|
|
type[ i[j+1] ][f[j+1]] = locally_delaunay;
|
|
}}else{
|
|
if( incircle(j+3,j+1,j+2,0,f,w,i) ) {
|
|
if( incircle(j+3,j,j+1,0,f,w,i) ) { // star from j+3///////////////////
|
|
f[j ]->set_vertex( i[j ], w[j+3]) ;
|
|
f[j+1]->set_vertex( i[j+1], w[j+3]) ;
|
|
f[j+2]->set_vertex( i[j+2], w[0 ]) ;
|
|
f[j+2]->set_vertex(ccw(i[j+2]), w[j ]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast, f[j+2], cw(i[j+2]) );
|
|
type[ cw(i[j+2])][f[j+2]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j+2], cw(i[j+2])));
|
|
|
|
// edge w[j] w[j+1]
|
|
type[i[j]][f[j]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
type[i[j+1]][f[j+1]] = boundary;
|
|
|
|
// edge w[j+2] w[j+3]
|
|
nn = f[j+2]->neighbor( i[j+2] );
|
|
this->tds().set_adjacency(f[j+1], ccw(i[j+1]),
|
|
nn, cw(nn->index(w[j+3])) );
|
|
type[ccw(i[j+1])][f[j+1]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j+2];
|
|
ilast = ccw(i[j+2]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[j] w[j+3]
|
|
this->tds().set_adjacency(f[j+2], i[j+2] , f[j], cw(i[j]) );
|
|
type[ i[j+2] ][f[j+2]] = locally_delaunay;
|
|
type[ cw(i[j ])][f[j ]] = locally_delaunay;
|
|
// edge w[j+1] w[j+3]
|
|
type[ cw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ccw(i[j ])][f[j ]] = locally_delaunay;
|
|
}else{ // star from j+1///////////////////
|
|
f[j ]->set_vertex( i[j ], w[0 ]) ;
|
|
f[j+1]->set_vertex( i[j+1], w[0 ]) ;
|
|
f[j+1]->set_vertex( cw(i[j+1]),w[j+3]) ;
|
|
f[j+2]->set_vertex( i[j+2], w[j+1]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast , f[j], cw(i[j]) );
|
|
type[ cw(i[j])][f[j]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j], cw(i[j])));
|
|
|
|
// edge w[j] w[j+1]
|
|
type[i[j]][f[j]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
nn = f[j+1]->neighbor( i[j+1] );
|
|
this->tds().set_adjacency(f[j+2], cw(i[j+2]),
|
|
nn , cw(nn->index(w[j+2])) );
|
|
type[ cw(i[j+2])][f[j+2]] = boundary;
|
|
// edge w[j+2] w[j+3]
|
|
type[i[j+2]][f[j+2]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j+1];
|
|
ilast = ccw(i[j+1]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[j+1] w[0]
|
|
type[ccw(i[j ])][f[j ]] = locally_delaunay;
|
|
type[ cw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
// edge w[j+1] w[j+3]
|
|
this->tds().set_adjacency(f[j+2], ccw(i[j+2]), f[j+1], i[j+1] );
|
|
type[ i[j+1] ][f[j+1]] = locally_delaunay;
|
|
type[ccw(i[j+2])][f[j+2]] = locally_delaunay;
|
|
}}else{ // star from 0///////////////////
|
|
f[j ]->set_vertex( i[j ], w[0 ]) ;
|
|
f[j+1]->set_vertex( i[j+1], w[0 ]) ;
|
|
f[j+2]->set_vertex( i[j+2], w[0 ]) ;
|
|
|
|
// edge w[0] w[j]
|
|
this->tds().set_adjacency(last, ilast, f[j], cw(i[j]) );
|
|
type[ cw(i[j])][f[j]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[j], cw(i[j])));
|
|
|
|
// edge w[j] w[j+1]
|
|
type[i[j]][f[j]] = boundary;
|
|
// edge w[j+1] w[j+2]
|
|
type[i[j+1]][f[j+1]] = boundary;
|
|
// edge w[j+2] w[j+3]
|
|
type[i[j+2]][f[j+2]] = boundary;
|
|
|
|
// edge w[j+3] w[0]
|
|
last = f[j+2];
|
|
ilast = ccw(i[j+2]);
|
|
type[ilast][last]=typelast=unknown;
|
|
|
|
// edge w[0] w[j+1]
|
|
type[ cw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ccw(i[j ])][f[j ]] = locally_delaunay;
|
|
// edge w[0] w[j+2]
|
|
type[ccw(i[j+1])][f[j+1]] = locally_delaunay;
|
|
type[ cw(i[j+2])][f[j+2]] = locally_delaunay;
|
|
}}
|
|
j+=3;
|
|
}
|
|
|
|
if(j ==d-1){
|
|
type[ilast][last]=typelast=boundary;
|
|
nn= f[d-1]->neighbor( i[d-1] );
|
|
this->tds().set_adjacency(last, ilast, nn, cw(nn->index(w[0])) );
|
|
}
|
|
if(j ==d-2){
|
|
f[d-2]->set_vertex( i[d-2], w[0]);
|
|
nn= f[d-1]->neighbor( i[d-1] );
|
|
this->tds().set_adjacency(f[d-2], ccw(i[d-2]), nn, cw(nn->index(w[0])) );
|
|
type[ccw(i[d-2])][f[d-2]]=boundary;
|
|
this->tds().set_adjacency(last, ilast, f[d-2] , cw(i[d-2]) );
|
|
type[ cw(i[d-2])][f[d-2]]=unknown;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[d-2], cw(i[d-2])));
|
|
}
|
|
if(j ==d-3){
|
|
if ( incircle(d-3,d-2,d-1,0,f,w,i) ) {
|
|
f[d-3]->set_vertex( i[d-3], w[d-1]);
|
|
f[d-2]->set_vertex( i[d-2], w[0]);
|
|
f[d-2]->set_vertex(ccw(i[d-2]), w[d-3]);
|
|
|
|
// edge w[0] w[d-3]
|
|
this->tds().set_adjacency(last, ilast, f[d-2], cw(i[d-2]) );
|
|
type[ cw(i[d-2])][f[d-2]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[d-2], cw(i[d-2])));
|
|
|
|
// edge w[d-3] w[d-2]
|
|
type[i[d-3]][f[d-3]] = boundary;
|
|
// edge w[d-2] w[d-1]
|
|
nn= f[d-2]->neighbor( i[d-2] );
|
|
this->tds().set_adjacency(f[d-3], ccw(i[d-3]), nn, cw(nn->index(w[d-1])) );
|
|
type[ccw(i[d-3])][f[d-3]] = boundary;
|
|
// edge w[d-1] w[0]
|
|
nn= f[d-1]->neighbor( i[d-1] );
|
|
this->tds().set_adjacency(f[d-2], ccw(i[d-2]), nn, cw(nn->index(w[0])) );
|
|
type[ccw(i[d-2])][f[d-2]] = boundary;
|
|
|
|
// edge w[d-3] w[d-1]
|
|
this->tds().set_adjacency(f[d-3], cw(i[d-3]), f[d-2], i[d-2] );
|
|
type[ cw(i[d-3])][f[d-3]] = locally_delaunay;
|
|
type[ i[d-2] ][f[d-2]] = locally_delaunay;
|
|
}else{
|
|
f[d-3]->set_vertex( i[d-3], w[0]);
|
|
f[d-2]->set_vertex( i[d-2], w[0]);
|
|
|
|
// edge w[0] w[d-3]
|
|
this->tds().set_adjacency(last, ilast, f[d-3], cw(i[d-3]) );
|
|
type[ cw(i[d-3])][f[d-3]] = typelast;
|
|
if (typelast != boundary)
|
|
to_be_checked.push_back(Edge( f[d-3], cw(i[d-3])));
|
|
|
|
// edge w[d-3] w[d-2]
|
|
type[i[d-3]][f[d-3]] = boundary;
|
|
// edge w[d-2] w[d-1]
|
|
type[i[d-2]][f[d-2]] = boundary;
|
|
// edge w[d-1] w[0]
|
|
nn= f[d-1]->neighbor( i[d-1] );
|
|
this->tds().set_adjacency(f[d-2], ccw(i[d-2]), nn, cw(nn->index(w[0])) );
|
|
type[ccw(i[d-2])][f[d-2]] = boundary;
|
|
|
|
// edge w[0] w[d-2]
|
|
type[ccw(i[d-3])][f[d-3]] = locally_delaunay;
|
|
type[ cw(i[d-2])][f[d-2]] = locally_delaunay;
|
|
}
|
|
}
|
|
|
|
// clean container
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[d-1]);
|
|
|
|
// flip marked edges to restore Delaunay property
|
|
while( ! to_be_checked.empty() ) {
|
|
Edge e= *to_be_checked.begin(); to_be_checked.pop_front();
|
|
int k = e.second;
|
|
Face_handle ff = e.first;
|
|
// check edge k of face ff
|
|
if( type[k][ff] == unknown ) {
|
|
Face_handle fopp = ff->neighbor(k);
|
|
int kk=fopp->index( ff );
|
|
Vertex_handle vopp = fopp->vertex( kk ) ;
|
|
Vertex_handle vff = ff->vertex( k ) ;
|
|
// std::cout<<"try "<<vff->point()<<";"<<vopp->point()<<std::endl;
|
|
if ( (this->is_infinite(vff))
|
|
? (test_conflict( vopp->point(), ff) )
|
|
: (test_conflict( vff->point(), fopp) )
|
|
) {
|
|
// make the flip
|
|
// do not use flip( ff, k) since faces can be neighbor twice
|
|
// through the boundary
|
|
ff->set_vertex ( cw(k) , vopp);
|
|
fopp->set_vertex ( cw(kk), vff );
|
|
|
|
nn= ff->neighbor( ccw(k)) ;
|
|
this->tds().set_adjacency(fopp, kk , nn, cw(nn->index(vff)) );
|
|
if (type[ccw(k)][ff]!=boundary) {
|
|
type[kk][fopp] = unknown;
|
|
to_be_checked.push_back(Edge(fopp,kk));
|
|
} else type[kk][fopp] = boundary;
|
|
|
|
nn = fopp->neighbor( ccw(kk)) ;
|
|
this->tds().set_adjacency(ff, k, nn, cw(nn->index(vopp)) );
|
|
if (type[ccw(kk)][fopp]!=boundary) {
|
|
type[k][ff] = unknown;
|
|
to_be_checked.push_back(Edge(ff,k));
|
|
} else type[k][ff] = boundary;
|
|
|
|
this->tds().set_adjacency(fopp, ccw(kk), ff, ccw(k) );
|
|
type[ccw(k )][ff] = locally_delaunay;
|
|
type[ccw(kk)][fopp] = locally_delaunay;
|
|
|
|
if ( type[cw(k )][ff] != boundary ) {
|
|
type[cw(k )][ff] = unknown;
|
|
to_be_checked.push_back(Edge ( ff , cw(k )));
|
|
}
|
|
if ( type[cw(kk)][fopp] != boundary) {
|
|
type[cw(kk)][fopp] = unknown ;
|
|
to_be_checked.push_back(Edge ( fopp, cw(kk)));
|
|
}
|
|
}else{ type[k][ff] = type[kk][fopp] = locally_delaunay; }
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree3(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{
|
|
// removing a degree 3 vertex
|
|
// only w[0] can be infinite
|
|
|
|
// modify the triangulation
|
|
Face_handle nn= f[1]->neighbor( i[1] );
|
|
this->tds().set_adjacency(f[0], ccw(i[0]) , nn , nn->index(f[1]) );
|
|
nn= f[2]->neighbor( i[2] );
|
|
this->tds().set_adjacency(f[0], cw(i[0]) , nn , nn->index(f[2]) );
|
|
f[0]->set_vertex ( i[0] , f[1]->vertex( cw(i[1]) ) );
|
|
|
|
// clean container
|
|
this->tds().delete_face(f[1]);
|
|
this->tds().delete_face(f[2]);
|
|
|
|
return;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree4(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i )
|
|
{
|
|
// removing a degree 4 vertex
|
|
// only w[0] can be infinite
|
|
|
|
Face_handle nn;
|
|
// modify f[0] f[1] for incircle test
|
|
f[0]->set_vertex( i[0], w[3] ); //w0 w1 w3
|
|
|
|
if ( !test_conflict( w[2]->point(), f[0]) ) {
|
|
// diagonal 1 3
|
|
f[1]->set_vertex( i[1], w[3] ); //w1 w2 w3
|
|
nn = f[3]->neighbor( i[3] );
|
|
this->tds().set_adjacency(f[0], cw(i[0]) , nn , nn->index(f[3]) );
|
|
nn = f[2]->neighbor( i[2] );
|
|
this->tds().set_adjacency(f[1], ccw(i[1]) , nn , nn->index(f[2]) );
|
|
// clean container
|
|
this->tds().delete_face(f[2]);
|
|
this->tds().delete_face(f[3]);
|
|
}else{
|
|
// diagonal 0 2
|
|
f[0]->set_vertex( i[0], w[2]); //w0 w1 w2
|
|
f[3]->set_vertex( i[3], w[2]); //w3 w0 w2
|
|
nn = f[1]->neighbor( i[1] );
|
|
this->tds().set_adjacency(f[0], ccw(i[0]) , nn , nn->index(f[1]) );
|
|
nn = f[2]->neighbor( i[2] );
|
|
this->tds().set_adjacency(f[3], cw(i[3]) , nn , nn->index(f[2]) );
|
|
// clean container
|
|
this->tds().delete_face(f[1]);
|
|
this->tds().delete_face(f[2]);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree5(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i )
|
|
{
|
|
// removing a degree 5 vertex
|
|
// only w[0] can be infinite
|
|
|
|
if (incircle(3,0,1,2,f,w,i)) {
|
|
if (incircle(4,0,1,3,f,w,i)) {
|
|
if (incircle(4,1,2,3,f,w,i)) {
|
|
// star from 4
|
|
remove_degree5_star(v,f[4],f[0],f[1],f[2],f[3],
|
|
w[4],w[0],w[1],w[2],w[3],
|
|
i[4],i[0],i[1],i[2],i[3]);
|
|
}else{
|
|
//star from 1
|
|
remove_degree5_star(v,f[1],f[2],f[3],f[4],f[0],
|
|
w[1],w[2],w[3],w[4],w[0],
|
|
i[1],i[2],i[3],i[4],i[0]);
|
|
|
|
|
|
}
|
|
}else{
|
|
// star from 3
|
|
remove_degree5_star(v,f[3],f[4],f[0],f[1],f[2],
|
|
w[3],w[4],w[0],w[1],w[2],
|
|
i[3],i[4],i[0],i[1],i[2]);
|
|
}
|
|
} else {
|
|
if (incircle(4,2,3,0,f,w,i)){
|
|
if (incircle(4,0,1,2,f,w,i)){
|
|
// star from 4
|
|
remove_degree5_star(v,f[4],f[0],f[1],f[2],f[3],
|
|
w[4],w[0],w[1],w[2],w[3],
|
|
i[4],i[0],i[1],i[2],i[3]);
|
|
}else{
|
|
//star from 2
|
|
remove_degree5_star(v,f[2],f[3],f[4],f[0],f[1],
|
|
w[2],w[3],w[4],w[0],w[1],
|
|
i[2],i[3],i[4],i[0],i[1]);
|
|
}
|
|
}else{
|
|
// star from 0
|
|
remove_degree5_star(v,f[0],f[1],f[2],f[3],f[4],
|
|
w[0],w[1],w[2],w[3],w[4],
|
|
i[0],i[1],i[2],i[3],i[4]);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::remove_degree5_star
|
|
(
|
|
Vertex_handle &v,
|
|
Face_handle & f0, Face_handle & f1, Face_handle & f2,
|
|
Face_handle & f3, Face_handle & f4,
|
|
Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2,
|
|
Vertex_handle &v3, Vertex_handle &v4,
|
|
int i0, int i1, int i2, int i3, int i4 )
|
|
{ // removing a degree 5 vertex, staring from v0
|
|
Face_handle nn;
|
|
f1->set_vertex( i1, v0) ; // f1 = v1v2v0
|
|
f2->set_vertex( i2, v0) ; // f2 = v2v3v0
|
|
f3->set_vertex( i3, v0) ; // f3 = v3v4v0
|
|
nn = f0->neighbor( i0 );
|
|
this->tds().set_adjacency(f1, cw(i1) , nn , nn->index(f0) );
|
|
nn = f4->neighbor( i4 );
|
|
this->tds().set_adjacency(f3, ccw(i3) , nn , nn->index(f4) );
|
|
this->tds().delete_face(f0);
|
|
this->tds().delete_face(f4);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree6(Vertex_handle v, std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{
|
|
// removing a degree 6 vertex
|
|
// only w[0] can be infinite
|
|
|
|
if(incircle(1,2,3,0,f,w,i)){
|
|
if(incircle(4,2,3,5,f,w,i)){
|
|
if(incircle(1,2,3,4,f,w,i)){
|
|
if(incircle(4,0,1,3,f,w,i)){
|
|
if(incircle(5,0,1,4,f,w,i)){
|
|
remove_degree6_star(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}else{
|
|
remove_degree6_N(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}}else{
|
|
remove_degree6_antiN(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}}else{
|
|
if(incircle(5,1,2,4,f,w,i)){
|
|
remove_degree6_N(v,f[2],f[3],f[4],f[5],f[0],f[1],
|
|
w[2],w[3],w[4],w[5],w[0],w[1],
|
|
i[2],i[3],i[4],i[5],i[0],i[1]);
|
|
}else{
|
|
if(incircle(5,0,1,4,f,w,i)){
|
|
remove_degree6_antiN(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}else{
|
|
remove_degree6_star(v,f[4],f[5],f[0],f[1],f[2],f[3],
|
|
w[4],w[5],w[0],w[1],w[2],w[3],
|
|
i[4],i[5],i[0],i[1],i[2],i[3]);
|
|
}}}}else{
|
|
if(incircle(1,2,3,5,f,w,i)){
|
|
if(incircle(1,3,4,5,f,w,i)){
|
|
if(incircle(4,0,1,3,f,w,i)){
|
|
if(incircle(5,0,1,4,f,w,i)){
|
|
remove_degree6_star(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}else{
|
|
remove_degree6_N(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}}else{
|
|
remove_degree6_antiN(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}}else{
|
|
if(incircle(5,0,1,3,f,w,i)){
|
|
remove_degree6_diamond(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}else{
|
|
if(incircle(4,5,0,3,f,w,i)){
|
|
remove_degree6_antiN(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}else{
|
|
remove_degree6_star(v,f[3],f[4],f[5],f[0],f[1],f[2],
|
|
w[3],w[4],w[5],w[0],w[1],w[2],
|
|
i[3],i[4],i[5],i[0],i[1],i[2]);
|
|
}}}}else{
|
|
remove_degree6_star(v,f[5],f[0],f[1],f[2],f[3],f[4],
|
|
w[5],w[0],w[1],w[2],w[3],w[4],
|
|
i[5],i[0],i[1],i[2],i[3],i[4]);
|
|
}}}else{
|
|
if(incircle(4,2,3,5,f,w,i)){
|
|
if(incircle(4,2,3,0,f,w,i)){
|
|
if(incircle(4,0,1,2,f,w,i)){
|
|
if(incircle(4,1,2,5,f,w,i)){
|
|
if(incircle(4,0,1,5,f,w,i)){
|
|
remove_degree6_star(v,f[4],f[5],f[0],f[1],f[2],f[3],
|
|
w[4],w[5],w[0],w[1],w[2],w[3],
|
|
i[4],i[5],i[0],i[1],i[2],i[3]);
|
|
}else{
|
|
remove_degree6_antiN(v,f[1],f[2],f[3],f[4],f[5],f[0],
|
|
w[1],w[2],w[3],w[4],w[5],w[0],
|
|
i[1],i[2],i[3],i[4],i[5],i[0]);
|
|
}}else{
|
|
remove_degree6_N(v,f[2],f[3],f[4],f[5],f[0],f[1],
|
|
w[2],w[3],w[4],w[5],w[0],w[1],
|
|
i[2],i[3],i[4],i[5],i[0],i[1]);
|
|
}}else{
|
|
if(incircle(4,5,0,2,f,w,i)){
|
|
remove_degree6_diamond(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}else{
|
|
if(incircle(5,0,1,2,f,w,i)){
|
|
remove_degree6_N(v,f[2],f[3],f[4],f[5],f[0],f[1],
|
|
w[2],w[3],w[4],w[5],w[0],w[1],
|
|
i[2],i[3],i[4],i[5],i[0],i[1]);
|
|
}else{
|
|
remove_degree6_star(v,f[2],f[3],f[4],f[5],f[0],f[1],
|
|
w[2],w[3],w[4],w[5],w[0],w[1],
|
|
i[2],i[3],i[4],i[5],i[0],i[1]);
|
|
}}}}else{
|
|
remove_degree6_star(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}}else{
|
|
if(incircle(5,2,3,0,f,w,i)){
|
|
if(incircle(5,0,1,2,f,w,i)){
|
|
remove_degree6_star(v,f[5],f[0],f[1],f[2],f[3],f[4],
|
|
w[5],w[0],w[1],w[2],w[3],w[4],
|
|
i[5],i[0],i[1],i[2],i[3],i[4]);
|
|
}else{
|
|
remove_degree6_antiN(v,f[2],f[3],f[4],f[5],f[0],f[1],
|
|
w[2],w[3],w[4],w[5],w[0],w[1],
|
|
i[2],i[3],i[4],i[5],i[0],i[1]);
|
|
}}else{
|
|
if(incircle(4,5,0,3,f,w,i)){
|
|
remove_degree6_star(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}else{
|
|
remove_degree6_N(v,f[0],f[1],f[2],f[3],f[4],f[5],
|
|
w[0],w[1],w[2],w[3],w[4],w[5],
|
|
i[0],i[1],i[2],i[3],i[4],i[5]);
|
|
}}}}
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::remove_degree6_star
|
|
(
|
|
Vertex_handle &v,
|
|
Face_handle & f0, Face_handle & f1, Face_handle & f2,
|
|
Face_handle & f3, Face_handle & f4, Face_handle & f5,
|
|
Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2,
|
|
Vertex_handle &v3, Vertex_handle &v4, Vertex_handle &v5,
|
|
int i0, int i1, int i2, int i3, int i4, int i5 )
|
|
{ // removing a degree 6 vertex, staring from v0
|
|
Face_handle nn;
|
|
f1->set_vertex( i1, v0) ; // f1 = v1v2v0
|
|
f2->set_vertex( i2, v0) ; // f2 = v2v3v0
|
|
f3->set_vertex( i3, v0) ; // f3 = v3v4v0
|
|
f4->set_vertex( i4, v0) ; // f4 = v4v5v0
|
|
nn = f0->neighbor( i0 );
|
|
this->tds().set_adjacency(f1, cw(i1), nn, nn->index(f0));
|
|
nn = f5->neighbor( i5 );
|
|
this->tds().set_adjacency(f4, ccw(i4), nn, nn->index(f5));
|
|
this->tds().delete_face(f0);
|
|
this->tds().delete_face(f5);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::remove_degree6_N
|
|
(
|
|
Vertex_handle &v,
|
|
Face_handle & f0, Face_handle & f1, Face_handle & f2,
|
|
Face_handle & f3, Face_handle & f4, Face_handle & f5,
|
|
Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2,
|
|
Vertex_handle &v3, Vertex_handle &v4, Vertex_handle &v5,
|
|
int i0, int i1, int i2, int i3, int i4, int i5 )
|
|
{ // removing a degree 6 vertex, N configuration with diagonal v0v3
|
|
Face_handle nn;
|
|
f1->set_vertex( i1, v0) ; // f1 = v1v2v0
|
|
f2->set_vertex( i2, v0) ; // f2 = v2v3v0
|
|
f4->set_vertex( i4, v3) ; // f4 = v4v5v3
|
|
f5->set_vertex( i5, v3) ; // f5 = v5v0v3
|
|
nn = f0->neighbor( i0 );
|
|
this->tds().set_adjacency(f1, cw(i1) , nn , nn->index(f0) );
|
|
nn = f3->neighbor( i3 );
|
|
this->tds().set_adjacency(f4, cw(i4) , nn, nn->index(f3) );
|
|
this->tds().set_adjacency(f2, ccw(i2) , f5 , ccw(i5) );
|
|
this->tds().delete_face(f0);
|
|
this->tds().delete_face(f3);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::remove_degree6_antiN
|
|
(
|
|
Vertex_handle &v,
|
|
Face_handle & f0, Face_handle & f1, Face_handle & f2,
|
|
Face_handle & f3, Face_handle & f4, Face_handle & f5,
|
|
Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2,
|
|
Vertex_handle &v3, Vertex_handle &v4, Vertex_handle &v5,
|
|
int i0, int i1, int i2, int i3, int i4, int i5 )
|
|
{ // removing a degree 6 vertex, antiN configuration with diagonal v0v3
|
|
Face_handle nn;
|
|
f0->set_vertex( i0, v3) ; // f0 = v0v1v3
|
|
f1->set_vertex( i1, v3) ; // f1 = v1v2v3
|
|
f3->set_vertex( i3, v0) ; // f3 = v3v4v0
|
|
f4->set_vertex( i4, v0) ; // f4 = v4v5v0
|
|
nn = f2->neighbor( i2 );
|
|
this->tds().set_adjacency(f1, ccw(i1) , nn , nn->index(f2) );
|
|
nn = f5->neighbor( i5 );
|
|
this->tds().set_adjacency(f4, ccw(i4) , nn , nn->index(f5) );
|
|
this->tds().set_adjacency(f0, cw(i0) , f3, cw(i3) );
|
|
this->tds().delete_face(f2);
|
|
this->tds().delete_face(f5);
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::remove_degree6_diamond
|
|
(
|
|
Vertex_handle &v,
|
|
Face_handle & f0, Face_handle & f1, Face_handle & f2,
|
|
Face_handle & f3, Face_handle & f4, Face_handle & f5,
|
|
Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2,
|
|
Vertex_handle &v3, Vertex_handle &v4, Vertex_handle &v5,
|
|
int i0, int i1, int i2, int i3, int i4, int i5 )
|
|
{ // removing a degree 6 vertex, with chords v0v2 v2v4 v4v0
|
|
Face_handle nn;
|
|
f0->set_vertex( i0, v2) ; // f0 = v0v1v2
|
|
f2->set_vertex( i2, v4) ; // f2 = v2v3v4
|
|
f4->set_vertex( i4, v0) ; // f4 = v4v5v0
|
|
f1->set_vertex( i1, v4) ;
|
|
f1->set_vertex( ccw(i1), v0) ; // f1 = v0v2v4
|
|
nn = f1->neighbor( i1 );
|
|
this->tds().set_adjacency(f0, ccw(i0) , nn , nn->index(f1) );
|
|
nn = f3->neighbor( i3 );
|
|
this->tds().set_adjacency(f2, ccw(i2) , nn , nn->index(f3) );
|
|
nn = f5->neighbor( i5 );
|
|
this->tds().set_adjacency(f4, ccw(i4) , nn , nn->index(f5) );
|
|
this->tds().set_adjacency(f0, cw(i0) , f1 , i1 );
|
|
this->tds().set_adjacency(f4, cw(i4) , f1 , cw(i1) );
|
|
|
|
this->tds().delete_face(f3);
|
|
this->tds().delete_face(f5);
|
|
}
|
|
|
|
|
|
template < class Gt, class Tds >
|
|
void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7(Vertex_handle v,std::vector<Face_handle> &f,
|
|
std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{
|
|
// removing a degree 7 vertex
|
|
// only w[0] can be infinite
|
|
|
|
if (incircle(2,0,1,3,f,w,i)) { // sweeping from above
|
|
if (incircle(2,3,4,0,f,w,i)) {
|
|
if (incircle(5,3,4,6,f,w,i)) {
|
|
if (incircle(5,3,4,2,f,w,i)) {
|
|
if (incircle(6,2,3,5,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 6 ,f,w,i);
|
|
}}else{
|
|
if (incircle(5,0,1,2,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(2,5,6,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightdelta(v, 5 ,f,w,i);
|
|
}}}}else{
|
|
if (incircle(4,0,1,2,f,w,i)) {
|
|
if (incircle(5,1,2,4,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(5,0,1,4,f,w,i)) {
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(2,4,5,0,f,w,i)) {
|
|
if (incircle(5,0,1,2,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(2,5,6,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftdelta(v, 2 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_rightdelta(v, 0 ,f,w,i);
|
|
}}}}else{
|
|
if (incircle(6,3,4,2,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_star(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 6 ,f,w,i);
|
|
}}else{
|
|
if (incircle(4,0,1,2,f,w,i)) {
|
|
if (incircle(2,4,5,6,f,w,i)) {
|
|
if (incircle(5,1,2,4,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(5,0,1,4,f,w,i)) {
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}} else{
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}}} else {
|
|
if (incircle(6,1,2,4,f,w,i)) {
|
|
remove_degree7_leftdelta(v, 6 ,f,w,i);
|
|
}else{
|
|
if (incircle(1,4,5,6,f,w,i)) {
|
|
if (incircle(1,4,5,0,f,w,i)) {
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}} else {
|
|
if (incircle(6,0,1,4,f,w,i)) {
|
|
remove_degree7_rightdelta(v, 4 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,4,5,0,f,w,i)) {
|
|
remove_degree7_star(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}}}}}}else{
|
|
if (incircle(2,4,5,6,f,w,i)) {
|
|
if (incircle(2,4,5,0,f,w,i)) {
|
|
if (incircle(5,0,1,2,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(2,5,6,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftdelta(v, 2 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_rightdelta(v, 0 ,f,w,i);
|
|
}}else{
|
|
if (incircle(2,6,0,4,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftdelta(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightdelta(v, 2 ,f,w,i);
|
|
}}else{
|
|
if (incircle(6,4,5,0,f,w,i)) {
|
|
remove_degree7_leftdelta(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightdelta(v, 0 ,f,w,i);
|
|
}}}}}}} else{
|
|
if (incircle(5,3,4,6,f,w,i)) {
|
|
if (incircle(5,3,4,0,f,w,i)) {
|
|
if (incircle(5,2,3,0,f,w,i)) {
|
|
if (incircle(6,2,3,5,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 6 ,f,w,i);
|
|
}}else
|
|
if (incircle(5,0,1,2,f,w,i)) {
|
|
if (incircle(6,1,2,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}else{
|
|
if (incircle(6,0,1,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(2,5,6,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightdelta(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(3,5,6,0,f,w,i)) {
|
|
if (incircle(6,2,3,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 6 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftfan(v, 3 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftdelta(v, 0 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_star(v, 0 ,f,w,i);
|
|
}}else{
|
|
if (incircle(6,3,4,0,f,w,i)) {
|
|
if (incircle(6,2,3,0,f,w,i)) {
|
|
if (incircle(6,0,1,2,f,w,i)) {
|
|
remove_degree7_star(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 6 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_zigzag(v, 3 ,f,w,i);
|
|
}}else{
|
|
if (incircle(6,4,5,0,f,w,i)) {
|
|
remove_degree7_leftfan(v, 0 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 0 ,f,w,i);
|
|
}}}}}else{ //sweeping from below
|
|
if (incircle(1,6,0,3,f,w,i)) {
|
|
if (incircle(5,6,0,4,f,w,i)) {
|
|
if (incircle(5,6,0,1,f,w,i)) {
|
|
if (incircle(4,0,1,5,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 4 ,f,w,i);
|
|
}}else{
|
|
if (incircle(5,2,3,1,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(1,4,5,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftdelta(v, 5 ,f,w,i);
|
|
}}}}else{
|
|
if (incircle(6,2,3,1,f,w,i)) {
|
|
if (incircle(5,1,2,6,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(5,2,3,6,f,w,i)) {
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(1,5,6,3,f,w,i)) {
|
|
if (incircle(5,2,3,1,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(1,4,5,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightdelta(v, 1 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_leftdelta(v, 3 ,f,w,i);
|
|
}}}}else{
|
|
if (incircle(4,6,0,1,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_star(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 4 ,f,w,i);
|
|
}}else{
|
|
if (incircle(6,2,3,1,f,w,i)) {
|
|
if (incircle(1,5,6,4,f,w,i)) {
|
|
if (incircle(5,1,2,6,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(5,2,3,6,f,w,i)) {
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}} else{
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}}} else {
|
|
if (incircle(4,1,2,6,f,w,i)) {
|
|
remove_degree7_rightdelta(v, 4 ,f,w,i);
|
|
}else{
|
|
if (incircle(2,5,6,4,f,w,i)) {
|
|
if (incircle(2,5,6,3,f,w,i)) {
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 2 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 2 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}} else {
|
|
if (incircle(4,2,3,6,f,w,i)) {
|
|
remove_degree7_leftdelta(v, 6 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,5,6,3,f,w,i)) {
|
|
remove_degree7_star(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 6 ,f,w,i);
|
|
}}}}}}else{
|
|
if (incircle(1,5,6,4,f,w,i)) {
|
|
if (incircle(1,5,6,3,f,w,i)) {
|
|
if (incircle(5,2,3,1,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_rightfan(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(1,4,5,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightfan(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightdelta(v, 1 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_leftdelta(v, 3 ,f,w,i);
|
|
}}else{
|
|
if (incircle(1,3,4,6,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightdelta(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftdelta(v, 1 ,f,w,i);
|
|
}}else{
|
|
if (incircle(4,5,6,3,f,w,i)) {
|
|
remove_degree7_rightdelta(v, 6 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftdelta(v, 3 ,f,w,i);
|
|
}}}}}}} else{
|
|
if (incircle(5,6,0,4,f,w,i)) {
|
|
if (incircle(5,6,0,3,f,w,i)) {
|
|
if (incircle(5,0,1,3,f,w,i)) {
|
|
if (incircle(4,0,1,5,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 4 ,f,w,i);
|
|
}}else
|
|
if (incircle(5,2,3,1,f,w,i)) {
|
|
if (incircle(4,1,2,5,f,w,i)) {
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}else{
|
|
if (incircle(4,2,3,5,f,w,i)) {
|
|
remove_degree7_leftfan(v, 5 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (incircle(1,4,5,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_zigzag(v, 1 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 1 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_leftdelta(v, 5 ,f,w,i);
|
|
}}}else{
|
|
if (! incircle(3,4,5,0,f,w,i)) {
|
|
if (incircle(4,0,1,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_rightfan(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_zigzag(v, 4 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightfan(v, 0 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_rightdelta(v, 3 ,f,w,i);
|
|
}}}else{
|
|
remove_degree7_star(v, 3 ,f,w,i);
|
|
}}else{
|
|
if (incircle(4,6,0,3,f,w,i)) {
|
|
if (incircle(4,0,1,3,f,w,i)) {
|
|
if (incircle(4,2,3,1,f,w,i)) {
|
|
remove_degree7_star(v, 4 ,f,w,i);
|
|
}else{
|
|
remove_degree7_leftfan(v, 4 ,f,w,i);
|
|
}}else{
|
|
remove_degree7_zigzag(v, 0 ,f,w,i);
|
|
}}else{
|
|
if (incircle(4,5,6,3,f,w,i)) {
|
|
remove_degree7_rightfan(v, 3 ,f,w,i);
|
|
}else{
|
|
remove_degree7_star(v, 3 ,f,w,i);
|
|
}}}}}
|
|
}
|
|
|
|
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
rotate7(int j, std::vector<Vertex_handle> &w,
|
|
std::vector<Face_handle> &f, std::vector<int> &i)
|
|
{
|
|
if (j==0) return;
|
|
Face_handle ff=f[0];
|
|
int ii=i[0],k=0,kk=(6*j)%7;
|
|
Vertex_handle ww=w[0];
|
|
for (int jj=0; k!=kk; jj=k) { // 7 is prime
|
|
k=(jj+j)%7;
|
|
w[jj]=w[k]; f[jj]=f[k]; i[jj]=i[k];
|
|
}
|
|
w[kk]=ww;f[kk]=ff;i[kk]=ii;
|
|
}
|
|
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_star (Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f, std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, staring from w[j]
|
|
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[1]->set_vertex( i[1], w[0]) ; // f1 = w1w2w0
|
|
f[2]->set_vertex( i[2], w[0]) ; // f2 = w2w3w0
|
|
f[3]->set_vertex( i[3], w[0]) ; // f3 = w3w4w0
|
|
f[4]->set_vertex( i[4], w[0]) ; // f4 = w4w5w0
|
|
f[5]->set_vertex( i[5], w[0]) ; // f5 = w5w6w0
|
|
|
|
nn = f[0]->neighbor( i[0] );
|
|
this->tds().set_adjacency(f[1], cw(i[1]) , nn , nn->index(f[0]) );
|
|
nn = f[6]->neighbor( i[6] );
|
|
this->tds().set_adjacency(f[5], ccw(i[5]) , nn , nn->index(f[6]) );
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[6]);
|
|
}
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_zigzag (Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f,std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, zigzag, w[j] = middle point
|
|
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[1]->set_vertex( i[1] , w[3]) ; // f1 = w1w2w3
|
|
f[2]->set_vertex(ccw(i[2]), w[1]) ;
|
|
f[2]->set_vertex( i[2] , w[0]) ; // f2 = w1w3w0
|
|
f[3]->set_vertex( i[3] , w[0]) ; // f3 = w3w4w0
|
|
f[4]->set_vertex( cw(i[4]), w[6]) ;
|
|
f[4]->set_vertex( i[4] , w[0]) ; // f4 = w4w6w0
|
|
f[5]->set_vertex( i[5] , w[4]) ; // f5 = w5w6w4
|
|
|
|
nn = f[2]->neighbor( i[2] );
|
|
this->tds().set_adjacency(f[1], ccw(i[1]) , nn, nn->index(f[2]) );
|
|
nn = f[0]->neighbor( i[0] );
|
|
this->tds().set_adjacency(f[2], cw(i[2]) , nn , nn->index(f[0]) );
|
|
nn = f[6]->neighbor( i[6] );
|
|
this->tds().set_adjacency(f[4], ccw(i[4]) , nn , nn->index(f[6]) );
|
|
nn = f[4]->neighbor( i[4] );
|
|
this->tds().set_adjacency(f[5], cw(i[5]) , nn , nn->index(f[4]) );
|
|
this->tds().set_adjacency(f[1], cw(i[1]) , f[2] , i[2] );
|
|
this->tds().set_adjacency(f[4], i[4] , f[5] , ccw(i[5]) );
|
|
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[6]);
|
|
}
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_leftdelta(Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f,std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, left delta from w[j]
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[1]->set_vertex( i[1] , w[0]) ; // f1 = w1w2w0
|
|
f[2]->set_vertex( i[2] , w[0]) ; // f2 = w2w3w0
|
|
f[3]->set_vertex( cw(i[3]), w[5]) ;
|
|
f[3]->set_vertex( i[3] , w[0]) ; // f3 = w3w5w0
|
|
f[4]->set_vertex( i[4] , w[3]) ; // f4 = w4w5w3
|
|
f[5]->set_vertex( i[5] , w[0]) ; // f5 = w5w6w0
|
|
|
|
nn = f[0]->neighbor( i[0] );
|
|
this->tds().set_adjacency(f[1], cw(i[1]) , nn , nn->index(f[0]) );
|
|
nn = f[3]->neighbor( i[3] );
|
|
this->tds().set_adjacency(f[4], cw(i[4]) , nn , nn->index(f[3]) );
|
|
nn = f[6]->neighbor( i[6] );
|
|
this->tds().set_adjacency(f[5], ccw(i[5]) , nn , nn->index(f[6]) );
|
|
this->tds().set_adjacency(f[3], i[3] , f[4] , ccw(i[4]) );
|
|
this->tds().set_adjacency(f[3], ccw(i[3]) , f[5] , cw(i[5]) );
|
|
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[6]);
|
|
}
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_rightdelta(Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f,std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, right delta from w[j]
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[1]->set_vertex( i[1] , w[0]) ; // f1 = w1w2w0
|
|
f[2]->set_vertex( i[2] , w[4]) ; // f2 = w2w3w4
|
|
f[3]->set_vertex(ccw(i[3]), w[2]) ;
|
|
f[3]->set_vertex( i[3] , w[0]) ; // f3 = w2w4w0
|
|
f[4]->set_vertex( i[4] , w[0]) ; // f4 = w4w5w0
|
|
f[5]->set_vertex( i[5] , w[0]) ; // f5 = w5w6w0
|
|
|
|
nn = f[0]->neighbor( i[0] );
|
|
this->tds().set_adjacency(f[1], cw(i[1]) , nn , nn->index(f[0]) );
|
|
nn = f[3]->neighbor( i[3] );
|
|
this->tds().set_adjacency(f[2], ccw(i[2]) , nn, nn->index(f[3]) );
|
|
nn = f[6]->neighbor( i[6] );
|
|
this->tds().set_adjacency(f[5], ccw(i[5]) , nn , nn->index(f[6]) );
|
|
this->tds().set_adjacency(f[1], ccw(i[1]) , f[3], cw(i[3]) );
|
|
this->tds().set_adjacency(f[3], i[3] , f[2], cw(i[2]) );
|
|
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[6]);
|
|
}
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_leftfan(Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f,std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, left fan from w[j]
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[1]->set_vertex( i[1] , w[0]) ; // f1 = w1w2w0
|
|
f[2]->set_vertex( i[2] , w[0]) ; // f2 = w2w3w0
|
|
f[3]->set_vertex( i[3] , w[0]) ; // f3 = w3w4w0
|
|
f[4]->set_vertex( i[4] , w[6]) ; // f4 = w4w5w6
|
|
f[6]->set_vertex( i[6] , w[4]) ; // f6 = w6w0w4
|
|
|
|
nn = f[0]->neighbor( i[0] );
|
|
this->tds().set_adjacency(f[1], cw(i[1]) , nn, nn->index(f[0]) );
|
|
nn = f[5]->neighbor( i[5] );
|
|
this->tds().set_adjacency(f[4], ccw(i[4]) , nn, nn->index(f[5]) );
|
|
this->tds().set_adjacency(f[3], ccw(i[3]) , f[6], ccw(i[6]) );
|
|
this->tds().set_adjacency(f[6], cw(i[6]) , f[4], cw(i[4]) );
|
|
|
|
this->tds().delete_face(f[0]);
|
|
this->tds().delete_face(f[5]);
|
|
}
|
|
template < class Gt, class Tds >
|
|
inline void
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
remove_degree7_rightfan(Vertex_handle &v, int j,
|
|
std::vector<Face_handle> &f,std::vector<Vertex_handle> &w, std::vector<int> &i)
|
|
{ // removing a degree 7 vertex, right fan from w[j]
|
|
|
|
rotate7(j,w,f,i);
|
|
|
|
Face_handle nn;
|
|
f[0]->set_vertex( i[0] , w[3]) ; // f0 = w0w1w3
|
|
f[2]->set_vertex( i[2] , w[1]) ; // f2 = w2w3w1
|
|
f[3]->set_vertex( i[3] , w[0]) ; // f3 = w3w4w0
|
|
f[4]->set_vertex( i[4] , w[0]) ; // f4 = w4w5w0
|
|
f[5]->set_vertex( i[5] , w[0]) ; // f5 = w5w6w0
|
|
|
|
nn = f[1]->neighbor( i[1] );
|
|
this->tds().set_adjacency(f[2], cw(i[2]) , nn, nn->index(f[1]) );
|
|
nn = f[6]->neighbor( i[6] );
|
|
this->tds().set_adjacency(f[5], ccw(i[5]) , nn, nn->index(f[6]) );
|
|
this->tds().set_adjacency(f[2], ccw(i[2]) , f[0], ccw(i[0]) );
|
|
this->tds().set_adjacency(f[0], cw(i[0]) , f[3] , cw(i[3]) );
|
|
|
|
this->tds().delete_face(f[1]);
|
|
this->tds().delete_face(f[6]);
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// DISPLACEMENT
|
|
|
|
template <class Gt, class Tds >
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
move_if_no_collision(Vertex_handle v, const Point &p) {
|
|
CGAL_triangulation_precondition(!this->is_infinite(v));
|
|
if(v->point() == p) return v;
|
|
const int dim = this->dimension();
|
|
|
|
if(dim == 2) {
|
|
Point ant = v->point();
|
|
v->set_point(p);
|
|
// This option optimizes only when most of the
|
|
// displacements would not break the orientation
|
|
// of the faces.. we will consider this as an a priori,
|
|
// because otherwise it is pointless to just do
|
|
// not rebuild from scratch.
|
|
if(this->well_oriented(v)) {
|
|
restore_edges(v);
|
|
return v;
|
|
}
|
|
v->set_point(ant);
|
|
}
|
|
|
|
Locate_type lt;
|
|
int li;
|
|
Vertex_handle inserted;
|
|
Face_handle loc = this->locate(p, lt, li, v->face());
|
|
|
|
if(lt == Triangulation_2<Gt,Tds>::VERTEX) return loc->vertex(li);
|
|
|
|
if(dim == 0) {
|
|
v->point() = p;
|
|
return v;
|
|
}
|
|
|
|
size_type n_vertices = this->tds().number_of_vertices();
|
|
|
|
if((lt == Triangulation::OUTSIDE_AFFINE_HULL) &&
|
|
(dim == 1) && (n_vertices == 3)) {
|
|
v->point() = p;
|
|
return v;
|
|
}
|
|
|
|
if((lt != Triangulation::OUTSIDE_AFFINE_HULL) && (dim == 1)) {
|
|
if(loc->has_vertex(v)) {
|
|
v->point() = p;
|
|
} else {
|
|
inserted = insert(p, lt, loc, li);
|
|
Face_handle f = v->face();
|
|
int i = f->index(v);
|
|
if (i==0) {f = f->neighbor(1);}
|
|
CGAL_triangulation_assertion(f->index(v) == 1);
|
|
Face_handle g= f->neighbor(0);
|
|
f->set_vertex(1, g->vertex(1));
|
|
f->set_neighbor(0,g->neighbor(0));
|
|
g->neighbor(0)->set_neighbor(1,f);
|
|
g->vertex(1)->set_face(f);
|
|
this->delete_face(g);
|
|
Face_handle f_ins = inserted->face();
|
|
i = f_ins->index(inserted);
|
|
if (i==0) {f_ins = f_ins->neighbor(1);}
|
|
CGAL_triangulation_assertion(f_ins->index(inserted) == 1);
|
|
Face_handle g_ins = f_ins->neighbor(0);
|
|
f_ins->set_vertex(1, v);
|
|
g_ins->set_vertex(0, v);
|
|
v->set_point(p);
|
|
v->set_face(inserted->face());
|
|
this->delete_vertex(inserted);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
if((lt != Triangulation::OUTSIDE_AFFINE_HULL) && this->test_dim_down(v)) {
|
|
// verify if p and two static vertices are collinear in this case
|
|
int iinf = 0;
|
|
Face_circulator finf = this->incident_faces(this->infinite_vertex()),
|
|
fdone(finf);
|
|
do {
|
|
if(!finf->has_vertex(v))
|
|
{
|
|
iinf = ~(finf->index(this->infinite_vertex()));
|
|
break;
|
|
}
|
|
} while(++finf != fdone);
|
|
if(this->orientation(finf->vertex(iinf&1)->point(),
|
|
finf->vertex(iinf&2)->point(),
|
|
p) == COLLINEAR)
|
|
{
|
|
v->point() = p;
|
|
this->tds().dim_down(loc, loc->index(v));
|
|
return v;
|
|
}
|
|
}
|
|
|
|
inserted = insert(p, lt, loc, li);
|
|
|
|
{
|
|
int d;
|
|
static int maxd=30;
|
|
static std::vector<Face_handle> f(maxd);
|
|
static std::vector<int> i(maxd);
|
|
static std::vector<Vertex_handle> w(maxd);
|
|
remove_degree_init(v,f,w,i,d,maxd);
|
|
remove_degree_triangulate(v,f,w,i,d);
|
|
}
|
|
|
|
// fixing pointer
|
|
Face_circulator fc = this->incident_faces(inserted), done(fc);
|
|
std::vector<Face_handle> faces_pt;
|
|
faces_pt.reserve(16);
|
|
do { faces_pt.push_back(fc); } while(++fc != done);
|
|
std::size_t ss = faces_pt.size();
|
|
for(std::size_t k=0; k<ss; k++)
|
|
{
|
|
Face_handle f = faces_pt[k];
|
|
int i = f->index(inserted);
|
|
f->set_vertex(i, v);
|
|
}
|
|
|
|
v->set_point(p);
|
|
v->set_face(inserted->face());
|
|
|
|
this->delete_vertex(inserted);
|
|
|
|
return v;
|
|
}
|
|
|
|
template <class Gt, class Tds >
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
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 <class Gt, class Tds >
|
|
bool
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
is_delaunay_after_displacement(Vertex_handle v, const Point &p) const
|
|
{
|
|
CGAL_triangulation_precondition(!this->is_infinite(v));
|
|
CGAL_triangulation_precondition(this->dimension() == 2);
|
|
CGAL_triangulation_precondition(!this->test_dim_down(v));
|
|
if(v->point() == p) return true;
|
|
Point ant = v->point();
|
|
v->set_point(p);
|
|
if(!this->well_oriented(v))
|
|
{
|
|
v->set_point(ant);
|
|
return false;
|
|
}
|
|
std::list<Edge> edges;
|
|
Face_circulator fc = this->incident_faces(v), done(fc);
|
|
int degree = 0;
|
|
do {
|
|
if((++degree) > 3) break;
|
|
} while(++fc != done);
|
|
fc = this->incident_faces(v);
|
|
done = fc;
|
|
if(degree == 3) {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
} while(++fc != done);
|
|
} else {
|
|
do {
|
|
int i = fc->index(v);
|
|
edges.push_back(Edge(fc, i));
|
|
edges.push_back(Edge(fc, this->cw(i)));
|
|
} while(++fc != done);
|
|
}
|
|
while(!edges.empty()) {
|
|
const Edge &e = edges.front();
|
|
Face_handle f = e.first;
|
|
int i = e.second;
|
|
edges.pop_front();
|
|
if(this->is_infinite(f->vertex(i))) continue;
|
|
Face_handle fi = f->neighbor(i);
|
|
Vertex_handle vm = this->_tds.mirror_vertex(f, i);
|
|
if(this->is_infinite(vm)) continue;
|
|
if(this->side_of_oriented_circle(f, vm->point()) == ON_POSITIVE_SIDE) {
|
|
v->set_point(ant);
|
|
return false;
|
|
}
|
|
}
|
|
v->set_point(ant);
|
|
return true;
|
|
}
|
|
|
|
template <class Gt, class Tds >
|
|
template <class OutputItFaces>
|
|
typename Delaunay_triangulation_2<Gt,Tds>::Vertex_handle
|
|
Delaunay_triangulation_2<Gt,Tds>::
|
|
move_if_no_collision_and_give_new_faces(Vertex_handle v,
|
|
const Point &p,
|
|
OutputItFaces oif)
|
|
{
|
|
CGAL_triangulation_precondition(!this->is_infinite(v));
|
|
if(v->point() == p) return v;
|
|
|
|
typedef std::list<Face_handle> Faces_list;
|
|
const int dim = this->dimension();
|
|
|
|
if(dim == 2) {
|
|
Point ant = v->point();
|
|
v->set_point(p);
|
|
// This option optimizes only when most of the
|
|
// displacements would not break the orientation
|
|
// of the faces.. we will consider this as an a priori,
|
|
// because otherwise it is pointless to just do
|
|
// not rebuild from scratch.
|
|
if(well_oriented(v)) {
|
|
std::set<Face_handle> faces_set;
|
|
restore_edges(v, faces_set);
|
|
for(typename std::set<Face_handle>::iterator ib = faces_set.begin(),
|
|
iend = faces_set.end(); ib != iend; ib++) *oif++ = *ib;
|
|
return v;
|
|
}
|
|
v->set_point(ant);
|
|
}
|
|
|
|
Locate_type lt;
|
|
int li;
|
|
Vertex_handle inserted;
|
|
Face_handle loc = this->locate(p, lt, li, v->face());
|
|
|
|
if(lt == Triangulation::VERTEX) return loc->vertex(li);
|
|
|
|
if(dim == 0) {
|
|
v->point() = p;
|
|
return v;
|
|
}
|
|
|
|
size_type n_vertices = this->tds().number_of_vertices();
|
|
|
|
if((lt == Triangulation::OUTSIDE_AFFINE_HULL) &&
|
|
(dim == 1) && (n_vertices == 3)) {
|
|
v->point() = p;
|
|
for(All_faces_iterator afi = this-> all_faces_begin();
|
|
afi != this->all_faces_end();
|
|
afi++) *oif++ = afi;
|
|
return v;
|
|
}
|
|
|
|
if((lt != Triangulation::OUTSIDE_AFFINE_HULL) && (dim == 1)) {
|
|
if(loc->has_vertex(v)) {
|
|
v->point() = p;
|
|
} else {
|
|
inserted = insert(p, lt, loc, li);
|
|
Face_handle f = v->face();
|
|
int i = f->index(v);
|
|
if (i==0) {f = f->neighbor(1);}
|
|
CGAL_triangulation_assertion(f->index(v) == 1);
|
|
Face_handle g= f->neighbor(0);
|
|
f->set_vertex(1, g->vertex(1));
|
|
f->set_neighbor(0,g->neighbor(0));
|
|
g->neighbor(0)->set_neighbor(1,f);
|
|
g->vertex(1)->set_face(f);
|
|
this->delete_face(g);
|
|
*oif++ = f;
|
|
Face_handle f_ins = inserted->face();
|
|
i = f_ins->index(inserted);
|
|
if (i==0) {f_ins = f_ins->neighbor(1);}
|
|
CGAL_triangulation_assertion(f_ins->index(inserted) == 1);
|
|
Face_handle g_ins = f_ins->neighbor(0);
|
|
f_ins->set_vertex(1, v);
|
|
g_ins->set_vertex(0, v);
|
|
v->set_face(inserted->face());
|
|
v->set_point(p);
|
|
this->delete_vertex(inserted);
|
|
}
|
|
*oif++ = v->face();
|
|
if(v->face()->neighbor(0)->has_vertex(v))
|
|
*oif++ = v->face()->neighbor(0);
|
|
if(v->face()->neighbor(1)->has_vertex(v))
|
|
*oif++ = v->face()->neighbor(1);
|
|
return v;
|
|
}
|
|
|
|
if((lt != Triangulation::OUTSIDE_AFFINE_HULL) && this->test_dim_down(v)) {
|
|
// verify if p and two static vertices are collinear in this case
|
|
int iinf;
|
|
Face_circulator finf = incident_faces(this->infinite_vertex()),
|
|
fdone(finf);
|
|
do {
|
|
if(!finf->has_vertex(v))
|
|
{
|
|
iinf = ~(finf->index(this->infinite_vertex()));
|
|
break;
|
|
}
|
|
} while(++finf != fdone);
|
|
if(this->orientation(finf->vertex(iinf&1)->point(),
|
|
finf->vertex(iinf&2)->point(),
|
|
p) == COLLINEAR)
|
|
{
|
|
v->point() = p;
|
|
this->tds().dim_down(loc, loc->index(v));
|
|
for(All_faces_iterator afi = this-> all_faces_begin();
|
|
afi != this->all_faces_end();
|
|
afi++) *oif++ = afi;
|
|
return v;
|
|
}
|
|
}
|
|
|
|
std::set<Face_handle> faces_set;
|
|
inserted = Delaunay_triangulation_2<Gt,Tds>::insert(p, lt, loc, li);
|
|
Face_circulator fc = this->incident_faces(inserted), done(fc);
|
|
do { faces_set.insert(fc); } while(++fc != done);
|
|
|
|
|
|
{
|
|
static int maxd=30;
|
|
static std::vector<Face_handle> f(maxd);
|
|
static std::vector<int> i(maxd);
|
|
static std::vector<Vertex_handle> w(maxd);
|
|
int d;
|
|
remove_degree_init(v,f,w,i,d,maxd);
|
|
remove_degree_triangulate(v,f,w,i,d);
|
|
this->delete_vertex(v);
|
|
Face_circulator fc(v[0]),done;
|
|
do *oif++ = fc++; while (fc!=done);
|
|
}
|
|
|
|
fc = this->incident_faces(inserted), done(fc);
|
|
std::vector<Face_handle> faces_pt;
|
|
faces_pt.reserve(16);
|
|
do { faces_pt.push_back(fc); } while(++fc != done);
|
|
int ss = faces_pt.size();
|
|
for(int k=0; k<ss; k++)
|
|
{
|
|
Face_handle f = faces_pt[k];
|
|
int i = f->index(inserted);
|
|
f->set_vertex(i, v);
|
|
}
|
|
v->set_point(p);
|
|
v->set_face(inserted->face());
|
|
this->delete_vertex(inserted);
|
|
|
|
for(typename std::set<Face_handle>::const_iterator ib = faces_set.begin(),
|
|
iend = faces_set.end(); ib != iend; ib++) *oif++ = *ib;
|
|
|
|
return v;
|
|
}
|
|
|
|
} //namespace CGAL
|
|
|
|
#endif // CGAL_DELAUNAY_TRIANGULATION_2_H
|