cgal/Apollonius_graph_2/include/CGAL/Apollonius_graph_2.C

2077 lines
52 KiB
C

// Copyright (c) 2003,2004 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) : Menelaos Karavelas <mkaravel@cse.nd.edu>
#ifndef CGAL_APOLLONIUS_GRAPH_2_C
#define CGAL_APOLLONIUS_GRAPH_2_C
// class implementation continued
//=================================
CGAL_BEGIN_NAMESPACE
//--------------------------------------------------------------------
// test method
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
is_valid(bool verbose, int level) const
{
if (level < 0) { return true; }
if (number_of_vertices() <= 1) { return true; }
// level 0 test: check the TDS
bool result = this->_tds.is_valid(verbose, level);
// bool result(true);
// CGAL_assertion( result );
if ( result && verbose ) {
std::cerr << "AGDS is ok... " << std::flush;
}
if (level == 0) { return result; }
// level 1 test: do the incircle tests
if (number_of_vertices() < 3) return true;
// CGAL_triangulation_assertion(result);
for (All_edges_iterator eit = all_edges_begin();
eit != all_edges_end(); ++eit) {
Edge e = *eit;
Face_handle f = e.first;
Vertex_handle v = tds().mirror_vertex(f, e.second);
if ( f->vertex(e.second) == v ) { continue; }
if ( !is_infinite(v) ) {
result = result &&
( incircle(f, v->site()) != NEGATIVE );
// CGAL_triangulation_assertion(result);
}
Edge sym_e = sym_edge(e);
f = sym_e.first;
v = tds().mirror_vertex(f, sym_e.second);
if ( !is_infinite(v) ) {
result = result &&
( incircle(f, v->site()) != NEGATIVE );
// CGAL_triangulation_assertion(result);
}
}
if ( result && verbose ) {
std::cerr << "Apollonius diagram is ok..." << std::flush;
}
if ( !result && verbose ) {
std::cerr << "Apollonius diagram is NOT valid..." << std::flush;
}
// CGAL_triangulation_assertion(result);
return result;
}
//--------------------------------------------------------------------
// embedding and visualization methods and constructions for primal
// and dual
//--------------------------------------------------------------------
// circumcenter
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Point_2
Apollonius_graph_2<Gt,Agds,LTag>::
circumcenter(const Face_handle& f) const
{
CGAL_triangulation_precondition (dimension()==2 || !is_infinite(f));
return circumcenter(f->vertex(0)->site(),
f->vertex(1)->site(),
f->vertex(2)->site());
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Point_2
Apollonius_graph_2<Gt,Agds,LTag>::
circumcenter(const Site_2& p0, const Site_2& p1,
const Site_2& p2) const
{
return
geom_traits().construct_Apollonius_vertex_2_object()(p0, p1, p2);
}
// circumcircle
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Site_2
Apollonius_graph_2<Gt,Agds,LTag>::
circumcircle(const Face_handle& f) const
{
CGAL_triangulation_precondition (dimension()==2 || !is_infinite(f));
return circumcircle(f->vertex(0)->site(),
f->vertex(1)->site(),
f->vertex(2)->site());
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Site_2
Apollonius_graph_2<Gt,Agds,LTag>::
circumcircle(const Site_2& p0, const Site_2& p1,
const Site_2& p2) const
{
return
geom_traits().construct_Apollonius_site_2_object()(p0, p1, p2);
}
template<class Gt, class Agds, class LTag>
typename Gt::Line_2
Apollonius_graph_2<Gt,Agds,LTag>::
circumcircle(const Site_2& p0, const Site_2& p1) const
{
return
geom_traits().construct_Apollonius_site_2_object()(p0, p1);
}
// dual
template<class Gt, class Agds, class LTag>
typename Gt::Object_2
Apollonius_graph_2<Gt,Agds,LTag>::
dual(const Face_handle& f) const
{
if ( !is_infinite(f) ) {
Site_2 cc = circumcircle(f);
return geom_traits().construct_object_2_object()(cc);
}
int i_inf(-1);
for (int i = 0; i < 3; i++) {
if ( is_infinite( f->vertex(i) ) ) {
i_inf = i;
break;
}
}
typename Gt::Line_2 ll = circumcircle(f->vertex((i_inf+1)%3)->site(),
f->vertex((i_inf+2)%3)->site());
return geom_traits().construct_object_2_object()(ll);
}
template<class Gt, class Agds, class LTag>
typename Gt::Object_2
Apollonius_graph_2<Gt,Agds,LTag>::
dual(const Edge e) const
{
CGAL_triangulation_precondition( !is_infinite(e) );
if ( dimension() == 1 ) {
Site_2 p = (e.first)->vertex(cw(e.second))->site();
Site_2 q = (e.first)->vertex(ccw(e.second))->site();
return construct_Apollonius_bisector_2_object()(p,q);
}
// dimension == 2
// none of the two adjacent faces is infinite
if( (!is_infinite(e.first)) &&
(!is_infinite(e.first->neighbor(e.second))) ) {
Site_2 p = (e.first)->vertex( ccw(e.second) )->site();
Site_2 q = (e.first)->vertex( cw(e.second) )->site();
Site_2 r = (e.first)->vertex( e.second )->site();
Site_2 s = tds().mirror_vertex(e.first, e.second)->site();
return construct_Apollonius_bisector_segment_2_object()(p,q,r,s);
}
// both of the adjacent faces are infinite
if ( is_infinite(e.first) &&
is_infinite(e.first->neighbor(e.second)) ) {
Site_2 p = (e.first)->vertex(cw(e.second))->site();
Site_2 q = (e.first)->vertex(ccw(e.second))->site();
return construct_Apollonius_bisector_2_object()(p,q);
}
// only one of the adjacent faces is infinite
CGAL_triangulation_assertion( is_infinite( e.first ) ||
is_infinite( e.first->neighbor(e.second) )
);
CGAL_triangulation_assertion( !(is_infinite( e.first ) &&
is_infinite( e.first->neighbor(e.second) )
)
);
CGAL_triangulation_assertion
( is_infinite( e.first->vertex(e.second) ) ||
is_infinite( tds().mirror_vertex(e.first, e.second) ) );
Edge ee = e;
if ( is_infinite( e.first->vertex(e.second) ) ) {
ee = sym_edge(e);
}
Site_2 p = ee.first->vertex( ccw(ee.second) )->site();
Site_2 q = ee.first->vertex( cw(ee.second) )->site();
Site_2 r = ee.first->vertex( ee.second )->site();
return construct_Apollonius_bisector_ray_2_object()(p,q,r);
}
// primal
template<class Gt, class Agds, class LTag>
typename Gt::Object_2
Apollonius_graph_2<Gt,Agds,LTag>::
primal(const Edge e) const
{
typedef typename Geom_traits::Segment_2 Segment;
typedef typename Geom_traits::Ray_2 Ray;
typedef CGAL::Hyperbola_segment_2<Gt> Hyperbola_segment;
typedef CGAL::Parabola_segment_2<Gt> Parabola_segment;
// typedef typename Geom_traits::Hyperbola_segment_2 Hyperbola_segment;
// typedef typename Geom_traits::Parabola_segment_2 Parabola_segment;
// CGAL_triangulation_precondition( !is_infinite(e) );
if ( number_of_vertices() != 2 ) {
if ( is_infinite(e) ) {
Ray ray;
if ( is_infinite( e.first->vertex(cw(e.second)) ) ) {
Site_2 p = e.first->vertex( ccw(e.second) )->site();
Site_2 r = e.first->vertex( e.second )->site();
Site_2 s = tds().mirror_vertex( e.first, e.second )->site();
ray = construct_Apollonius_primal_ray_2_object()(p,r,s);
} else {
CGAL_triangulation_assertion
( is_infinite( e.first->vertex(ccw(e.second)) ) );
Site_2 q = e.first->vertex( cw(e.second) )->site();
Site_2 r = e.first->vertex( e.second )->site();
Site_2 s = tds().mirror_vertex( e.first, e.second )->site();
ray = construct_Apollonius_primal_ray_2_object()(q,s,r);
}
return make_object(ray);
}
}
if ( dimension() == 1 ) {
Site_2 p = (e.first)->vertex(cw(e.second))->site();
Site_2 q = (e.first)->vertex(ccw(e.second))->site();
Segment seg = construct_Apollonius_primal_segment_2_object()(p, q);
return make_object(seg);
}
// dimension == 2
if( (!is_infinite(e.first)) &&
(!is_infinite(e.first->neighbor(e.second))) ) {
Site_2 p = (e.first)->vertex( ccw(e.second) )->site();
Site_2 q = (e.first)->vertex( cw(e.second) )->site();
Site_2 r = (e.first)->vertex( e.second )->site();
Site_2 s = tds().mirror_vertex(e.first, e.second)->site();
return construct_Apollonius_primal_segment_2_object()(p,q,r,s);
}
// both of the adjacent faces are infinite
if ( is_infinite(e.first) &&
is_infinite(e.first->neighbor(e.second)) ) {
Site_2 p = (e.first)->vertex(cw(e.second))->site();
Site_2 q = (e.first)->vertex(ccw(e.second))->site();
Segment seg = construct_Apollonius_primal_segment_2_object()(p,q);
return make_object(seg);
}
// only one of the adjacent faces is infinite
Edge ee = e;
if ( is_infinite(e.first) ) {
ee = sym_edge(e);
}
Site_2 p = (ee.first)->vertex( ccw(ee.second) )->site();
Site_2 q = (ee.first)->vertex( cw(ee.second) )->site();
Site_2 r = (ee.first)->vertex( ee.second )->site();
Parabola_segment ps =
construct_Apollonius_primal_segment_2_object()(p,q,r);
return make_object(ps);
}
//--------------------------------------------------------------------
// combinatorial operations
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Edge
Apollonius_graph_2<Gt,Agds,LTag>::
flip(Face_handle& f, int i)
{
CGAL_triangulation_precondition ( f != Face_handle() );
CGAL_triangulation_precondition (i == 0 || i == 1 || i == 2);
CGAL_triangulation_precondition( dimension()==2 );
CGAL_triangulation_precondition( f->vertex(i) != tds().mirror_vertex(f,i) );
this->_tds.flip(f, i);
return Edge(f, ccw(i));
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Edge
Apollonius_graph_2<Gt,Agds,LTag>::
flip(Edge e)
{
return flip(e.first, e.second);
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_in_face(Face_handle& f, const Site_2& p)
{
Vertex_handle v = this->_tds.insert_in_face( f );
v->set_site(p);
return v;
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
is_degree_2(const Vertex_handle& v) const
{
Face_circulator fc = incident_faces(v);
Face_circulator fc1 = fc;
++(++fc1);
return ( fc == fc1 );
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_degree_2(Edge e)
{
return this->_tds.insert_degree_2(e.first, e.second);
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_degree_2(Edge e, const Site_2& p)
{
Vertex_handle v = insert_degree_2(e);
v->set_site(p);
return v;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_degree_2(Vertex_handle v)
{
CGAL_triangulation_precondition( is_degree_2(v) );
this->_tds.remove_degree_2( v );
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_degree_3(Vertex_handle v)
{
#ifdef CGAL_T2_USE_ITERATOR_AS_HANDLE
remove_degree_3(v, Face_handle());
#else
remove_degree_3(v, NULL);
#endif
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
#ifdef CGAL_T2_USE_ITERATOR_AS_HANDLE
remove_degree_3(Vertex_handle v, Face_handle f) // af:was Face*
#else
remove_degree_3(Vertex_handle v, Face* f)
#endif
{
CGAL_triangulation_precondition( degree(v) == 3 );
this->_tds.remove_degree_3(v, f);
}
//--------------------------------------------------------------------
// insertion of weighted point
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_first(const Site_2& p)
{
CGAL_triangulation_precondition(number_of_vertices() == 0);
Vertex_handle v = this->_tds.insert_second();
v->set_site(p);
return v;
// return Delaunay_graph::insert_first(p);
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_second(const Site_2& p)
{
CGAL_triangulation_precondition( number_of_vertices() == 1 );
Vertex_handle vnew;
Vertex_handle v(finite_vertices_begin());
if ( is_hidden(v->site(), p) ) {
v->add_hidden_site(p);
vnew = Vertex_handle();
} else if ( is_hidden(p, v->site()) ) {
v->add_hidden_site(v->site());
v->set_site(p);
vnew = v;
} else {
CGAL_triangulation_precondition(number_of_vertices() == 1);
vnew = this->_tds.insert_dim_up(infinite_vertex(), true);
vnew->set_site(p);
// vnew = Delaunay_graph::insert_second(p);
}
return vnew;
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert_third(const Site_2& p)
{
CGAL_triangulation_precondition( number_of_vertices() == 2 );
Vertex_handle v1(finite_vertices_begin());
Vertex_handle v2(++finite_vertices_begin());
if ( is_hidden(v1->site(), p) ) {
v1->add_hidden_site(p);
return Vertex_handle();
}
if ( is_hidden(v2->site(), p) ) {
v2->add_hidden_site(p);
return Vertex_handle();
}
bool t1 = is_hidden(p, v1->site());
bool t2 = is_hidden(p, v2->site());
if ( t1 && !t2 ) {
v1->add_hidden_site(v1->site());
v1->set_site(p);
return v1;
} else if ( !t1 && t2 ) {
v2->add_hidden_site(v2->site());
v2->set_site(p);
return v2;
} else if ( t1 && t2 ) {
v1->add_hidden_site(v1->site());
v1->add_hidden_site(v2->site());
v1->set_site(p);
remove_second(v2);
return v1;
}
Vertex_handle v = this->_tds.insert_dim_up(infinite_vertex());
v->set_site(p);
Face_handle f(finite_faces_begin());
Point_2 p1 = f->vertex(0)->site().point();
Point_2 p2 = f->vertex(1)->site().point();
Point_2 p3 = f->vertex(2)->site().point();
Orientation o =
geom_traits().orientation_2_object()(p1, p2, p3);
if ( o != LEFT_TURN ) {
f->reorient();
for (int i = 0; i < 3; i++) {
f->neighbor(i)->reorient();
}
}
Conflict_type ct =
finite_edge_conflict_type_degenerated(v1->site(), v2->site(), p);
if ( ct == NO_CONFLICT ) {
Oriented_side os =
side_of_bisector(v1->site(), v2->site(), p.point());
CGAL_assertion( os != ON_ORIENTED_BOUNDARY );
Vertex_handle vv = ( os == ON_NEGATIVE_SIDE ) ? v1 : v2;
Face_circulator fc = incident_faces(v);
while ( true ) {
Face_handle f(fc);
int k = f->index(v);
Vertex_handle vh = f->vertex(ccw(k));
if ( vh == vv ) {
flip(f, cw(k));
break;
}
++fc;
}
} else if ( ct == INTERIOR ) {
Edge_circulator ec = incident_edges(v);
while ( true ) {
if ( is_infinite(ec) ) {
flip(*ec);
break;
}
ec++;
}
} else if ( ct == ENTIRE_EDGE ) {
Face_circulator fc = incident_faces(v);
while ( true ) {
Face_handle f(fc);
if ( !is_infinite(f) ) {
flip(f, f->index(v));
break;
}
++fc;
}
} else if ( ct == BOTH_VERTICES ) {
Conflict_type ct1 =
finite_edge_conflict_type_degenerated(v1->site(), p, v2->site());
Edge_circulator ec;
ec = ( ct1 == INTERIOR ) ? incident_edges(v2) : incident_edges(v1);
while ( true ) {
if ( is_infinite(ec) ) {
flip(*ec);
break;
}
ec++;
}
} else {
CGAL_assertion( ct == RIGHT_VERTEX || ct == LEFT_VERTEX );
// do nothing here
}
// CGAL_triangulation_assertion( is_valid() );
return v;
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
insert(const Site_2& p, Vertex_handle vnear)
{
if ( number_of_vertices() == 0 ) {
return insert_first(p);
}
if ( number_of_vertices() == 1 ) {
return insert_second(p);
}
if ( number_of_vertices() == 2 ) {
return insert_third(p);
}
// first find the nearest neighbor
Vertex_handle vnearest = nearest_neighbor(p.point(), vnear);
CGAL_assertion( vnearest != Vertex_handle() );
// check if it is hidden
Site_2 wp_nearest = vnearest->site();
if ( is_hidden(wp_nearest, p) ) {
vnearest->add_hidden_site(p);
return Vertex_handle();
}
// find the first conflict
// first look for conflict with vertex
Face_circulator fc_start = incident_faces(vnearest);
Face_circulator fc = fc_start;
Face_handle start_f;
Sign s;
do {
Face_handle f(fc);
s = incircle(f, p);
if ( s == NEGATIVE ) {
start_f = f;
break;
}
++fc;
} while ( fc != fc_start );
// we are not in conflict with an Apollonius vertex, so we have to
// be in conflict with the interior of an Apollonius edge
if ( s != NEGATIVE ) {
Edge_circulator ec_start = incident_edges(vnearest);
Edge_circulator ec = ec_start;
bool interior_in_conflict(false);
Edge e;
do {
e = *ec;
interior_in_conflict = edge_interior(e, p, false);
if ( interior_in_conflict ) { break; }
++ec;
} while ( ec != ec_start );
CGAL_assertion( interior_in_conflict );
return insert_degree_2(e, p);
}
// we are in conflict with an Apollonius vertex; start from that and
// find the entire conflict region and then repair the diagram
List l;
Face_map fm;
Vertex_map vm;
// MK:: NEED TO WRITE A FUNCTION CALLED find_conflict_region WHICH
// IS GIVEN A STARTING FACE, A LIST, A FACE MAP, A VERTEX MAP AND A
// LIST OF FLIPPED EDGES AND WHAT IS DOES IS INITIALIZE THE CONFLICT
// REGION AND EXPANDS THE CONFLICT REGION.
initialize_conflict_region(start_f, l);
expand_conflict_region(start_f, p, l, fm, vm, NULL);
// retriangulate_conflict_region(v, l, fm, vm);
Vertex_handle v = retriangulate_conflict_region(p, l, fm, vm);
fm.clear();
vm.clear();
return v;
}
//--------------------------------------------------------------------
// find conflict region
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
find_conflict_region_remove(const Vertex_handle& v,
const Vertex_handle& vnearest,
List& l, Face_map& fm,
Vertex_map& vm,
std::vector<Vh_triple*>* fe)
{
Site_2 p = v->site();
// check if it is hidden
Site_2 wp_nearest = vnearest->site();
if ( is_hidden(wp_nearest, p) ) {
vnearest->add_hidden_site(p);
return;
}
CGAL_precondition( vnearest != Vertex_handle() );
// find the first conflict
// first look for conflict with vertex
Face_circulator fc_start = incident_faces(vnearest);
Face_circulator fc = fc_start;
Face_handle start_f;
Sign s;
do {
Face_handle f(fc);
s = incircle(f, p);
if ( s == NEGATIVE ) {
start_f = f;
break;
}
++fc;
} while ( fc != fc_start );
CGAL_assertion( s == NEGATIVE );
// we are not in conflict with an Apollonius vertex, so we have to
// be in conflict with the interior of an Apollonius edge
if ( s != NEGATIVE ) {
Edge_circulator ec_start = incident_edges(vnearest);
Edge_circulator ec = ec_start;
bool interior_in_conflict(false);
Edge e;
do {
e = *ec;
interior_in_conflict = edge_interior(e, p, false);
if ( interior_in_conflict ) { break; }
++ec;
} while ( ec != ec_start );
CGAL_assertion( interior_in_conflict );
l.push_back(e);
l.push_back(sym_edge(e));
return;
}
initialize_conflict_region(start_f, l);
expand_conflict_region(start_f, v->site(), l, fm, vm, fe);
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
initialize_conflict_region(const Face_handle& f, List& l) const
{
l.clear();
for (int i = 0; i < 3; i++) {
l.push_back(sym_edge(f, i));
}
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
check_edge_for_hidden_sites(const Face_handle& f, int i,
const Site_2& p, Vertex_map& vm) const
{
bool found(false);
Vertex_handle v1 = f->vertex(ccw(i));
if ( vm.find(v1) == vm.end() ) {
if ( !is_infinite(v1) && is_hidden(p, v1->site()) ) {
vm[v1] = true;
found = true;
}
} else {
found = true;
}
Vertex_handle v2 = f->vertex(cw(i));
if ( vm.find(v2) == vm.end() ) {
if ( !is_infinite(v2) && is_hidden(p, v2->site()) ) {
vm[v2] = true;
found = true;
}
} else {
found = true;
}
return found;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
expand_conflict_region(const Face_handle& f, const Site_2& p,
List& l, Face_map& fm, Vertex_map& vm,
std::vector<Vh_triple*>* fe)
{
// setting fm[f] to true means that the face has been reached and
// that the face is available for recycling. If we do not want the
// face to be available for recycling we must set this flag to
// false.
fm[f] = true;
// CGAL_assertion( fm.find(f) != fm.end() );
for (int i = 0; i < 3; i++) {
bool hidden_found =
check_edge_for_hidden_sites(f, i, p, vm);
Face_handle n = f->neighbor(i);
if ( !hidden_found ) {
Sign s = incircle(n, p);
if ( s != NEGATIVE ) { continue; }
bool interior_in_conflict = edge_interior(f, i, p, true);
if ( !interior_in_conflict ) { continue; }
}
if ( fm.find(n) != fm.end() ) {
Edge e = sym_edge(f, i);
if ( l.is_in_list(e) ||
l.is_in_list(sym_edge(e)) ) {
l.remove(e);
l.remove(sym_edge(e));
}
continue;
}
Edge e = sym_edge(f, i);
CGAL_assertion( l.is_in_list(e) );
int j = tds().mirror_index(f, i);
Edge e_before = sym_edge(n, ccw(j));
Edge e_after = sym_edge(n, cw(j));
if ( !l.is_in_list(e_before) ) {
l.insert_before(e, e_before);
}
if ( !l.is_in_list(e_after) ) {
l.insert_after(e, e_after);
}
l.remove(e);
if ( fe != NULL ) {
Vh_triple* vhq = new Vh_triple[1];
(*vhq)[0] = Vertex_handle();
(*vhq)[1] = n->vertex( j );
(*vhq)[2] = n->vertex( ccw(j) );
fe->push_back(vhq);
}
expand_conflict_region(n, p, l, fm, vm, fe);
} // for-loop
}
//--------------------------------------------------------------------
// retriangulate conflict region
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
add_bogus_vertex(Edge e, List& l)
{
Edge esym = sym_edge(e);
Face_handle g1 = e.first;
Face_handle g2 = esym.first;
Vertex_handle v = insert_degree_2(e);
Face_circulator fc(v);
Face_handle f1(fc);
Face_handle f2(++fc);
int i1 = f1->index(v);
int i2 = f2->index(v);
CGAL_assertion( ((f1->neighbor(i1) == g1) && (f2->neighbor(i2) == g2)) ||
((f1->neighbor(i1) == g2) && (f2->neighbor(i2) == g1)) );
Edge ee, eesym;
if ( f1->neighbor(i1) == g1 ) {
ee = Edge(f2, i2);
eesym = Edge(f1, i1);
} else {
ee = Edge(f1, i1);
eesym = Edge(f2, i2);
}
l.replace(e, ee);
l.replace(esym, eesym);
return v;
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_list
Apollonius_graph_2<Gt,Agds,LTag>::
add_bogus_vertices(List& l)
{
Vertex_list vertex_list;
Edge_list edge_list;
Edge e_start = l.front();
Edge e = e_start;
do {
Edge esym = sym_edge(e);
if ( l.is_in_list(esym) &&
edge_list.find(esym) == edge_list.end() ) {
edge_list.insert(e);
}
e = l.next(e);
} while ( e != e_start );
typename Edge_list::iterator it;
for (it = edge_list.begin(); it != edge_list.end(); ++it) {
e = *it;
Vertex_handle v = add_bogus_vertex(e, l);
vertex_list.push_back(v);
}
return vertex_list;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_bogus_vertices(Vertex_list& vl)
{
while ( vl.size() > 0 ) {
Vertex_handle v = vl.front();
vl.pop_front();
remove_degree_2(v);
}
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
move_hidden_sites(Vertex_handle& vold, Vertex_handle& vnew)
{
typename Vertex::Hidden_sites_iterator wpit;
for (wpit = vold->hidden_sites_begin();
wpit != vold->hidden_sites_end(); ++wpit) {
vnew->add_hidden_site(*wpit);
}
vold->clear_hidden_sites_container();
}
template<class Gt, class Agds, class LTag>
std::vector<typename Apollonius_graph_2<Gt,Agds,LTag>::Face*>
Apollonius_graph_2<Gt,Agds,LTag>::
get_faces_for_recycling(Face_map& fm, unsigned int n_wanted)
{
std::vector<Face*> vf;
typename Face_map::iterator fmit;
for (fmit = fm.begin(); fmit != fm.end(); ++fmit) {
Face_handle f = (*fmit).first;
if ( fm[f] == true ) { vf.push_back( f ); }
}
while ( vf.size() < n_wanted ) {
Face* fp = static_cast<Face*>(this->_tds.create_face());
vf.push_back(fp);
}
while ( vf.size() > n_wanted ) {
Face* fp = vf.back();
vf.pop_back();
this->_tds.delete_face(fp);
}
return vf;
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_hidden_vertices(Vertex_map& vm)
{
typename Vertex_map::iterator it;
for (it = vm.begin(); it != vm.end(); ++it) {
Vertex_handle vhidden = (*it).first;
this->_tds.delete_vertex( vhidden );
}
vm.clear();
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
retriangulate_conflict_region(const Site_2& p, List& l,
Face_map& fm, Vertex_map& vm)
{
size_type vmsize = vm.size();
size_type num_vert = number_of_vertices();
if ( num_vert - vmsize == 0 ) {
// 1. copy all hidden sites to a temporary list
Site_list wp_list;
typename Vertex_map::iterator vmit;
for (vmit = vm.begin(); vmit != vm.end(); ++vmit) {
Vertex_handle vhidden = (*vmit).first;
wp_list.push_back(vhidden->site());
typename Vertex::Hidden_sites_iterator it;
for (it = vhidden->hidden_sites_begin();
it != vhidden->hidden_sites_end(); ++it) {
wp_list.push_back(*it);
}
vhidden->clear_hidden_sites_container();
}
// 2. clear the current Apollonius diagram
clear();
// 3. add a new vertex
Vertex_handle v = insert_first(p);
// 4. add all old sites to the hidden site list of the
// new site
Site_list_iterator wpit;
for (wpit = wp_list.begin(); wpit != wp_list.end(); ++wpit) {
v->add_hidden_site(*wpit);
}
return v;
} else if ( num_vert - vmsize == 1 ) {
// 1. copy all hidden sites to a temporary list
Site_list wp_list;
typename Vertex_map::iterator vmit;
for (vmit = vm.begin(); vmit != vm.end(); ++vmit) {
Vertex_handle vhidden = (*vmit).first;
wp_list.push_back(vhidden->site());
typename Vertex::Hidden_sites_iterator it;
for (it = vhidden->hidden_sites_begin();
it != vhidden->hidden_sites_end(); ++it) {
wp_list.push_back(*it);
}
vhidden->clear_hidden_sites_container();
}
// 2. find which vertex remains non-hidden and copy its hidden
// sites to a local container
Vertex_handle non_hidden;
Finite_vertices_iterator vit = finite_vertices_begin();
do {
non_hidden = Vertex_handle(vit);
++vit;
} while ( vm.find(non_hidden) != vm.end() );
Site_2 p1 = non_hidden->site();
Site_list wp_list1;
typename Vertex::Hidden_sites_iterator it;
for (it = non_hidden->hidden_sites_begin();
it != non_hidden->hidden_sites_end(); ++it) {
wp_list1.push_back(*it);
}
non_hidden->clear_hidden_sites_container();
// 3. clear the current Apollonius graph
clear();
// 4. insert the two non-hidden sites and copy the corresponding
// hidden sites
Vertex_handle v1 = insert_first(p1);
for (Site_list_iterator it = wp_list1.begin();
it != wp_list1.end(); ++it) {
v1->add_hidden_site(*it);
}
Vertex_handle v = insert_second(p);
for (Site_list_iterator it = wp_list.begin();
it != wp_list.end(); ++it) {
v->add_hidden_site(*it);
}
return v;
}
Vertex_handle v = this->_tds.create_vertex();
v->set_site(p);
// 1. move all the hidden sites to the new one
typename Vertex_map::iterator vmit;
for (vmit = vm.begin(); vmit != vm.end(); ++vmit) {
Vertex_handle vhidden = (*vmit).first;
move_hidden_sites(vhidden, v);
v->add_hidden_site(vhidden->site());
}
CGAL_precondition( number_of_vertices() - vm.size() >= 2 );
// 2. add the bogus vetrices
Vertex_list dummy_vertices = add_bogus_vertices(l);
// 3. repair the face pointers...
Edge e_start = l.front();
Edge eit = e_start;
do {
Edge esym = sym_edge(eit);
Face_handle f = eit.first;
int k = eit.second;
CGAL_assertion( !l.is_in_list(esym) );
CGAL_assertion( fm.find(f) == fm.end() );
f->vertex(ccw(k))->set_face(f);
f->vertex( cw(k))->set_face(f);
eit = l.next(eit);
} while ( eit != e_start );
// std::vector<Face*> vf = get_faces_for_recycling(fm, l.size());
std::list<Face*> vf;
// 4. copy the edge list to a vector of edges and clear the in place
// list
typedef typename Agds::Edge Agds_edge;
std::vector<Agds_edge> ve;
Edge efront = l.front();
Edge e = efront;
do {
ve.push_back(Agds_edge(e.first, e.second));
e = l.next(e);
} while ( e != efront );
l.clear();
// 5. remove the hidden vertices
remove_hidden_vertices(vm);
// 6. retriangulate the hole
// _tds.star_hole( v, ve.begin(), ve.end(), vf.begin(), vf.end());
this->_tds.star_hole(v, ve.begin(), ve.end());
// 7. remove the bogus vertices
remove_bogus_vertices(dummy_vertices);
// 8. remove the unused faces
typename Face_map::iterator it;
for (it = fm.begin(); it != fm.end(); ++it) {
Face_handle fh = (*it).first;
this->_tds.delete_face( fh );
}
CGAL_assertion( number_of_vertices() + vmsize == num_vert + 1 );
// 9. DONE!!!!
return v;
}
//--------------------------------------------------------------------
// point location
//--------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
nearest_neighbor(const Point_2& p) const
{
return nearest_neighbor(p, Vertex_handle());
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Vertex_handle
Apollonius_graph_2<Gt,Agds,LTag>::
nearest_neighbor(const Point_2& p,
Vertex_handle start_vertex) const
{
if ( number_of_vertices() == 0 ) {
return Vertex_handle();
}
if ( start_vertex == Vertex_handle() ) {
start_vertex = finite_vertex();
}
// if ( start_vertex == Vertex_handle() ) { return start_vertex; }
Vertex_handle vclosest;
Vertex_handle v = start_vertex;
if ( number_of_vertices() < 3 ) {
vclosest = v;
Finite_vertices_iterator vit = finite_vertices_begin();
for (; vit != finite_vertices_end(); ++vit) {
Vertex_handle v1(vit);
if ( v1 != vclosest /*&& !is_infinite(v1)*/ ) {
Site_2 p1 = vclosest->site();
Site_2 p2 = v1->site();
if ( side_of_bisector(p1, p2, p) == ON_NEGATIVE_SIDE ) {
vclosest = v1;
}
}
}
return vclosest;
}
do {
vclosest = v;
Site_2 p1 = v->site();
Vertex_circulator vc_start = incident_vertices(v);
Vertex_circulator vc = vc_start;
do {
if ( !is_infinite(vc) ) {
Vertex_handle v1(vc);
Site_2 p2 = v1->site();
if ( side_of_bisector(p1, p2, p) == ON_NEGATIVE_SIDE ) {
v = v1;
break;
}
}
++vc;
} while ( vc != vc_start );
} while ( vclosest != v );
return vclosest;
}
//----------------------------------------------------------------------
// methods for the predicates
//----------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
is_hidden(const Site_2 &p, const Site_2 &q) const
{
return geom_traits().is_hidden_2_object()(p, q);
}
template<class Gt, class Agds, class LTag>
Oriented_side
Apollonius_graph_2<Gt,Agds,LTag>::
side_of_bisector(const Site_2 &p1,
const Site_2 &p2,
const Point_2 &p) const
{
return geom_traits().oriented_side_of_bisector_2_object()(p1, p2, p);
}
template<class Gt, class Agds, class LTag>
Sign
Apollonius_graph_2<Gt,Agds,LTag>::
incircle(const Site_2 &p1, const Site_2 &p2,
const Site_2 &p3, const Site_2 &q) const
{
return geom_traits().vertex_conflict_2_object()(p1, p2, p3, q);
}
template<class Gt, class Agds, class LTag>
Sign
Apollonius_graph_2<Gt,Agds,LTag>::
incircle(const Site_2 &p1, const Site_2 &p2,
const Site_2 &q) const
{
return
geom_traits().vertex_conflict_2_object()(p1, p2, q);
}
template<class Gt, class Agds, class LTag>
Sign
Apollonius_graph_2<Gt,Agds,LTag>::
incircle(const Face_handle& f, const Site_2& q) const
{
if ( !is_infinite(f) ) {
return incircle(f->vertex(0)->site(),
f->vertex(1)->site(),
f->vertex(2)->site(), q);
}
int inf_i(-1); // to avoid compiler warning
for (int i = 0; i < 3; i++) {
if ( is_infinite(f->vertex(i)) ) {
inf_i = i;
break;
}
}
return incircle( f->vertex( ccw(inf_i) )->site(),
f->vertex( cw(inf_i) )->site(), q );
}
template<class Gt, class Agds, class LTag>
Sign
Apollonius_graph_2<Gt,Agds,LTag>::
incircle(const Vertex_handle& v0, const Vertex_handle& v1,
const Vertex_handle& v) const
{
CGAL_precondition( !is_infinite(v0) && !is_infinite(v1)
&& !is_infinite(v) );
return incircle( v0->site(), v1->site(), v->site());
}
template<class Gt, class Agds, class LTag>
Sign
Apollonius_graph_2<Gt,Agds,LTag>::
incircle(const Vertex_handle& v0, const Vertex_handle& v1,
const Vertex_handle& v2, const Vertex_handle& v) const
{
CGAL_precondition( !is_infinite(v) );
if ( !is_infinite(v0) && !is_infinite(v1) &&
!is_infinite(v2) ) {
return incircle(v0->site(), v1->site(),
v2->site(), v->site());
}
if ( is_infinite(v0) ) {
CGAL_precondition( !is_infinite(v1) && !is_infinite(v2) );
return incircle( v1->site(), v2->site(), v->site());
}
if ( is_infinite(v1) ) {
CGAL_precondition( !is_infinite(v0) && !is_infinite(v2) );
return incircle( v2->site(), v0->site(), v->site());
}
CGAL_assertion( is_infinite(v2) );
CGAL_precondition( !is_infinite(v0) && !is_infinite(v1) );
return incircle( v0->site(), v1->site(), v->site());
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior(const Site_2& p1,
const Site_2& p2,
const Site_2& p3,
const Site_2& p4,
const Site_2& q, bool b) const
{
if ( is_hidden(q, p1) ) { return true; }
if ( is_hidden(q, p2) ) { return true; }
return
geom_traits().finite_edge_interior_conflict_2_object()(p1,p2,p3,p4,q,b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior(const Face_handle& f, int i,
const Site_2& p, bool b) const
{
CGAL_precondition( !is_infinite(f) &&
!is_infinite(f->neighbor(i)) );
return finite_edge_interior( f->vertex( ccw(i) )->site(),
f->vertex( cw(i) )->site(),
f->vertex( i )->site(),
tds().mirror_vertex(f, i)->site(), p, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior(const Vertex_handle& v1,
const Vertex_handle& v2,
const Vertex_handle& v3,
const Vertex_handle& v4,
const Vertex_handle& v, bool b) const
{
CGAL_precondition( !is_infinite(v1) && !is_infinite(v2) &&
!is_infinite(v3) && !is_infinite(v4) &&
!is_infinite(v) );
return finite_edge_interior( v1->site(), v2->site(),
v3->site(), v4->site(),
v->site(), b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior_degenerated(const Site_2& p1,
const Site_2& p2,
const Site_2& p3,
const Site_2& q,
bool b) const
{
if ( is_hidden(q, p1) ) { return true; }
if ( is_hidden(q, p2) ) { return true; }
return
geom_traits().finite_edge_interior_conflict_2_object()(p1,p2,p3,q,b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior_degenerated(const Site_2& p1,
const Site_2& p2,
const Site_2& q,
bool b) const
{
if ( is_hidden(q, p1) ) { return true; }
if ( is_hidden(q, p2) ) { return true; }
return
geom_traits().finite_edge_interior_conflict_2_object()(p1, p2, q, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior_degenerated(const Face_handle& f, int i,
const Site_2& p, bool b) const
{
if ( !is_infinite( tds().mirror_vertex(f, i) ) ) {
CGAL_precondition( is_infinite(f->vertex(i)) );
Face_handle g = f->neighbor(i);
int j = tds().mirror_index(f, i);
return finite_edge_interior_degenerated(g, j, p, b);
}
CGAL_precondition( is_infinite( tds().mirror_vertex(f, i) ) );
Site_2 p1 = f->vertex( ccw(i) )->site();
Site_2 p2 = f->vertex( cw(i) )->site();
if ( is_infinite(f->vertex(i)) ) {
return finite_edge_interior_degenerated(p1, p2, p, b);
}
Site_2 p3 = f->vertex(i)->site();
return finite_edge_interior_degenerated(p1, p2, p3, p, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_interior_degenerated(const Vertex_handle& v1,
const Vertex_handle& v2,
const Vertex_handle& v3,
const Vertex_handle& v4,
const Vertex_handle& v, bool b) const
{
CGAL_precondition( !is_infinite(v1) && !is_infinite(v2) &&
!is_infinite(v) );
if ( !is_infinite( v4 ) ) {
CGAL_precondition( is_infinite(v3) );
return
finite_edge_interior_degenerated(v2, v1, v4, v3, v, b);
}
CGAL_precondition( is_infinite( v4 ) );
Site_2 p1 = v1->site();
Site_2 p2 = v2->site();
Site_2 p = v->site();
if ( is_infinite(v3) ) {
return finite_edge_interior_degenerated(p1, p2, p, b);
}
Site_2 p3 = v3->site();
return finite_edge_interior_degenerated(p1, p2, p3, p, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
infinite_edge_interior(const Site_2& p2,
const Site_2& p3,
const Site_2& p4,
const Site_2& q,
bool b) const
{
if ( is_hidden(q, p2) ) { return true; }
return
geom_traits().infinite_edge_interior_conflict_2_object()(p2,p3,p4,q,b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
infinite_edge_interior(const Face_handle& f, int i,
const Site_2& p, bool b) const
{
if ( !is_infinite( f->vertex(ccw(i)) ) ) {
CGAL_precondition( is_infinite( f->vertex(cw(i)) ) );
Face_handle g = f->neighbor(i);
int j = tds().mirror_index(f, i);
return infinite_edge_interior(g, j, p, b);
}
CGAL_precondition( is_infinite( f->vertex(ccw(i)) ) );
Site_2 p2 = f->vertex( cw(i) )->site();
Site_2 p3 = f->vertex( i )->site();
Site_2 p4 = tds().mirror_vertex(f, i)->site();
return infinite_edge_interior(p2, p3, p4, p, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
infinite_edge_interior(const Vertex_handle& v1,
const Vertex_handle& v2,
const Vertex_handle& v3,
const Vertex_handle& v4,
const Vertex_handle& v, bool b) const
{
CGAL_precondition( !is_infinite(v3) && !is_infinite(v4) &&
!is_infinite(v) );
if ( !is_infinite( v1 ) ) {
CGAL_precondition( is_infinite( v2 ) );
return infinite_edge_interior(v2, v1, v4, v3, v, b);
}
CGAL_precondition( is_infinite( v1 ) );
Site_2 p2 = v2->site();
Site_2 p3 = v3->site();
Site_2 p4 = v4->site();
Site_2 p = v->site();
return infinite_edge_interior(p2, p3, p4, p, b);
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
edge_interior(const Vertex_handle& v1,
const Vertex_handle& v2,
const Vertex_handle& v3,
const Vertex_handle& v4,
const Vertex_handle& v, bool b) const
{
CGAL_precondition( !is_infinite(v) );
bool is_inf_v1 = is_infinite(v1);
bool is_inf_v2 = is_infinite(v2);
bool is_inf_v3 = is_infinite(v3);
bool is_inf_v4 = is_infinite(v4);
bool result;
if ( !is_inf_v1 && !is_inf_v2 && !is_inf_v3 && !is_inf_v4 ) {
result = finite_edge_interior(v1, v2, v3, v4, v, b);
} else if ( is_inf_v3 || is_inf_v4 ) {
result = finite_edge_interior_degenerated(v1, v2, v3, v4, v, b);
} else {
result = infinite_edge_interior(v1, v2, v3, v4, v, b);
}
return result;
}
template<class Gt, class Agds, class LTag>
bool
Apollonius_graph_2<Gt,Agds,LTag>::
edge_interior(const Face_handle& f, int i,
const Site_2& p, bool b) const
{
Face_handle g = f->neighbor(i);
bool is_inf_f = is_infinite(f);
bool is_inf_g = is_infinite(g);
bool result;
if ( !is_inf_f && !is_inf_g ) {
result = finite_edge_interior(f, i, p, b);
} else if ( !is_inf_f || !is_inf_g ) {
result = finite_edge_interior_degenerated(f, i, p, b);
} else {
// Edge e(f, i);
if ( !is_infinite(f, i) ) {
result = finite_edge_interior_degenerated(f, i, p, b);
} else {
result = infinite_edge_interior(f, i, p, b);
}
}
return result;
}
template<class Gt, class Agds, class LTag>
typename Apollonius_graph_2<Gt,Agds,LTag>::Conflict_type
Apollonius_graph_2<Gt,Agds,LTag>::
finite_edge_conflict_type_degenerated(const Site_2& p1,
const Site_2& p2,
const Site_2& q) const
{
Sign i1 = incircle(p1, p2, q);
Sign i2 = incircle(p2, p1, q);
if ( i1 == NEGATIVE && i2 == POSITIVE ) {
return LEFT_VERTEX;
} else if ( i1 == POSITIVE && i2 == NEGATIVE ) {
return RIGHT_VERTEX;
} else if ( i1 == POSITIVE && i2 == POSITIVE ) {
bool b = finite_edge_interior_degenerated(p1, p2, q, false);
return (b ? INTERIOR : NO_CONFLICT);
} else if ( i1 == NEGATIVE && i2 == NEGATIVE ) {
bool b = finite_edge_interior_degenerated(p1, p2, q, true);
return (b ? ENTIRE_EDGE : BOTH_VERTICES);
} else {
// this should never be reached; the degenerated incircle never
// returns ZERO
CGAL_assertion( false );
}
// to satisfy compiler
return NO_CONFLICT;
}
//----------------------------------------------------------------------
// methods for disk removal
//----------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_first(Vertex_handle v)
{
Delaunay_graph::remove_first(v);
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_second(Vertex_handle v)
{
Delaunay_graph::remove_second(v);
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_third(Vertex_handle v)
{
if ( is_degree_2(v) ) {
Face_handle fh( incident_faces(v) );
int i = fh->index(v);
flip(fh, i);
} else if ( degree(v) == 4 ) {
Edge_circulator ec = incident_edges(v);
for (int i = 0; i < 4; i++) {
Edge e = *ec;
Edge sym = sym_edge(e);
if ( e.first->vertex(e.second) != sym.first->vertex(sym.second) ) {
flip(e);
break;
}
++ec;
}
}
this->_tds.remove_dim_down( v );
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove(Vertex_handle v)
{
CGAL_triangulation_precondition( v != Vertex_handle() );
CGAL_triangulation_precondition( !is_infinite(v) );
// find a neighbor of v to use for point location of hidden sites to
// be re-inserted
Vertex_handle vnear;
if ( /*StoreHidden*/ true ) {
if ( number_of_vertices() > 10 ) {
Vertex_circulator vc_start = incident_vertices(v);
Vertex_circulator vc = vc_start;
do {
if ( !is_infinite(vc) ) {
vnear = Vertex_handle(vc);
break;
}
++vc;
} while ( vc != vc_start );
}
}
Site_list wp_list;
typename Vertex::Hidden_sites_iterator wpit;
for (wpit = v->hidden_sites_begin();
wpit != v->hidden_sites_end(); ++wpit) {
wp_list.push_back(*wpit);
}
int n = number_of_vertices();
if ( n == 1 ) {
remove_first(v);
} else if ( n == 2 ) {
remove_second(v);
} else if ( n == 3 ) {
remove_third(v);
} else {
int deg = degree(v);
if ( deg == 2 ) {
remove_degree_2(v);
} else if ( deg == 3 ) {
remove_degree_3(v);
} else {
remove_degree_d_vertex(v);
}
}
Site_less_than_comparator less_than(geom_traits());
std::sort(wp_list.begin(), wp_list.end(), less_than);
for (unsigned int i = 0; i < wp_list.size(); i++) {
vnear = insert(wp_list[i], vnear);
}
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
remove_degree_d_vertex(Vertex_handle v)
{
minimize_degree(v);
int deg = degree(v);
if ( deg == 3 ) {
remove_degree_3(v);
return;
}
if ( deg == 2 ) {
remove_degree_2(v);
return;
}
Apollonius_graph_2<Gt,Agds,LTag> ag_small;
std::map<Vertex_handle,Vertex_handle> vmap;
Vertex_circulator vc_start = incident_vertices(v);
Vertex_circulator vc = incident_vertices(v);
Vertex_handle vh_large, vh_small;
do {
vh_large = Vertex_handle(vc);
if ( is_infinite(vh_large) ) {
vh_small = ag_small.infinite_vertex();
vmap[vh_small] = vh_large;
} else {
vh_small = ag_small.insert(vc->site());
if ( vh_small != Vertex_handle() ) {
vmap[vh_small] = vh_large;
}
}
++vc;
} while ( vc != vc_start );
if ( ag_small.number_of_vertices() == 2 ) {
CGAL_assertion( deg == 4 );
Edge_circulator ec = incident_edges(v);
for (int i = 0; i < 4; i++) {
Edge e = *ec;
Edge sym = sym_edge(e);
if ( e.first->vertex(e.second) != sym.first->vertex(sym.second) ) {
flip(e);
break;
}
++ec;
}
remove_degree_3(v);
return;
}
Vertex_handle vn = ag_small.nearest_neighbor(v->site().point());
assert( vn != Vertex_handle() );
List l;
Face_map fm;
Vertex_map vm;
std::vector<Vh_triple*> flipped_edges;
ag_small.find_conflict_region_remove(v, vn, l, fm, vm,
&flipped_edges);
l.clear();
fm.clear();
vm.clear();
Edge_circulator ec;
unsigned int num_fe = flipped_edges.size();
for (unsigned int i = 0; i < num_fe; i++) {
Vh_triple *vhq = flipped_edges[num_fe - i - 1];
bool found(false);
ec = incident_edges(v);
Edge_circulator ec_start = ec;
do {
Edge e = *ec;
if ( (e.first->vertex( cw(e.second) ) == vmap[(*vhq)[1]] &&
e.first->vertex( e.second ) == vmap[(*vhq)[2]]) ||
(e.first->vertex( ccw(e.second) ) == vmap[(*vhq)[1]] &&
tds().mirror_vertex(e.first,e.second) == vmap[(*vhq)[2]]) ) {
flip(e);
found = true;
break;
}
++ec;
} while ( ec != ec_start );
CGAL_assertion( found );
}
CGAL_triangulation_precondition( degree(v) == 3 );
#ifdef CGAL_T2_USE_ITERATOR_AS_HANDLE
this->_tds.remove_degree_3( v, Face_handle() );
#else
this->_tds.remove_degree_3( v, NULL );
#endif
for (unsigned int i = 0; i < num_fe; i++) {
delete flipped_edges[i];
}
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::
minimize_degree(Vertex_handle v)
{
CGAL_precondition ( degree(v) > 3 );
Face_circulator fc_start = incident_faces(v);
Face_circulator fc = incident_faces(v);
bool found(false);
do {
Face_handle f = Face_handle(fc);
int i = ccw( f->index(v) );
CGAL_assertion( f->vertex( cw(i) ) == v );
Vertex_handle v0 = f->vertex( i );
Vertex_handle v1 = tds().mirror_vertex( f, i );
bool is_admissible = (v0 != v1) &&
!is_infinite(f) && !is_infinite( f->neighbor(i) );
if ( is_admissible && is_degenerate_edge(f, i) ) {
Edge e = flip(f, i);
f = e.first;
if ( !f->has_vertex(v) ) {
f = e.first->neighbor(e.second);
CGAL_assertion( f->has_vertex(v) );
}
fc = --( incident_faces(v,f) );
fc_start = fc;
found = true;
} else {
++fc;
found = false;
}
} while ( found || fc != fc_start );
}
//----------------------------------------------------------------------
// methods for I/O
//----------------------------------------------------------------------
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::file_output(std::ostream& os) const
{
// ouput to a file
size_type n = this->_tds.number_of_vertices();
size_type m = this->_tds.number_of_full_dim_faces();
CGAL_assertion( n >= 1 );
if( is_ascii(os) ) {
os << n << ' ' << m << ' ' << dimension() << std::endl;
} else {
os << n << m << dimension();
}
std::map<Vertex_handle,int> V;
std::map<Face_handle,int> F;
// first vertex (infinite vertex)
int inum = 0;
V[infinite_vertex()] = inum++;
// finite vertices
if (is_ascii(os)) os << std::endl;
for (Finite_vertices_iterator vit = finite_vertices_begin();
vit != finite_vertices_end(); ++vit) {
V[vit] = inum++;
os << vit->site();
if ( is_ascii(os) ) { os << ' '; }
os << vit->number_of_hidden_sites();
typename Vertex::Hidden_sites_iterator hit;
for (hit = vit->hidden_sites_begin(); hit != vit->hidden_sites_end();
++hit) {
if ( is_ascii(os) ) { os << ' '; }
os << *hit;
}
// write non-combinatorial info of the vertex
// os << *vit ;
if ( is_ascii(os) ) { os << std::endl; }
}
if ( is_ascii(os) ) { os << std::endl; }
// vertices of the faces
inum = 0;
int dim = (dimension() == -1 ? 1 : dimension() + 1);
for(All_faces_iterator fit = all_faces_begin();
fit != all_faces_end(); ++fit) {
F[fit] = inum++;
for(int j = 0; j < dim ; ++j) {
os << V[ fit->vertex(j) ];
if( is_ascii(os) ) { os << ' '; }
}
// write non-combinatorial info of the face
// os << *fit ;
if( is_ascii(os) ) { os << std::endl; }
}
if( is_ascii(os) ) { os << std::endl; }
// neighbor pointers of the faces
for( All_faces_iterator it = all_faces_begin();
it != all_faces_end(); ++it) {
for(int j = 0; j < dimension()+1; ++j){
os << F[ it->neighbor(j) ];
if( is_ascii(os) ) { os << ' '; }
}
if( is_ascii(os) ) { os << std::endl; }
}
if ( is_ascii(os) ) { os << std::endl; }
}
template<class Gt, class Agds, class LTag>
void
Apollonius_graph_2<Gt,Agds,LTag>::file_input(std::istream& is)
{
//input from file
size_type n, m;
int d;
is >> n >> m >> d;
CGAL_assertion( n >= 1 );
if ( n == 1 ) {
CGAL_assertion( d == -1 );
if ( number_of_vertices() > 0 ) { clear(); }
return;
}
if ( n == 2 ) {
CGAL_assertion( d == 0 );
if ( number_of_vertices() > 0 ) { clear(); }
Site_2 s;
is >> s;
Vertex_handle v = insert(s);
unsigned int n_hidden;
is >> n_hidden;
for (unsigned int i = 0; i < n_hidden; i++) {
is >> s;
v->add_hidden_site(s);
}
return;
}
if ( n == 3 ) {
CGAL_assertion( d == 1 );
if ( number_of_vertices() > 0 ) { clear(); }
for (int j = 0; j < 2; j++) {
Site_2 s;
is >> s;
Vertex_handle v = insert(s);
unsigned int n_hidden;
is >> n_hidden;
for (unsigned int i = 0; i < n_hidden; i++) {
is >> s;
v->add_hidden_site(s);
}
}
return;
}
if (this->_tds.number_of_vertices() != 0) { this->_tds.clear(); }
this->_tds.set_dimension(d);
std::vector<Vertex_handle> V(n);
std::vector<Face_handle> F(m);
size_type i = 0;
// first vertex (infinite vertex)
V[0] = create_vertex();
this->set_infinite_vertex(V[0]);
i++;
// read vertices
for (; i < n; ++i) {
V[i] = create_vertex();
Site_2 s;
is >> s;
V[i]->set_site(s);
unsigned int n_hidden;
is >> n_hidden;
for (unsigned int j = 0; j < n_hidden; j++) {
is >> s;
V[i]->add_hidden_site(s);
}
// read non-combinatorial info of the vertex
// is >> *(V[i]);
}
// Creation of the faces
int index;
int dim = (dimension() == -1 ? 1 : dimension() + 1);
for (i = 0; i < m; ++i) {
F[i] = this->_tds.create_face();
for (int j = 0; j < dim ; ++j){
is >> index;
F[i]->set_vertex(j, V[index]);
// The face pointer of vertices is set too often,
// but otherwise we had to use a further map
V[index]->set_face(F[i]);
}
// read in non-combinatorial info of the face
// is >> *(F[i]) ;
}
// Setting the neighbor pointers
for (i = 0; i < m; ++i) {
for (int j = 0; j < dimension()+1; ++j){
is >> index;
F[i]->set_neighbor(j, F[index]);
}
}
}
CGAL_END_NAMESPACE
#endif // CGAL_APOLLONIUS_GRAPH_2_C