mirror of https://github.com/CGAL/cgal
506 lines
15 KiB
C++
506 lines
15 KiB
C++
// Copyright (c) 2003,2004,2005,2006 INRIA Sophia-Antipolis (France) and
|
|
// Notre Dame University (U.S.A.). 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: svn+ssh://scm.gforge.inria.fr/svn/cgal/trunk/Segment_Delaunay_graph_Linf_2/include/CGAL/Segment_Delaunay_graph_Linf_hierarchy_2.h $
|
|
// $Id: Segment_Delaunay_graph_Linf_hierarchy_2.h 56966 2010-06-22 10:15:50Z afabri $
|
|
//
|
|
//
|
|
// Author(s) : Menelaos Karavelas <mkaravel@cse.nd.edu>
|
|
|
|
|
|
|
|
#ifndef CGAL_SEGMENT_DELAUNAY_GRAPH_LINF_HIERARCHY_2_H
|
|
#define CGAL_SEGMENT_DELAUNAY_GRAPH_LINF_HIERARCHY_2_H
|
|
|
|
#include <map>
|
|
|
|
#include <boost/random.hpp>
|
|
#include <boost/random/linear_congruential.hpp>
|
|
#include <boost/random/geometric_distribution.hpp>
|
|
#include <boost/random/variate_generator.hpp>
|
|
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_2/basic.h>
|
|
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_2.h>
|
|
#include <CGAL/Triangulation_data_structure_2.h>
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_vertex_base_2.h>
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_hierarchy_vertex_base_2.h>
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_face_base_2.h>
|
|
|
|
|
|
namespace CGAL {
|
|
|
|
//--------------------------------------------------------------------
|
|
//--------------------------------------------------------------------
|
|
|
|
// parameterization of the hierarchy
|
|
#ifdef CGAL_SDG_HIERARCHY_DEMO
|
|
const unsigned int sdg_hierarchy_2__ratio = 3;
|
|
const unsigned int sdg_hierarchy_2__minsize = 5;
|
|
#else
|
|
const unsigned int sdg_hierarchy_2__ratio = 30;
|
|
const unsigned int sdg_hierarchy_2__minsize = 20;
|
|
#endif
|
|
const unsigned int sdg_hierarchy_2__maxlevel = 5;
|
|
// maximal number of points is 30^5 = 24 millions !
|
|
|
|
//--------------------------------------------------------------------
|
|
//--------------------------------------------------------------------
|
|
|
|
template < class Gt,
|
|
class ST = Segment_Delaunay_graph_Linf_storage_traits_2<Gt>,
|
|
class STag = Tag_false,
|
|
class D_S = Triangulation_data_structure_2<
|
|
Segment_Delaunay_graph_Linf_hierarchy_vertex_base_2<
|
|
Segment_Delaunay_graph_Linf_vertex_base_2<ST> >,
|
|
Segment_Delaunay_graph_Linf_face_base_2<Gt> >,
|
|
class LTag = Tag_false>
|
|
class Segment_Delaunay_graph_Linf_hierarchy_2
|
|
: public Segment_Delaunay_graph_Linf_2<Gt,ST,D_S,LTag>
|
|
{
|
|
protected:
|
|
typedef Segment_Delaunay_graph_Linf_hierarchy_2<Gt,ST,STag,D_S,LTag> Self;
|
|
|
|
public:
|
|
// PUBLIC TYPES
|
|
//-------------
|
|
typedef Segment_Delaunay_graph_Linf_2<Gt,ST,D_S,LTag> Base;
|
|
|
|
typedef typename Base::Geom_traits Geom_traits;
|
|
typedef typename Base::Storage_traits Storage_traits;
|
|
|
|
typedef typename Geom_traits::Point_2 Point_2;
|
|
typedef typename Geom_traits::Site_2 Site_2;
|
|
|
|
typedef typename Base::Vertex_handle Vertex_handle;
|
|
typedef typename Base::Face_handle Face_handle;
|
|
typedef typename Base::Edge Edge;
|
|
|
|
typedef typename Base::Vertex_circulator Vertex_circulator;
|
|
typedef typename Base::Edge_circulator Edge_circulator;
|
|
typedef typename Base::Face_circulator Face_circulator;
|
|
|
|
typedef typename Base::All_faces_iterator All_faces_iterator;
|
|
typedef typename Base::Finite_faces_iterator Finite_faces_iterator;
|
|
typedef typename Base::All_vertices_iterator All_vertices_iterator;
|
|
typedef typename Base::Finite_vertices_iterator Finite_vertices_iterator;
|
|
typedef typename Base::All_edges_iterator All_edges_iterator;
|
|
typedef typename Base::Finite_edges_iterator Finite_edges_iterator;
|
|
|
|
typedef typename Base::Input_sites_iterator Input_sites_iterator;
|
|
typedef typename Base::Output_sites_iterator Output_sites_iterator;
|
|
|
|
typedef typename Base::Point_handle Point_handle;
|
|
|
|
protected:
|
|
typedef typename Base::Handle_map Handle_map;
|
|
typedef typename Base::Point_handle_pair Point_handle_pair;
|
|
|
|
using Base::merge_info;
|
|
using Base::same_segments;
|
|
using Base::is_degenerate_segment;
|
|
using Base::convert_info;
|
|
using Base::second_endpoint_of_segment;
|
|
using Base::split_storage_site;
|
|
using Base::first_endpoint_of_segment;
|
|
using Base::incircle;
|
|
|
|
public:
|
|
using Base::is_infinite;
|
|
|
|
typedef typename Base::Point_container Point_container;
|
|
typedef typename Base::size_type size_type;
|
|
|
|
typedef typename Base::Intersections_tag Intersections_tag;
|
|
|
|
typedef STag Insert_segments_in_hierarchy_tag;
|
|
typedef STag Segments_in_hierarchy_tag;
|
|
|
|
protected:
|
|
// LOCAL TYPES
|
|
//------------
|
|
typedef typename Base::Storage_site_2 Storage_site_2;
|
|
typedef typename Base::List List;
|
|
typedef typename Base::Face_map Face_map;
|
|
typedef typename Base::Vertex_triple Vertex_triple;
|
|
|
|
typedef typename Base::Arrangement_type Arrangement_type;
|
|
typedef typename Base::AT2 AT2;
|
|
|
|
protected:
|
|
// LOCAL VARIABLES
|
|
//----------------
|
|
static const int UNDEFINED_LEVEL = -1;
|
|
|
|
// here is the stack of triangulations which form the hierarchy
|
|
Base* hierarchy[sdg_hierarchy_2__maxlevel];
|
|
boost::rand48 random; // random generator
|
|
public:
|
|
// CONSTRUCTORS
|
|
//-------------
|
|
Segment_Delaunay_graph_Linf_hierarchy_2(const Gt& gt = Gt());
|
|
|
|
template<class Input_iterator>
|
|
Segment_Delaunay_graph_Linf_hierarchy_2(Input_iterator first,
|
|
Input_iterator beyond,
|
|
const Gt& gt=Gt())
|
|
: Base(gt)
|
|
{
|
|
init_hierarchy(gt);
|
|
insert(first, beyond);
|
|
}
|
|
|
|
Segment_Delaunay_graph_Linf_hierarchy_2(const Self& sdg);
|
|
Self& operator=(const Self& sdg);
|
|
|
|
// DESTRUCTOR
|
|
//-----------
|
|
~Segment_Delaunay_graph_Linf_hierarchy_2();
|
|
|
|
public:
|
|
// ACCESS METHODS
|
|
//---------------
|
|
const Base& diagram(unsigned int i) const {
|
|
CGAL_precondition( i < sdg_hierarchy_2__maxlevel );
|
|
return *hierarchy[i];
|
|
}
|
|
|
|
public:
|
|
// INSERTION METHODS
|
|
//------------------
|
|
template<class Input_iterator>
|
|
size_type insert(Input_iterator first, Input_iterator beyond) {
|
|
return insert(first, beyond, Tag_false());
|
|
}
|
|
|
|
template<class Input_iterator>
|
|
size_type insert(Input_iterator first, Input_iterator beyond, Tag_true)
|
|
{
|
|
std::vector<Site_2> site_vec;
|
|
for (Input_iterator it = first; it != beyond; ++it) {
|
|
site_vec.push_back(Site_2(*it));
|
|
}
|
|
|
|
boost::random_number_generator<boost::rand48> rng(random);
|
|
std::random_shuffle(site_vec.begin(), site_vec.end(),rng);
|
|
return insert(site_vec.begin(), site_vec.end(), Tag_false());
|
|
}
|
|
|
|
template<class Input_iterator>
|
|
size_type insert(Input_iterator first, Input_iterator beyond, Tag_false)
|
|
{
|
|
// do it the obvious way: insert them as they come;
|
|
// one might think though that it might be better to first insert
|
|
// all end points and then all segments, or a variation of that.
|
|
size_type n_before = this->number_of_vertices();
|
|
for (Input_iterator it = first; it != beyond; ++it) {
|
|
insert(*it);
|
|
}
|
|
size_type n_after = this->number_of_vertices();
|
|
return n_after - n_before;
|
|
}
|
|
|
|
Vertex_handle insert(const Point_2& p) {
|
|
Point_handle ph = this->register_input_site(p);
|
|
Storage_site_2 ss =
|
|
this->st_.construct_storage_site_2_object()(ph);
|
|
return insert_point(p, ss, UNDEFINED_LEVEL);
|
|
}
|
|
|
|
Vertex_handle insert(const Point_2& p0, const Point_2& p1) {
|
|
Point_handle_pair php = this->register_input_site(p0,p1);
|
|
Storage_site_2 ss =
|
|
this->st_.construct_storage_site_2_object()(php.first, php.second);
|
|
Vertex_handle v = insert_segment(p0, p1, ss, UNDEFINED_LEVEL);
|
|
if ( v == Vertex_handle() ) {
|
|
this->unregister_input_site( php.first, php.second );
|
|
}
|
|
return v;
|
|
}
|
|
|
|
Vertex_handle insert(const Vertex_handle& v0, const Vertex_handle& v1) {
|
|
return hierarchy[0]->insert(v0, v1);
|
|
}
|
|
|
|
Vertex_handle insert(const Point_2& p, Vertex_handle) {
|
|
return insert(p);
|
|
}
|
|
|
|
Vertex_handle insert(const Point_2& p0, const Point_2& p1,
|
|
Vertex_handle) {
|
|
return insert(p0, p1);
|
|
}
|
|
|
|
Vertex_handle insert(const Site_2& t) {
|
|
// the intended use is to unify the calls to insert(...);
|
|
// thus the site must be an exact one;
|
|
CGAL_precondition( t.is_input() );
|
|
|
|
if ( t.is_segment() ) {
|
|
Point_handle_pair php =
|
|
this->register_input_site(t.source(), t.target());
|
|
Storage_site_2 ss =
|
|
this->st_.construct_storage_site_2_object()(php.first, php.second);
|
|
Vertex_handle v =
|
|
insert_segment(t.source(), t.target(), ss, UNDEFINED_LEVEL);
|
|
if ( v == Vertex_handle() ) {
|
|
this->unregister_input_site( php.first, php.second );
|
|
}
|
|
return v;
|
|
} else if ( t.is_point() ) {
|
|
Point_handle ph = this->register_input_site( t.point() );
|
|
Storage_site_2 ss = this->st_.construct_storage_site_2_object()(ph);
|
|
return insert_point(t.point(), ss, UNDEFINED_LEVEL);
|
|
} else {
|
|
CGAL_precondition ( t.is_defined() );
|
|
return Vertex_handle(); // to avoid compiler error
|
|
}
|
|
}
|
|
|
|
inline Vertex_handle insert(const Site_2& t, Vertex_handle) {
|
|
return insert(t);
|
|
}
|
|
|
|
template<class Info_t>
|
|
inline
|
|
Vertex_handle insert(const Site_2& t, const Info_t& info)
|
|
{
|
|
typedef typename Storage_traits::Info Info;
|
|
CGAL_SEGMENT_DELAUNAY_GRAPH_LINF_2_NS::Internal::
|
|
Check_type_equality_for_info<Info_t, Info>();
|
|
// the intended use is to unify the calls to insert(...);
|
|
// thus the site must be an exact one;
|
|
CGAL_precondition( t.is_input() );
|
|
|
|
if ( t.is_segment() ) {
|
|
Point_handle_pair php =
|
|
this->register_input_site(t.source(), t.target());
|
|
Storage_site_2 ss =
|
|
this->st_.construct_storage_site_2_object()(php.first, php.second);
|
|
ss.set_info(info);
|
|
Vertex_handle v =
|
|
insert_segment(t.source(), t.target(), ss, UNDEFINED_LEVEL);
|
|
if ( v == Vertex_handle() ) {
|
|
this->unregister_input_site( php.first, php.second );
|
|
}
|
|
return v;
|
|
} else if ( t.is_point() ) {
|
|
Point_handle ph = this->register_input_site( t.point() );
|
|
Storage_site_2 ss = this->st_.construct_storage_site_2_object()(ph);
|
|
ss.set_info(info);
|
|
return insert_point(t.point(), ss, UNDEFINED_LEVEL);
|
|
} else {
|
|
CGAL_precondition ( t.is_defined() );
|
|
return Vertex_handle(); // to avoid compiler error
|
|
}
|
|
}
|
|
|
|
template<class Info_t>
|
|
inline
|
|
Vertex_handle insert(const Site_2& t, const Info_t& info, Vertex_handle)
|
|
{
|
|
return insert(t, info);
|
|
}
|
|
|
|
protected:
|
|
Vertex_handle insert_point(const Point_2& p, const Storage_site_2& ss,
|
|
int level) {
|
|
if ( level == UNDEFINED_LEVEL ) {
|
|
level = random_level();
|
|
}
|
|
|
|
Vertex_handle vertices[sdg_hierarchy_2__maxlevel];
|
|
|
|
insert_point(p, ss, level, vertices);
|
|
|
|
return vertices[0];
|
|
}
|
|
|
|
// std::pair<bool,Vertex_triple>
|
|
std::pair<bool,int>
|
|
insert_point(const Point_2& p, const Storage_site_2& ss,
|
|
int level, Vertex_handle* vertices);
|
|
|
|
void insert_point(const Site_2& t, const Storage_site_2& ss,
|
|
int low, int high, Vertex_handle vbelow,
|
|
Vertex_handle* vertices);
|
|
|
|
Vertex_handle insert_segment(const Point_2& p0, const Point_2& p1,
|
|
const Storage_site_2& ss, int level);
|
|
|
|
Vertex_handle insert_segment_interior(const Site_2& t,
|
|
const Storage_site_2& ss,
|
|
const Vertex_handle* vertices0,
|
|
int level);
|
|
|
|
void insert_segment_in_upper_levels(const Site_2& t,
|
|
const Storage_site_2& ss,
|
|
Vertex_handle vbelow,
|
|
const Vertex_handle* vertices0,
|
|
int level, Tag_true);
|
|
|
|
void insert_segment_in_upper_levels(const Site_2& ,
|
|
const Storage_site_2& ,
|
|
Vertex_handle ,
|
|
const Vertex_handle* ,
|
|
int , Tag_false) {}
|
|
|
|
Vertex_handle insert_segment_on_point(const Storage_site_2& ss,
|
|
const Vertex_handle& v,
|
|
int level, int which);
|
|
|
|
template<class Tag>
|
|
Vertex_handle
|
|
insert_intersecting_segment_with_tag(const Storage_site_2&,
|
|
const Site_2& ,
|
|
Vertex_handle ,
|
|
int , Tag_false /* itag */, Tag) {
|
|
#if defined(__POWERPC__) && \
|
|
defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ == 4)
|
|
// hack to avoid nasty warning for G++ 3.4 on Darwin
|
|
static int i;
|
|
#else
|
|
static int i = 0;
|
|
#endif
|
|
if ( i == 0 ) {
|
|
i = 1;
|
|
print_error_message();
|
|
}
|
|
return Vertex_handle();
|
|
}
|
|
|
|
Vertex_handle
|
|
insert_intersecting_segment_with_tag(const Storage_site_2& ss,
|
|
const Site_2& t,
|
|
Vertex_handle v,
|
|
int level,
|
|
Tag_true itag, Tag_false stag);
|
|
|
|
Vertex_handle
|
|
insert_intersecting_segment_with_tag(const Storage_site_2& ss,
|
|
const Site_2& t,
|
|
Vertex_handle v,
|
|
int level,
|
|
Tag_true itag, Tag_true stag);
|
|
|
|
public:
|
|
// REMOVAL METHODS
|
|
//----------------
|
|
bool remove(const Vertex_handle& v);
|
|
|
|
public:
|
|
// NEAREST NEIGHBOR LOCATION
|
|
//--------------------------
|
|
Vertex_handle nearest_neighbor(const Point_2& p,
|
|
bool force_point = false) const;
|
|
|
|
Vertex_handle nearest_neighbor(const Point_2& p, Vertex_handle)
|
|
{
|
|
return nearest_neighbor(p);
|
|
}
|
|
|
|
protected:
|
|
void nearest_neighbor(const Site_2& p,
|
|
Vertex_handle vnear[sdg_hierarchy_2__maxlevel],
|
|
bool force_point) const;
|
|
|
|
public:
|
|
// MISCELLANEOUS
|
|
//--------------
|
|
void init_hierarchy(const Geom_traits& gt);
|
|
|
|
void copy(const Segment_Delaunay_graph_Linf_hierarchy_2& sdgh);
|
|
|
|
void swap(Segment_Delaunay_graph_Linf_hierarchy_2& sdgh);
|
|
void clear();
|
|
|
|
public:
|
|
// FILE I/O
|
|
//---------
|
|
void file_input(std::istream&);
|
|
void file_output(std::ostream&) const;
|
|
|
|
public:
|
|
// VALIDITY CHECK
|
|
//---------------
|
|
bool is_valid(bool verbose = false, int level = 1) const;
|
|
|
|
protected:
|
|
// LOCAL HELPER METHODS
|
|
//---------------------
|
|
int random_level() {
|
|
boost::geometric_distribution<> proba(1.0/sdg_hierarchy_2__ratio);
|
|
boost::variate_generator<boost::rand48&, boost::geometric_distribution<> > die(random, proba);
|
|
|
|
return (std::min)(die(), (int)sdg_hierarchy_2__maxlevel)-1;
|
|
}
|
|
|
|
int find_level(Vertex_handle v) const {
|
|
CGAL_precondition( v != Vertex_handle() );
|
|
int level = 0;
|
|
Vertex_handle vertex = v;
|
|
while ( vertex->up() != Vertex_handle() ) {
|
|
vertex = vertex->up();
|
|
level++;
|
|
}
|
|
|
|
return level;
|
|
}
|
|
|
|
Vertex_handle
|
|
vertex_at_level(const Vertex_handle& v, int k) const
|
|
{
|
|
CGAL_precondition( k <= sdg_hierarchy_2__maxlevel );
|
|
|
|
int level = 0;
|
|
Vertex_handle v_at_level = v;
|
|
while ( level < k ) {
|
|
v_at_level = v_at_level->up();
|
|
level++;
|
|
}
|
|
return v_at_level;
|
|
}
|
|
|
|
void print_error_message() const;
|
|
};
|
|
|
|
|
|
|
|
template<class Gt, class STag, class D_S, class LTag>
|
|
std::istream& operator>>(std::istream& is,
|
|
Segment_Delaunay_graph_Linf_hierarchy_2<Gt,STag,D_S,LTag>&
|
|
sdgh)
|
|
{
|
|
sdgh.file_input(is);
|
|
return is;
|
|
}
|
|
|
|
template<class Gt, class STag, class D_S, class LTag>
|
|
std::ostream& operator<<(std::ostream& os,
|
|
const
|
|
Segment_Delaunay_graph_Linf_hierarchy_2<Gt,STag,D_S,LTag>&
|
|
sdgh)
|
|
{
|
|
sdgh.file_output(os);
|
|
return os;
|
|
}
|
|
|
|
|
|
} //namespace CGAL
|
|
|
|
|
|
#include <CGAL/Segment_Delaunay_graph_Linf_2/Segment_Delaunay_graph_Linf_hierarchy_2_impl.h>
|
|
|
|
|
|
#endif // CGAL_SEGMENT_DELAUNAY_GRAPH_LINF_HIERARCHY_2_H
|