dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Delaunay_triangulation_2.h

2473 lines
84 KiB
C++

// Copyright (c) 1997 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h $
// $Id: Delaunay_triangulation_2.h d1a323c 2020-03-26T19:24:14+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// 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/license/Triangulation_2.h>
#include <CGAL/Triangulation_2.h>
#include <CGAL/iterator.h>
#include <CGAL/Object.h>
#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
#include <CGAL/Spatial_sort_traits_adapter_2.h>
#include <CGAL/tss.h>
#include <boost/mpl/and.hpp>
#endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
namespace CGAL {
template < class Gt,
class Tds = Triangulation_data_structure_2 <
Triangulation_vertex_base_2<Gt>,
Triangulation_face_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;
//Tag to distinguish Delaunay from regular triangulations
typedef Tag_false Weighted_tag;
// Tag to distinguish periodic triangulations from others
typedef Tag_false Periodic_tag;
#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()); }
Delaunay_triangulation_2(Delaunay_triangulation_2&&) = default;
Delaunay_triangulation_2& operator=(const Delaunay_triangulation_2&) = default;
Delaunay_triangulation_2& operator=(Delaunay_triangulation_2&&) = default;
~Delaunay_triangulation_2() = default;
template <class InputIterator>
Delaunay_triangulation_2(InputIterator first, InputIterator last,
const Gt& gt = Gt())
: Triangulation_2<Gt,Tds>(gt)
{
insert(first,last);
}
// 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:
#ifndef CGAL_DT2_USE_RECURSIVE_PROPAGATING_FLIP
void non_recursive_propagating_flip(Face_handle f,int i);
void propagating_flip(const Face_handle& f, int i, int depth=0);
#else
void propagating_flip(const Face_handle& f,int i);
#endif
// 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, 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;
}
#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
template < class InputIterator >
std::ptrdiff_t
insert(InputIterator first, InputIterator last,
typename boost::enable_if<
boost::is_convertible<
typename std::iterator_traits<InputIterator>::value_type,
Point
>
>::type* = nullptr)
#else
template < class InputIterator >
std::ptrdiff_t
insert(InputIterator first, InputIterator last)
#endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
{
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;
}
#ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
private:
using Triangulation::top_get_first;
using Triangulation::top_get_second;
template <class Tuple_or_pair,class InputIterator>
std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last)
{
size_type n = this->number_of_vertices();
std::vector<std::size_t> indices;
std::vector<Point> points;
std::vector<typename Tds::Vertex::Info> infos;
std::size_t index=0;
for (InputIterator it=first;it!=last;++it) {
Tuple_or_pair value=*it;
points.push_back(top_get_first(value));
infos.push_back (top_get_second(value));
indices.push_back(index++);
}
typedef typename Pointer_property_map<Point>::type Pmap;
typedef Spatial_sort_traits_adapter_2<Geom_traits,Pmap> Search_traits;
spatial_sort(indices.begin(), indices.end(),
Search_traits(make_property_map(points),geom_traits()));
Vertex_handle v_hint;
Face_handle hint;
for (typename std::vector<std::size_t>::const_iterator
it = indices.begin(), end = indices.end();
it != end; ++it) {
v_hint = insert(points[*it], hint);
if(v_hint!=Vertex_handle()) {
v_hint->info()=infos[*it];
hint=v_hint->face();
}
}
return this->number_of_vertices() - n;
}
public:
template < class InputIterator >
std::ptrdiff_t
insert(InputIterator first,
InputIterator last,
typename boost::enable_if<
boost::is_convertible<
typename std::iterator_traits<InputIterator>::value_type,
std::pair<Point,typename internal::Info_check<typename Tds::Vertex>::type>
> >::type* = nullptr)
{
return insert_with_info< std::pair<Point,typename internal::Info_check<typename Tds::Vertex>::type> >(first,last);
}
template <class InputIterator_1,class InputIterator_2>
std::ptrdiff_t
insert(boost::zip_iterator< boost::tuple<InputIterator_1,InputIterator_2> > first,
boost::zip_iterator< boost::tuple<InputIterator_1,InputIterator_2> > last,
typename boost::enable_if<
boost::mpl::and_<
boost::is_convertible< typename std::iterator_traits<InputIterator_1>::value_type, Point >,
boost::is_convertible< typename std::iterator_traits<InputIterator_2>::value_type, typename internal::Info_check<typename Tds::Vertex>::type >
>
>::type* = nullptr)
{
return insert_with_info< boost::tuple<Point,typename internal::Info_check<typename Tds::Vertex>::type> >(first,last);
}
#endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
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:
#ifdef CGAL_DT2_USE_RECURSIVE_PROPAGATE_CONFLICTS
template <class OutputItFaces, class OutputItBoundaryEdges>
std::pair<OutputItFaces,OutputItBoundaryEdges>
propagate_conflicts (const Point &p,
const Face_handle fh,
const 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;
}
#else // NO CGAL_DT2_USE_RECURSIVE_PROPAGATE_CONFLICTS
template <class OutputItFaces, class OutputItBoundaryEdges>
std::pair<OutputItFaces,OutputItBoundaryEdges>
non_recursive_propagate_conflicts(const Point &p,
const Face_handle fh,
const int i,
std::pair<OutputItFaces,OutputItBoundaryEdges> pit) const
{
std::stack<std::pair<Face_handle, int> > stack;
stack.push(std::make_pair(fh,i));
while (!stack.empty())
{
const Face_handle fh=stack.top().first;
const int i=stack.top().second;
stack.pop();
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);
// In the non-recursive version, we walk via 'ccw(j)' first. Here, we are filling the stack
// and the order is thus the opposite (we want the top element of the stack to be 'ccw(j)')
stack.push(std::make_pair(fn,cw(j)));
stack.push(std::make_pair(fn,ccw(j)));
}
}
return pit;
}
template <class OutputItFaces, class OutputItBoundaryEdges>
std::pair<OutputItFaces,OutputItBoundaryEdges>
propagate_conflicts (const Point &p,
const Face_handle fh,
const int i,
std::pair<OutputItFaces,OutputItBoundaryEdges> pit,
int depth=0) const
{
if(depth == 100)
return non_recursive_propagate_conflicts(p, fh, i, pit);
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, depth+1);
pit = propagate_conflicts(p,fn,cw(j), pit, depth+1);
}
return pit;
}
#endif // NO CGAL_DT2_USE_RECURSIVE_PROPAGATE_CONFLICTS
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();
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->_tds.is_face(f));
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
{
CGAL_triangulation_precondition(this->_tds.is_edge(e.first,e.second));
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;
}
#ifndef CGAL_DT2_USE_RECURSIVE_PROPAGATING_FLIP
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
non_recursive_propagating_flip(Face_handle f, int i)
{
std::stack<Edge> edges;
const Vertex_handle& vp = f->vertex(i);
const Point& p = vp->point();
edges.push(Edge(f,i));
while(! edges.empty()) {
const Edge& e = edges.top();
f = e.first;
i = e.second;
const Face_handle& n = f->neighbor(i);
if(ON_POSITIVE_SIDE != side_of_oriented_circle(n, p, true)) {
edges.pop();
continue;
}
this->flip(f, i);
// As we haven't popped it, we don't have to push it
edges.push(Edge(n,n->index(vp)));
}
}
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
propagating_flip(const Face_handle& f,int i, int depth)
{
#ifdef CGAL_DT2_IMMEDIATELY_NON_RECURSIVE_PROPAGATING_FLIP
non_recursive_propagating_flip(f,i);
#else
int max_depth = 100;
if(depth==max_depth) {
non_recursive_propagating_flip(f,i);
return;
}
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,depth+1);
i = n->index(f->vertex(i));
propagating_flip(n,i,depth+1);
#endif
}
#else
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
propagating_flip(const 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);
}
#endif
///////////////////////////////////////////////////////////////
// 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 {
CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, maxd,30);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<Face_handle>, f, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<int>, i, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(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; }
CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, maxd,30);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<Face_handle>, f, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<int>, i, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(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> &,
std::vector<Vertex_handle> &,
std::vector<int> &,int)
{
// removing a degree d vertex, (dim is not going down)
// this is the old removal procedure that is used now only if d > 7
std::list<Edge> hole;
make_hole(v, hole);
fill_hole_delaunay(hole);
return;
}
template < class Gt, class Tds >
void
Delaunay_triangulation_2<Gt,Tds>::
remove_degree3(Vertex_handle, std::vector<Face_handle> &f,
std::vector<Vertex_handle> &, 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, 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 &,
Face_handle & f0, Face_handle & f1, Face_handle & f2,
Face_handle & f3, Face_handle & f4,
Vertex_handle &v0, Vertex_handle &, Vertex_handle &,
Vertex_handle &, Vertex_handle &,
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 &,
Face_handle & f0, Face_handle & f1, Face_handle & f2,
Face_handle & f3, Face_handle & f4, Face_handle & f5,
Vertex_handle &v0, Vertex_handle &, Vertex_handle &,
Vertex_handle &, Vertex_handle &, Vertex_handle &,
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 &,
Face_handle & f0, Face_handle & f1, Face_handle & f2,
Face_handle & f3, Face_handle & f4, Face_handle & f5,
Vertex_handle &v0, Vertex_handle &, Vertex_handle &,
Vertex_handle &v3, Vertex_handle &, Vertex_handle &,
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 &,
Face_handle & f0, Face_handle & f1, Face_handle & f2,
Face_handle & f3, Face_handle & f4, Face_handle & f5,
Vertex_handle &v0, Vertex_handle &, Vertex_handle &,
Vertex_handle &v3, Vertex_handle &, Vertex_handle &,
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 &,
Face_handle & f0, Face_handle & f1, Face_handle & f2,
Face_handle & f3, Face_handle & f4, Face_handle & f5,
Vertex_handle &v0, Vertex_handle &, Vertex_handle &v2,
Vertex_handle &, Vertex_handle &v4, Vertex_handle &,
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 &, 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 &, 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 &, 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 &, 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 &, 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 &, 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;
CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, maxd,30);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<Face_handle>, f, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<int>, i, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(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;
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;
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);
{
CGAL_STATIC_THREAD_LOCAL_VARIABLE(int, maxd,30);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<Face_handle>, f, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(std::vector<int>, i, maxd);
CGAL_STATIC_THREAD_LOCAL_VARIABLE(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