mirror of https://github.com/CGAL/cgal
Merge branch 'Tangential_complex-cjamin-old' into Tangential_complex-cjamin
This commit is contained in:
commit
4958fcc746
|
|
@ -2651,7 +2651,7 @@ rebuild_restricted_delaunay(OutdatedCells& outdated_cells,
|
||||||
|
|
||||||
# ifdef CGAL_MESH_3_PROFILING
|
# ifdef CGAL_MESH_3_PROFILING
|
||||||
std::cerr << std::endl << " Updating cells...";
|
std::cerr << std::endl << " Updating cells...";
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
size_t num_cells = c3t3_.number_of_cells_in_complex();
|
size_t num_cells = c3t3_.number_of_cells_in_complex();
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ private:
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
std::cerr << "Computing moves...";
|
std::cerr << "Computing moves...";
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -688,7 +688,7 @@ operator()(int nb_iterations, Visitor visitor)
|
||||||
running_time_.start();
|
running_time_.start();
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fill set containing moving vertices
|
// Fill set containing moving vertices
|
||||||
|
|
@ -899,7 +899,7 @@ update_mesh(const Moves_vector& moves,
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
std::cerr << "Moving vertices...";
|
std::cerr << "Moving vertices...";
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,7 @@ Mesher_3<C3T3,MC,MD>::refine_mesh(std::string dump_after_refine_surface_prefix)
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
std::cerr << "Refining facets..." << std::endl;
|
std::cerr << "Refining facets..." << std::endl;
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
facets_mesher_.refine(facets_visitor_);
|
facets_mesher_.refine(facets_visitor_);
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
|
|
@ -481,7 +481,7 @@ initialize()
|
||||||
{
|
{
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
std::cerr << "Initializing... ";
|
std::cerr << "Initializing... ";
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
//=====================================
|
//=====================================
|
||||||
// Bounding box estimation
|
// Bounding box estimation
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ protected:
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
protected:
|
protected:
|
||||||
WallClockTimer m_timer;
|
Wall_clock_timer m_timer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@
|
||||||
// TBB timers
|
// TBB timers
|
||||||
#ifdef CGAL_LINKED_WITH_TBB
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
#include <tbb/tick_count.h>
|
#include <tbb/tick_count.h>
|
||||||
struct WallClockTimer
|
struct Wall_clock_timer
|
||||||
{
|
{
|
||||||
tbb::tick_count t;
|
tbb::tick_count t;
|
||||||
WallClockTimer()
|
Wall_clock_timer()
|
||||||
{
|
{
|
||||||
t = tbb::tick_count::now();
|
t = tbb::tick_count::now();
|
||||||
}
|
}
|
||||||
|
|
@ -48,10 +48,10 @@
|
||||||
#else
|
#else
|
||||||
#include <CGAL/Real_timer.h>
|
#include <CGAL/Real_timer.h>
|
||||||
|
|
||||||
struct WallClockTimer
|
struct Wall_clock_timer
|
||||||
{
|
{
|
||||||
CGAL::Real_timer t;
|
CGAL::Real_timer t;
|
||||||
WallClockTimer()
|
Wall_clock_timer()
|
||||||
{
|
{
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -632,7 +632,7 @@ scan_triangulation_impl()
|
||||||
typedef typename Tr::Finite_cells_iterator Finite_cell_iterator;
|
typedef typename Tr::Finite_cells_iterator Finite_cell_iterator;
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -930,7 +930,7 @@ scan_triangulation_impl()
|
||||||
typedef typename Tr::Finite_facets_iterator Finite_facet_iterator;
|
typedef typename Tr::Finite_facets_iterator Finite_facet_iterator;
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_VERY_VERBOSE
|
#ifdef CGAL_MESH_3_VERY_VERBOSE
|
||||||
|
|
|
||||||
|
|
@ -797,7 +797,7 @@ operator()(Visitor visitor)
|
||||||
running_time_.start();
|
running_time_.start();
|
||||||
|
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Build priority queue (we use one queue for all steps)
|
// Build priority queue (we use one queue for all steps)
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ public: // methods
|
||||||
operator()(Visitor visitor = Visitor())
|
operator()(Visitor visitor = Visitor())
|
||||||
{
|
{
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Mesh_optimization_return_code ret =
|
Mesh_optimization_return_code ret =
|
||||||
|
|
@ -964,7 +964,7 @@ pump_vertices(double sliver_criterion_limit,
|
||||||
Visitor& visitor)
|
Visitor& visitor)
|
||||||
{
|
{
|
||||||
#ifdef CGAL_MESH_3_PROFILING
|
#ifdef CGAL_MESH_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init(sliver_criterion_limit);
|
init(sliver_criterion_limit);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright (c) 2014
|
||||||
|
// INRIA Saclay-Ile de France (France)
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 3 of the License,
|
||||||
|
// or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Marc Glisse
|
||||||
|
|
||||||
|
#ifndef CGAL_EPECK_D_H
|
||||||
|
#define CGAL_EPECK_D_H
|
||||||
|
#include <CGAL/NewKernel_d/Cartesian_base.h>
|
||||||
|
#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h>
|
||||||
|
#include <CGAL/NewKernel_d/Kernel_d_interface.h>
|
||||||
|
#include <CGAL/internal/Exact_type_selector.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
#define CGAL_BASE \
|
||||||
|
Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim>
|
||||||
|
template<class Dim>
|
||||||
|
struct Epeck_d_help1
|
||||||
|
: CGAL_BASE
|
||||||
|
{
|
||||||
|
CGAL_CONSTEXPR Epeck_d_help1(){}
|
||||||
|
CGAL_CONSTEXPR Epeck_d_help1(int d):CGAL_BASE(d){}
|
||||||
|
};
|
||||||
|
#undef CGAL_BASE
|
||||||
|
#define CGAL_BASE \
|
||||||
|
Kernel_d_interface< \
|
||||||
|
Cartesian_wrap< \
|
||||||
|
Epeck_d_help1<Dim>, \
|
||||||
|
Epeck_d<Dim> > >
|
||||||
|
template<class Dim>
|
||||||
|
struct Epeck_d
|
||||||
|
: CGAL_BASE
|
||||||
|
{
|
||||||
|
CGAL_CONSTEXPR Epeck_d(){}
|
||||||
|
CGAL_CONSTEXPR Epeck_d(int d):CGAL_BASE(d){}
|
||||||
|
};
|
||||||
|
#undef CGAL_BASE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -30,7 +30,7 @@ namespace CGAL {
|
||||||
|
|
||||||
template < typename Base_, typename AK_, typename EK_ >
|
template < typename Base_, typename AK_, typename EK_ >
|
||||||
struct Cartesian_filter_K : public Base_,
|
struct Cartesian_filter_K : public Base_,
|
||||||
private Store_kernel<AK_>, private Store_kernel2<EK_>
|
private Store_kernel<AK_>, private Store_kernel2<EK_>
|
||||||
{
|
{
|
||||||
CGAL_CONSTEXPR Cartesian_filter_K(){}
|
CGAL_CONSTEXPR Cartesian_filter_K(){}
|
||||||
CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){}
|
CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){}
|
||||||
|
|
@ -61,11 +61,11 @@ struct Cartesian_filter_K : public Base_,
|
||||||
template<class T> struct Type : Get_type<Kernel_base,T> {};
|
template<class T> struct Type : Get_type<Kernel_base,T> {};
|
||||||
|
|
||||||
template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_K,T>::type> struct Functor :
|
template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_K,T>::type> struct Functor :
|
||||||
Inherit_functor<Kernel_base,T,D> {};
|
Inherit_functor<Kernel_base,T,D> {};
|
||||||
template<class T,class D> struct Functor<T,D,Predicate_tag> {
|
template<class T,class D> struct Functor<T,D,Predicate_tag> {
|
||||||
typedef typename Get_functor<AK, T>::type AP;
|
typedef typename Get_functor<AK, T>::type AP;
|
||||||
typedef typename Get_functor<EK, T>::type EP;
|
typedef typename Get_functor<EK, T>::type EP;
|
||||||
typedef Filtered_predicate2<EP,AP,C2E,C2A> type;
|
typedef Filtered_predicate2<EP,AP,C2E,C2A> type;
|
||||||
};
|
};
|
||||||
// TODO:
|
// TODO:
|
||||||
// template<class T> struct Functor<T,No_filter_tag,Predicate_tag> :
|
// template<class T> struct Functor<T,No_filter_tag,Predicate_tag> :
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ template <class Base_> struct Kernel_d_interface : public Base_ {
|
||||||
typedef typename Get_functor<Base, Point_dimension_tag>::type Point_dimension_d;
|
typedef typename Get_functor<Base, Point_dimension_tag>::type Point_dimension_d;
|
||||||
typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type Side_of_oriented_sphere_d;
|
typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type Side_of_oriented_sphere_d;
|
||||||
typedef typename Get_functor<Base, Power_side_of_power_sphere_tag>::type Power_side_of_power_sphere_d;
|
typedef typename Get_functor<Base, Power_side_of_power_sphere_tag>::type Power_side_of_power_sphere_d;
|
||||||
|
typedef typename Get_functor<Base, Power_center_tag>::type Power_center_d;
|
||||||
|
typedef typename Get_functor<Base, Power_distance_tag>::type Power_distance_d;
|
||||||
typedef typename Get_functor<Base, Contained_in_affine_hull_tag>::type Contained_in_affine_hull_d;
|
typedef typename Get_functor<Base, Contained_in_affine_hull_tag>::type Contained_in_affine_hull_d;
|
||||||
typedef typename Get_functor<Base, Construct_flat_orientation_tag>::type Construct_flat_orientation_d;
|
typedef typename Get_functor<Base, Construct_flat_orientation_tag>::type Construct_flat_orientation_d;
|
||||||
typedef typename Get_functor<Base, In_flat_orientation_tag>::type In_flat_orientation_d;
|
typedef typename Get_functor<Base, In_flat_orientation_tag>::type In_flat_orientation_d;
|
||||||
|
|
@ -73,6 +75,7 @@ template <class Base_> struct Kernel_d_interface : public Base_ {
|
||||||
typedef typename Get_functor<Base, In_flat_power_side_of_power_sphere_tag>::type In_flat_power_side_of_power_sphere_d;
|
typedef typename Get_functor<Base, In_flat_power_side_of_power_sphere_tag>::type In_flat_power_side_of_power_sphere_d;
|
||||||
typedef typename Get_functor<Base, Point_to_vector_tag>::type Point_to_vector_d;
|
typedef typename Get_functor<Base, Point_to_vector_tag>::type Point_to_vector_d;
|
||||||
typedef typename Get_functor<Base, Vector_to_point_tag>::type Vector_to_point_d;
|
typedef typename Get_functor<Base, Vector_to_point_tag>::type Vector_to_point_d;
|
||||||
|
typedef typename Get_functor<Base, Translated_point_tag>::type Translated_point_d;
|
||||||
typedef typename Get_functor<Base, Scaled_vector_tag>::type Scaled_vector_d;
|
typedef typename Get_functor<Base, Scaled_vector_tag>::type Scaled_vector_d;
|
||||||
typedef typename Get_functor<Base, Difference_of_vectors_tag>::type Difference_of_vectors_d;
|
typedef typename Get_functor<Base, Difference_of_vectors_tag>::type Difference_of_vectors_d;
|
||||||
typedef typename Get_functor<Base, Difference_of_points_tag>::type Difference_of_points_d;
|
typedef typename Get_functor<Base, Difference_of_points_tag>::type Difference_of_points_d;
|
||||||
|
|
@ -188,6 +191,8 @@ template <class Base_> struct Kernel_d_interface : public Base_ {
|
||||||
Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); }
|
Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); }
|
||||||
Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); }
|
Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); }
|
||||||
Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); }
|
Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); }
|
||||||
|
Power_center_d power_center_d_object()const{ return Power_center_d(*this); }
|
||||||
|
Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); }
|
||||||
Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); }
|
Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); }
|
||||||
Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); }
|
Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); }
|
||||||
Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); }
|
Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); }
|
||||||
|
|
@ -198,6 +203,7 @@ template <class Base_> struct Kernel_d_interface : public Base_ {
|
||||||
In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object()const{ return In_flat_power_side_of_power_sphere_d(*this); }
|
In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object()const{ return In_flat_power_side_of_power_sphere_d(*this); }
|
||||||
Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); }
|
Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); }
|
||||||
Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); }
|
Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); }
|
||||||
|
Translated_point_d translated_point_d_object()const{ return Translated_point_d(*this); }
|
||||||
Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); }
|
Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); }
|
||||||
Difference_of_vectors_d difference_of_vectors_d_object()const{ return Difference_of_vectors_d(*this); }
|
Difference_of_vectors_d difference_of_vectors_d_object()const{ return Difference_of_vectors_d(*this); }
|
||||||
Difference_of_points_d difference_of_points_d_object()const{ return Difference_of_points_d(*this); }
|
Difference_of_points_d difference_of_points_d_object()const{ return Difference_of_points_d(*this); }
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ template <class R_> struct Construct_sphere : Store_kernel<R_> {
|
||||||
}
|
}
|
||||||
template <class Iter>
|
template <class Iter>
|
||||||
result_type operator()(Iter f, Iter e)const{
|
result_type operator()(Iter f, Iter e)const{
|
||||||
typedef typename Get_type<R_, Point_tag>::type Point;
|
|
||||||
typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel());
|
typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel());
|
||||||
typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
|
typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,33 @@ template <class R_> struct Point_weight {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class R_> struct Power_distance : private Store_kernel<R_> {
|
||||||
|
CGAL_FUNCTOR_INIT_STORE(Power_distance)
|
||||||
|
typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type;
|
||||||
|
typedef first_argument_type second_argument_type;
|
||||||
|
typedef typename Get_type<R_, FT_tag>::type result_type;
|
||||||
|
|
||||||
|
result_type operator()(first_argument_type const&a, second_argument_type const&b)const{
|
||||||
|
typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
|
||||||
|
typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
|
||||||
|
typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
|
||||||
|
return sd(pdw(a),pdw(b))-pw(a)-pw(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <class R_> struct Power_distance_to_point : private Store_kernel<R_> {
|
||||||
|
CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point)
|
||||||
|
typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type;
|
||||||
|
typedef typename Get_type<R_, Point_tag>::type second_argument_type;
|
||||||
|
typedef typename Get_type<R_, FT_tag>::type result_type;
|
||||||
|
|
||||||
|
result_type operator()(first_argument_type const&a, second_argument_type const&b)const{
|
||||||
|
typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
|
||||||
|
typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
|
||||||
|
typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel());
|
||||||
|
return sd(pdw(a),b)-pw(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class R_> struct Power_side_of_power_sphere : private Store_kernel<R_> {
|
template<class R_> struct Power_side_of_power_sphere : private Store_kernel<R_> {
|
||||||
CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere)
|
CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere)
|
||||||
typedef R_ R;
|
typedef R_ R;
|
||||||
|
|
@ -114,6 +141,56 @@ template<class R_> struct In_flat_power_side_of_power_sphere : private Store_ker
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Construct a point at (weighted) distance 0 from all the input
|
||||||
|
template <class R_> struct Power_center : Store_kernel<R_> {
|
||||||
|
CGAL_FUNCTOR_INIT_STORE(Power_center)
|
||||||
|
typedef typename Get_type<R_, Weighted_point_tag>::type WPoint;
|
||||||
|
typedef WPoint result_type;
|
||||||
|
typedef typename Get_type<R_, Point_tag>::type Point;
|
||||||
|
typedef typename Get_type<R_, FT_tag>::type FT;
|
||||||
|
template <class Iter>
|
||||||
|
result_type operator()(Iter f, Iter e)const{
|
||||||
|
// 2*(x-y).c == (x^2-wx^2)-(y^2-wy^2)
|
||||||
|
typedef typename R_::LA LA;
|
||||||
|
typedef typename LA::Square_matrix Matrix;
|
||||||
|
typedef typename LA::Vector Vec;
|
||||||
|
typedef typename LA::Construct_vector CVec;
|
||||||
|
typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel());
|
||||||
|
typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel());
|
||||||
|
typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel());
|
||||||
|
typename Get_functor<R_, Squared_distance_to_origin_tag>::type sdo(this->kernel());
|
||||||
|
typename Get_functor<R_, Power_distance_to_point_tag>::type pdp(this->kernel());
|
||||||
|
typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel());
|
||||||
|
typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel());
|
||||||
|
typename Get_functor<R_, Construct_ttag<Weighted_point_tag> >::type cwp(this->kernel());
|
||||||
|
|
||||||
|
WPoint const& wp0 = *f;
|
||||||
|
Point const& p0 = pdw(wp0);
|
||||||
|
int d = pd(p0);
|
||||||
|
FT const& n0 = sdo(p0) - pw(wp0);
|
||||||
|
Matrix m(d,d);
|
||||||
|
Vec b = typename CVec::Dimension()(d);
|
||||||
|
// Write the point coordinates in lines.
|
||||||
|
int i;
|
||||||
|
for(i=0; ++f!=e; ++i) {
|
||||||
|
WPoint const& wp=*f;
|
||||||
|
Point const& p=pdw(wp);
|
||||||
|
FT const& np = sdo(p) - pw(wp);
|
||||||
|
for(int j=0;j<d;++j) {
|
||||||
|
m(i,j)=2*(c(p,j)-c(p0,j));
|
||||||
|
b[i] = np - n0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CGAL_assertion (i == d);
|
||||||
|
Vec res = typename CVec::Dimension()(d);;
|
||||||
|
//std::cout << "Mat: " << m << "\n Vec: " << one << std::endl;
|
||||||
|
LA::solve(res, CGAL_MOVE(m), CGAL_MOVE(b));
|
||||||
|
//std::cout << "Sol: " << res << std::endl;
|
||||||
|
Point center = cp(d,LA::vector_begin(res),LA::vector_end(res));
|
||||||
|
FT const& r2 = pdp (wp0, center);
|
||||||
|
return cwp(CGAL_MOVE(center), r2);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point<K>),(Point_tag),());
|
CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point<K>),(Point_tag),());
|
||||||
CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Weighted_point_tag>,(CartesianDKernelFunctors::Construct_weighted_point<K>),(Weighted_point_tag,Point_tag),());
|
CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Weighted_point_tag>,(CartesianDKernelFunctors::Construct_weighted_point<K>),(Weighted_point_tag,Point_tag),());
|
||||||
|
|
@ -121,5 +198,8 @@ CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_d
|
||||||
CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight<K>),(Weighted_point_tag,Point_tag),());
|
CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight<K>),(Weighted_point_tag,Point_tag),());
|
||||||
CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere<K>),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
|
CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere<K>),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
|
||||||
CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere<K>),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
|
CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere<K>),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag));
|
||||||
|
CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag));
|
||||||
|
CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag));
|
||||||
|
CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center<K>),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag<Point_tag>,Construct_ttag<Weighted_point_tag>,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag));
|
||||||
} // namespace CGAL
|
} // namespace CGAL
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,8 @@ namespace CGAL {
|
||||||
CGAL_DECL_COMPUTE(Hyperplane_translation);
|
CGAL_DECL_COMPUTE(Hyperplane_translation);
|
||||||
CGAL_DECL_COMPUTE(Value_at);
|
CGAL_DECL_COMPUTE(Value_at);
|
||||||
CGAL_DECL_COMPUTE(Point_weight);
|
CGAL_DECL_COMPUTE(Point_weight);
|
||||||
|
CGAL_DECL_COMPUTE(Power_distance);
|
||||||
|
CGAL_DECL_COMPUTE(Power_distance_to_point);
|
||||||
#undef CGAL_DECL_COMPUTE
|
#undef CGAL_DECL_COMPUTE
|
||||||
|
|
||||||
#define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \
|
#define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \
|
||||||
|
|
@ -269,6 +271,7 @@ namespace CGAL {
|
||||||
CGAL_DECL_CONSTRUCT(Construct_max_vertex,Point);
|
CGAL_DECL_CONSTRUCT(Construct_max_vertex,Point);
|
||||||
CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point);
|
CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point);
|
||||||
CGAL_DECL_CONSTRUCT(Point_drop_weight,Point);
|
CGAL_DECL_CONSTRUCT(Point_drop_weight,Point);
|
||||||
|
CGAL_DECL_CONSTRUCT(Power_center,Weighted_point);
|
||||||
#undef CGAL_DECL_CONSTRUCT
|
#undef CGAL_DECL_CONSTRUCT
|
||||||
#if 0
|
#if 0
|
||||||
#define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \
|
#define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ int main()
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <CGAL/NewKernel_d/Types/Weighted_point.h>
|
#include <CGAL/NewKernel_d/Types/Weighted_point.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
//typedef CGAL::Cartesian_base_d<double,CGAL::Dimension_tag<2> > K0;
|
//typedef CGAL::Cartesian_base_d<double,CGAL::Dimension_tag<2> > K0;
|
||||||
//typedef CGAL::Cartesian_base_d<CGAL::Interval_nt_advanced,CGAL::Dimension_tag<2> > KA;
|
//typedef CGAL::Cartesian_base_d<CGAL::Interval_nt_advanced,CGAL::Dimension_tag<2> > KA;
|
||||||
|
|
@ -84,6 +85,7 @@ void test2(){
|
||||||
typedef typename K1::Ray_d R;
|
typedef typename K1::Ray_d R;
|
||||||
typedef typename K1::Iso_box_d IB;
|
typedef typename K1::Iso_box_d IB;
|
||||||
typedef typename K1::Flat_orientation_d FO;
|
typedef typename K1::Flat_orientation_d FO;
|
||||||
|
typedef typename K1::Weighted_point_d WP;
|
||||||
|
|
||||||
//typedef K1::Construct_point CP;
|
//typedef K1::Construct_point CP;
|
||||||
typedef typename K1::Construct_point_d CP;
|
typedef typename K1::Construct_point_d CP;
|
||||||
|
|
@ -135,6 +137,13 @@ void test2(){
|
||||||
typedef typename K1::Construct_min_vertex_d CmV;
|
typedef typename K1::Construct_min_vertex_d CmV;
|
||||||
typedef typename K1::Construct_max_vertex_d CMV;
|
typedef typename K1::Construct_max_vertex_d CMV;
|
||||||
typedef typename K1::Compute_squared_radius_d SR;
|
typedef typename K1::Compute_squared_radius_d SR;
|
||||||
|
typedef typename K1::Translated_point_d TP;
|
||||||
|
typedef typename K1::Power_center_d PC;
|
||||||
|
typedef typename K1::Power_distance_d PoD;
|
||||||
|
typedef typename K1::Weighted_point_d WP;
|
||||||
|
typedef typename K1::Construct_weighted_point_d CWP;
|
||||||
|
typedef typename K1::Point_drop_weight_d PDW;
|
||||||
|
typedef typename K1::Point_weight_d PW;
|
||||||
|
|
||||||
CGAL_USE_TYPE(AT);
|
CGAL_USE_TYPE(AT);
|
||||||
CGAL_USE_TYPE(D);
|
CGAL_USE_TYPE(D);
|
||||||
|
|
@ -196,6 +205,12 @@ void test2(){
|
||||||
CmV cmv Kinit(construct_min_vertex_d_object);
|
CmV cmv Kinit(construct_min_vertex_d_object);
|
||||||
CMV cMv Kinit(construct_max_vertex_d_object);
|
CMV cMv Kinit(construct_max_vertex_d_object);
|
||||||
SR sr Kinit(compute_squared_radius_d_object);
|
SR sr Kinit(compute_squared_radius_d_object);
|
||||||
|
TP tp Kinit(translated_point_d_object);
|
||||||
|
PC pc Kinit(power_center_d_object);
|
||||||
|
CWP cwp Kinit(construct_weighted_point_d_object);
|
||||||
|
PDW pdw Kinit(point_drop_weight_d_object);
|
||||||
|
PW pw Kinit(point_weight_d_object);
|
||||||
|
PoD pod Kinit(power_distance_d_object);
|
||||||
|
|
||||||
CGAL_USE(bc);
|
CGAL_USE(bc);
|
||||||
CGAL_USE(pol);
|
CGAL_USE(pol);
|
||||||
|
|
@ -203,11 +218,12 @@ void test2(){
|
||||||
CGAL_USE(cd);
|
CGAL_USE(cd);
|
||||||
CGAL_USE(cli);
|
CGAL_USE(cli);
|
||||||
CGAL_USE(cr);
|
CGAL_USE(cr);
|
||||||
|
using std::abs;
|
||||||
P a=cp(3,4);
|
P a=cp(3,4);
|
||||||
assert(pd(a)==2);
|
assert(pd(a)==2);
|
||||||
assert(pv(a)[1]==4);
|
assert(pv(a)[1]==4);
|
||||||
P b=vp(cv(5,6,7));
|
P b=vp(cv(5,6,7));
|
||||||
assert(fabs(b[0]-5./7)<.0001);
|
assert(abs(b[0]-5./7)<.0001);
|
||||||
assert(lc(b,a,1));
|
assert(lc(b,a,1));
|
||||||
assert(!lc(a,b,0));
|
assert(!lc(a,b,0));
|
||||||
int rr[]={3,5,2};
|
int rr[]={3,5,2};
|
||||||
|
|
@ -221,8 +237,8 @@ void test2(){
|
||||||
assert(cl(a,c)==CGAL::SMALLER);
|
assert(cl(a,c)==CGAL::SMALLER);
|
||||||
assert(ll(b,c));
|
assert(ll(b,c));
|
||||||
assert(cl(c,b)==CGAL::LARGER);
|
assert(cl(c,b)==CGAL::LARGER);
|
||||||
assert(fabs(m(a,c)[0]-3)<.0001);
|
assert(abs(m(a,c)[0]-3)<.0001);
|
||||||
assert(fabs(m(a,c)[1]-4.5)<.0001);
|
assert(abs(m(a,c)[1]-4.5)<.0001);
|
||||||
P d=cp(r,r+3,CGAL::Homogeneous_tag());
|
P d=cp(r,r+3,CGAL::Homogeneous_tag());
|
||||||
S s=cs(c,d);
|
S s=cs(c,d);
|
||||||
std::cout << cc(a,1) << std::endl;
|
std::cout << cc(a,1) << std::endl;
|
||||||
|
|
@ -277,9 +293,9 @@ void test2(){
|
||||||
assert(v.size()==1);
|
assert(v.size()==1);
|
||||||
assert(lr(tab3+0,tab3+2)==1);
|
assert(lr(tab3+0,tab3+2)==1);
|
||||||
H h=ch(tab2+1,tab2+3,tab2[0]);
|
H h=ch(tab2+1,tab2+3,tab2[0]);
|
||||||
assert(fabs(va(h,x2)-1)<.0001);
|
assert(abs(va(h,x2)-1)<.0001);
|
||||||
assert(fabs(va(h,x3)-1)<.0001);
|
assert(abs(va(h,x3)-1)<.0001);
|
||||||
assert(fabs(va(h,x1)+1)<.0001);
|
assert(abs(va(h,x1)+1)<.0001);
|
||||||
H h2=ch(tab2+1,tab2+3,x1,CGAL::ON_POSITIVE_SIDE);
|
H h2=ch(tab2+1,tab2+3,x1,CGAL::ON_POSITIVE_SIDE);
|
||||||
assert(hops(h2,x1));
|
assert(hops(h2,x1));
|
||||||
assert(os(h2,x1)==CGAL::ON_POSITIVE_SIDE);
|
assert(os(h2,x1)==CGAL::ON_POSITIVE_SIDE);
|
||||||
|
|
@ -340,20 +356,35 @@ void test2(){
|
||||||
Sp sp = csp(tabz+0,tabz+3);
|
Sp sp = csp(tabz+0,tabz+3);
|
||||||
P cent0=cos(sp);
|
P cent0=cos(sp);
|
||||||
P cent1=cos(tabz+0,tabz+3);
|
P cent1=cos(tabz+0,tabz+3);
|
||||||
assert(fabs(cent0[0]-2)<.0001);
|
assert(abs(cent0[0]-2)<.0001);
|
||||||
assert(fabs(cent0[1]+3)<.0001);
|
assert(abs(cent0[1]+3)<.0001);
|
||||||
assert(fabs(cent1[0]-2)<.0001);
|
assert(abs(cent1[0]-2)<.0001);
|
||||||
assert(fabs(cent1[1]+3)<.0001);
|
assert(abs(cent1[1]+3)<.0001);
|
||||||
assert(fabs(sp.squared_radius()-25)<.0001);
|
assert(abs(sp.squared_radius()-25)<.0001);
|
||||||
|
#if 1
|
||||||
|
// Fails for an exact kernel
|
||||||
P psp0=ps(sp,0);
|
P psp0=ps(sp,0);
|
||||||
P psp1=ps(sp,1);
|
P psp1=ps(sp,1);
|
||||||
P psp2=ps(sp,2);
|
P psp2=ps(sp,2);
|
||||||
assert(!ed(psp0,psp1));
|
assert(!ed(psp0,psp1));
|
||||||
assert(!ed(psp0,psp2));
|
assert(!ed(psp0,psp2));
|
||||||
assert(!ed(psp2,psp1));
|
assert(!ed(psp2,psp1));
|
||||||
assert(fabs(sd(cent0,psp0)-25)<.0001);
|
assert(abs(sd(cent0,psp0)-25)<.0001);
|
||||||
assert(fabs(sd(cent0,psp1)-25)<.0001);
|
assert(abs(sd(cent0,psp1)-25)<.0001);
|
||||||
assert(fabs(sd(cent0,psp2)-25)<.0001);
|
assert(abs(sd(cent0,psp2)-25)<.0001);
|
||||||
|
#endif
|
||||||
|
P x2py1 = tp(x2,y1);
|
||||||
|
assert(x2py1[1]==-2);
|
||||||
|
WP tw[]={cwp(cp(5,0),1.5),cwp(cp(2,std::sqrt(3)),1),cwp(cp(2,-std::sqrt(3)),1)};
|
||||||
|
WP xw=pc(tw+0,tw+3);
|
||||||
|
assert(abs(pod(xw,tw[0]))<.0001);
|
||||||
|
assert(abs(pod(xw,tw[1]))<.0001);
|
||||||
|
assert(abs(pod(xw,tw[2]))<.0001);
|
||||||
|
assert(pdw(xw)[0]<2.95);
|
||||||
|
assert(pdw(xw)[0]>2.5);
|
||||||
|
assert(pw(xw)<2.95);
|
||||||
|
assert(pw(xw)>2.5);
|
||||||
|
|
||||||
|
|
||||||
P tl=cp(2,5);
|
P tl=cp(2,5);
|
||||||
P br=cp(4,-1);
|
P br=cp(4,-1);
|
||||||
|
|
@ -459,6 +490,7 @@ void test3(){
|
||||||
PD pd Kinit(point_dimension_d_object);
|
PD pd Kinit(point_dimension_d_object);
|
||||||
AI ai Kinit(affinely_independent_d_object);
|
AI ai Kinit(affinely_independent_d_object);
|
||||||
SBDS sbds Kinit(side_of_bounded_sphere_d_object);
|
SBDS sbds Kinit(side_of_bounded_sphere_d_object);
|
||||||
|
using std::abs;
|
||||||
P a; // Triangulation needs this :-(
|
P a; // Triangulation needs this :-(
|
||||||
a=cp(2,3,4);
|
a=cp(2,3,4);
|
||||||
assert(pd(a)==3);
|
assert(pd(a)==3);
|
||||||
|
|
@ -482,7 +514,7 @@ void test3(){
|
||||||
std::cout << *i << ' ';
|
std::cout << *i << ' ';
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
P e=cp(-2,3,0);
|
P e=cp(-2,3,0);
|
||||||
assert(fabs(sd(e,a)-32)<.0001);
|
assert(abs(sd(e,a)-32)<.0001);
|
||||||
P tab[]={a,b,c,d,e};
|
P tab[]={a,b,c,d,e};
|
||||||
std::cout << po (&tab[0],tab+4) << ' ';
|
std::cout << po (&tab[0],tab+4) << ' ';
|
||||||
std::cout << sos(&tab[0],tab+5) << ' ';
|
std::cout << sos(&tab[0],tab+5) << ' ';
|
||||||
|
|
|
||||||
|
|
@ -91,16 +91,26 @@ public:
|
||||||
|
|
||||||
struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{
|
struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{
|
||||||
PointPropertyMap ppmap;
|
PointPropertyMap ppmap;
|
||||||
using Base_traits::Construct_cartesian_const_iterator_d::operator();
|
|
||||||
|
|
||||||
Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_)
|
Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_)
|
||||||
:Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){}
|
:Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){}
|
||||||
|
|
||||||
typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const
|
typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const
|
||||||
{ return this->operator() (get(ppmap,p)); }
|
{ return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p)); }
|
||||||
|
|
||||||
typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const
|
typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p, int) const
|
||||||
{ return this->operator() (get(ppmap,p),0); }
|
{ return Base_traits::Construct_cartesian_const_iterator_d::operator() (get(ppmap,p),0); }
|
||||||
|
|
||||||
|
// These 2 additional operators forward the call to Base_traits.
|
||||||
|
// This is needed because of an undocumented requirement of
|
||||||
|
// Orthogonal_k_neighbor_search and Orthogonal_incremental_neighbor_search:
|
||||||
|
// Traits::Construct_cartesian_const_iterator should be callable
|
||||||
|
// on the query point type
|
||||||
|
typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p) const
|
||||||
|
{ return Base_traits::Construct_cartesian_const_iterator_d::operator() (p); }
|
||||||
|
|
||||||
|
typename Base_traits::Cartesian_const_iterator_d operator()(const typename Base_traits::Point_d& p, int) const
|
||||||
|
{ return Base_traits::Construct_cartesian_const_iterator_d::operator() (p,0); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Construct_iso_box_d: public Base::Construct_iso_box_d{
|
struct Construct_iso_box_d: public Base::Construct_iso_box_d{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Created by the script cgal_create_cmake_script
|
||||||
|
# This is the CMake script for compiling a CGAL application.
|
||||||
|
|
||||||
|
|
||||||
|
project( Tangential_complex_apps )
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.6.2)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
|
||||||
|
cmake_policy(VERSION 2.8.4)
|
||||||
|
else()
|
||||||
|
cmake_policy(VERSION 2.6)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(CGAL QUIET COMPONENTS Core )
|
||||||
|
|
||||||
|
if ( CGAL_FOUND )
|
||||||
|
include( ${CGAL_USE_FILE} )
|
||||||
|
|
||||||
|
find_package(Eigen3 3.1.0)
|
||||||
|
if (EIGEN3_FOUND)
|
||||||
|
include( ${EIGEN3_USE_FILE} )
|
||||||
|
include_directories (BEFORE "../../include")
|
||||||
|
|
||||||
|
include( CGAL_CreateSingleSourceCGALProgram )
|
||||||
|
|
||||||
|
create_single_source_cgal_program( "euler_charact.cpp" )
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
|
||||||
|
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include <CGAL/Tangential_complex/Simplicial_complex.h>
|
||||||
|
|
||||||
|
using namespace CGAL::Tangential_complex_;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
std::cout << "Usage: euler_charact <input.off>\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Simplicial_complex complex;
|
||||||
|
complex.load_simplices_from_OFF(argv[1]);
|
||||||
|
|
||||||
|
complex.euler_characteristic(true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Created by the script cgal_create_cmake_script
|
||||||
|
# This is the CMake script for compiling a CGAL application.
|
||||||
|
|
||||||
|
|
||||||
|
project( Tangential_complex_benchmark )
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.6.2)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
|
||||||
|
cmake_policy(VERSION 2.8.4)
|
||||||
|
else()
|
||||||
|
cmake_policy(VERSION 2.6)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Creates a new CMake option, turned ON by default
|
||||||
|
option(ACTIVATE_MSVC_PRECOMPILED_HEADERS
|
||||||
|
"Activate precompiled headers in MSVC"
|
||||||
|
OFF)
|
||||||
|
|
||||||
|
# Macro to add precompiled headers for MSVC
|
||||||
|
# This function does two things:
|
||||||
|
# 1. Enable precompiled headers on each file which is listed in "SourcesVar".
|
||||||
|
# 2. Add the content of "PrecompiledSource" (e.g. "StdAfx.cpp") to "SourcesVar".
|
||||||
|
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
|
||||||
|
IF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS)
|
||||||
|
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
|
||||||
|
SET(Sources ${${SourcesVar}})
|
||||||
|
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
|
||||||
|
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\"")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(${Sources}
|
||||||
|
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeader}\"")
|
||||||
|
# Add precompiled header to SourcesVar
|
||||||
|
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
|
||||||
|
ENDIF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS)
|
||||||
|
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
|
||||||
|
|
||||||
|
# The compiler might need more memory because of precompiled headers
|
||||||
|
if(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS AND NOT(MSVC_VERSION LESS 1310))
|
||||||
|
set(CGAL_C_FLAGS "${CGAL_C_FLAGS} /Zm1000")
|
||||||
|
set(CGAL_CXX_FLAGS "${CGAL_CXX_FLAGS} /Zm1000")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(CGAL QUIET COMPONENTS Core )
|
||||||
|
|
||||||
|
if ( CGAL_FOUND )
|
||||||
|
include( ${CGAL_USE_FILE} )
|
||||||
|
|
||||||
|
find_package( TBB QUIET )
|
||||||
|
|
||||||
|
if( TBB_FOUND )
|
||||||
|
include(${TBB_USE_FILE})
|
||||||
|
list(APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
include( CGAL_CreateSingleSourceCGALProgram )
|
||||||
|
|
||||||
|
find_package(Eigen3 3.1.0)
|
||||||
|
if (EIGEN3_FOUND)
|
||||||
|
include( ${EIGEN3_USE_FILE} )
|
||||||
|
include_directories (BEFORE "../../include")
|
||||||
|
include_directories (BEFORE "include")
|
||||||
|
|
||||||
|
set (SOURCE_FILES "benchmark_tc.cpp")
|
||||||
|
ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES)
|
||||||
|
create_single_source_cgal_program( ${SOURCE_FILES} )
|
||||||
|
|
||||||
|
set (SOURCE_FILES "benchmark_mesh_d.cpp")
|
||||||
|
ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES)
|
||||||
|
create_single_source_cgal_program( ${SOURCE_FILES} )
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Build the precompiled headers.
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef STDAFX_H
|
||||||
|
#define STDAFX_H
|
||||||
|
|
||||||
|
// CGAL
|
||||||
|
#include <CGAL/Tangential_complex/config.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Regular_triangulation_euclidean_traits.h>
|
||||||
|
#include <CGAL/Regular_triangulation.h>
|
||||||
|
#include <CGAL/Delaunay_triangulation.h>
|
||||||
|
#include <CGAL/Tangential_complex/utilities.h>
|
||||||
|
#include <CGAL/Tangential_complex/Point_cloud.h>
|
||||||
|
#include <CGAL/Combination_enumerator.h>
|
||||||
|
|
||||||
|
#endif //STDAFX_H
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
template<typename value_type = std::string>
|
||||||
|
class Simple_XML_exporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef value_type Value_type;
|
||||||
|
typedef std::vector<value_type> Element;
|
||||||
|
typedef std::map<std::string, value_type> Element_with_map;
|
||||||
|
typedef std::vector<Element> List_of_elements;
|
||||||
|
|
||||||
|
Simple_XML_exporter(
|
||||||
|
const std::string &list_name,
|
||||||
|
const std::string &element_name,
|
||||||
|
const std::vector<std::string> &subelement_names,
|
||||||
|
bool add_timestamp = true)
|
||||||
|
: m_list_name(list_name),
|
||||||
|
m_element_name(element_name),
|
||||||
|
m_subelement_names(subelement_names),
|
||||||
|
m_add_timestamp(add_timestamp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool add_element(const Element &element)
|
||||||
|
{
|
||||||
|
if (element.size() == m_subelement_names.size())
|
||||||
|
{
|
||||||
|
m_list_of_elements.push_back(element);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_element(Element_with_map &element)
|
||||||
|
{
|
||||||
|
Element elt;
|
||||||
|
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name = m_subelement_names.begin();
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name_end = m_subelement_names.end();
|
||||||
|
for ( ; it_subelement_name != it_subelement_name_end ; ++it_subelement_name)
|
||||||
|
{
|
||||||
|
elt.push_back(element[*it_subelement_name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return add_element(elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool export_to_xml(const std::string &filename) const
|
||||||
|
{
|
||||||
|
std::ofstream xmlfile;
|
||||||
|
xmlfile.open(filename.c_str());
|
||||||
|
xmlfile << "<?xml version='1.0'?>" << std::endl;
|
||||||
|
xmlfile << "<" << m_list_name << ">" << std::endl;
|
||||||
|
|
||||||
|
typename List_of_elements::const_iterator it_element = m_list_of_elements.begin();
|
||||||
|
typename List_of_elements::const_iterator it_element_end = m_list_of_elements.end();
|
||||||
|
for (int id = 1 ; it_element != it_element_end ; ++it_element, ++id)
|
||||||
|
{
|
||||||
|
xmlfile << " <" << m_element_name << ">" << std::endl;
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name = m_subelement_names.begin();
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name_end = m_subelement_names.end();
|
||||||
|
|
||||||
|
if (m_add_timestamp)
|
||||||
|
xmlfile << " <id> " << time(NULL) << " </id>" << std::endl;
|
||||||
|
|
||||||
|
for (int i = 0 ;
|
||||||
|
it_subelement_name != it_subelement_name_end ;
|
||||||
|
++it_subelement_name, ++i)
|
||||||
|
{
|
||||||
|
xmlfile
|
||||||
|
<< " <" << *it_subelement_name << "> "
|
||||||
|
<< (*it_element)[i]
|
||||||
|
<< " </" << *it_subelement_name << ">" << std::endl;
|
||||||
|
}
|
||||||
|
xmlfile << " </" << m_element_name << ">" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlfile << "</" << m_list_name << ">" << std::endl;
|
||||||
|
xmlfile.close();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_list_name;
|
||||||
|
std::string m_element_name;
|
||||||
|
std::vector<std::string> m_subelement_names;
|
||||||
|
List_of_elements m_list_of_elements;
|
||||||
|
bool m_add_timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename value_type = std::string>
|
||||||
|
class Streaming_XML_exporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef value_type Value_type;
|
||||||
|
typedef std::vector<value_type> Element;
|
||||||
|
typedef std::map<std::string, value_type> Element_with_map;
|
||||||
|
typedef std::vector<Element> List_of_elements;
|
||||||
|
|
||||||
|
Streaming_XML_exporter(
|
||||||
|
const std::string &filename,
|
||||||
|
const std::string &list_name,
|
||||||
|
const std::string &element_name,
|
||||||
|
const std::vector<std::string> &subelement_names,
|
||||||
|
bool add_timestamp = true)
|
||||||
|
: m_list_name(list_name),
|
||||||
|
m_element_name(element_name),
|
||||||
|
m_subelement_names(subelement_names),
|
||||||
|
m_add_timestamp(add_timestamp)
|
||||||
|
{
|
||||||
|
m_xml_fstream.open(filename.c_str());
|
||||||
|
if (m_xml_fstream.good())
|
||||||
|
{
|
||||||
|
m_xml_fstream << "<?xml version='1.0'?>" << std::endl;
|
||||||
|
m_xml_fstream << "<" << m_list_name << ">" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Could not open file '" << filename << "'." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Streaming_XML_exporter()
|
||||||
|
{
|
||||||
|
close_file();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_file()
|
||||||
|
{
|
||||||
|
m_xml_fstream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_element(const Element &element)
|
||||||
|
{
|
||||||
|
if (element.size() == m_subelement_names.size())
|
||||||
|
{
|
||||||
|
m_xml_fstream << " <" << m_element_name << ">" << std::endl;
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name = m_subelement_names.begin();
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name_end = m_subelement_names.end();
|
||||||
|
|
||||||
|
if (m_add_timestamp)
|
||||||
|
{
|
||||||
|
m_xml_fstream << " <id> " << time(NULL) << " </id>" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0 ;
|
||||||
|
it_subelement_name != it_subelement_name_end ;
|
||||||
|
++it_subelement_name, ++i)
|
||||||
|
{
|
||||||
|
m_xml_fstream
|
||||||
|
<< " <" << *it_subelement_name << "> "
|
||||||
|
<< element[i]
|
||||||
|
<< " </" << *it_subelement_name << ">" << std::endl;
|
||||||
|
}
|
||||||
|
m_xml_fstream << " </" << m_element_name << ">" << std::endl;
|
||||||
|
|
||||||
|
// Save current pointer position
|
||||||
|
std::ofstream::streampos pos = m_xml_fstream.tellp();
|
||||||
|
// Close the XML file (temporarily) so that the XML file is always correct
|
||||||
|
m_xml_fstream << "</" << m_list_name << ">" << std::endl;
|
||||||
|
// Restore the pointer position so that the next "add_element" will overwrite
|
||||||
|
// the end of the file
|
||||||
|
m_xml_fstream.seekp(pos);
|
||||||
|
|
||||||
|
m_xml_fstream.flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_element(Element_with_map &element)
|
||||||
|
{
|
||||||
|
Element elt;
|
||||||
|
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name = m_subelement_names.begin();
|
||||||
|
std::vector<std::string>::const_iterator
|
||||||
|
it_subelement_name_end = m_subelement_names.end();
|
||||||
|
for ( ; it_subelement_name != it_subelement_name_end ; ++it_subelement_name)
|
||||||
|
{
|
||||||
|
elt.push_back(element[*it_subelement_name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return add_element(elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::ofstream m_xml_fstream;
|
||||||
|
std::string m_list_name;
|
||||||
|
std::string m_element_name;
|
||||||
|
std::vector<std::string> m_subelement_names;
|
||||||
|
bool m_add_timestamp;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,430 @@
|
||||||
|
//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP
|
||||||
|
|
||||||
|
// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
|
||||||
|
// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define TBB_USE_THREADING_TOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 100000000;
|
||||||
|
|
||||||
|
#include <CGAL/assertions_behaviour.h>
|
||||||
|
#include <CGAL/Mesh_d.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
#include <CGAL/Mesh_3/Profiling_tools.h>
|
||||||
|
|
||||||
|
#include "../../test/Tangential_complex/testing_utilities.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/algorithm/string/trim_all.hpp>
|
||||||
|
#include <boost/range/adaptor/strided.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# include <tbb/task_scheduler_init.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace CGAL::Tangential_complex_;
|
||||||
|
|
||||||
|
const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt";
|
||||||
|
|
||||||
|
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
|
||||||
|
typedef Kernel::FT FT;
|
||||||
|
typedef Kernel::Point_d Point;
|
||||||
|
typedef CGAL::Mesh_d<Kernel, Kernel, CGAL::Parallel_tag> Mesh;
|
||||||
|
|
||||||
|
//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY
|
||||||
|
//#define MESH_D_INPUT_STRIDES 10 // only take one point every MESH_D_INPUT_STRIDES points
|
||||||
|
//#define MESH_D_NO_EXPORT
|
||||||
|
//#define CGAL_MESH_D_USE_LINEAR_PROG_TO_COMPUTE_INTERSECTION
|
||||||
|
//#define CGAL_MESH_D_FILTER_BY_TESTING_ALL_VERTICES_TANGENT_PLANES
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Mesh, typename Indexed_simplex_range = void>
|
||||||
|
bool export_to_off(
|
||||||
|
Mesh const& mesh,
|
||||||
|
std::string const& input_name_stripped,
|
||||||
|
std::string const& suffix,
|
||||||
|
Indexed_simplex_range const *p_simpl_to_color_in_red = NULL,
|
||||||
|
Indexed_simplex_range const *p_simpl_to_color_in_green = NULL,
|
||||||
|
Indexed_simplex_range const *p_simpl_to_color_in_blue = NULL)
|
||||||
|
{
|
||||||
|
#ifdef MESH_D_NO_EXPORT
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
if (mesh.intrinsic_dimension() <= 3)
|
||||||
|
{
|
||||||
|
std::stringstream output_filename;
|
||||||
|
output_filename << "output/" << input_name_stripped << "_"
|
||||||
|
<< mesh.intrinsic_dimension() << "_in_R"
|
||||||
|
<< mesh.ambient_dimension() << "_"
|
||||||
|
<< mesh.number_of_vertices() << "v"
|
||||||
|
<< suffix << ".off";
|
||||||
|
|
||||||
|
std::ofstream off_stream(output_filename.str().c_str());
|
||||||
|
|
||||||
|
mesh.export_to_off(
|
||||||
|
off_stream,
|
||||||
|
p_simpl_to_color_in_red,
|
||||||
|
p_simpl_to_color_in_green,
|
||||||
|
p_simpl_to_color_in_blue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void make_mesh(
|
||||||
|
std::vector<Point> &points,
|
||||||
|
int intrinsic_dim,
|
||||||
|
bool sparsify = true,
|
||||||
|
double sparsity = 0.01,
|
||||||
|
const char *input_name = "mesh")
|
||||||
|
{
|
||||||
|
Kernel k;
|
||||||
|
Kernel lk; // local kernel (intrinsic dim)
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Init
|
||||||
|
//===========================================================================
|
||||||
|
Wall_clock_timer t;
|
||||||
|
|
||||||
|
// Get input_name_stripped
|
||||||
|
std::string input_name_stripped(input_name);
|
||||||
|
size_t slash_index = input_name_stripped.find_last_of('/');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = input_name_stripped.find_last_of('\\');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = 0;
|
||||||
|
else
|
||||||
|
++slash_index;
|
||||||
|
input_name_stripped = input_name_stripped.substr(
|
||||||
|
slash_index, input_name_stripped.find_last_of('.') - slash_index);
|
||||||
|
|
||||||
|
int ambient_dim = k.point_dimension_d_object()(*points.begin());
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
|
||||||
|
std::vector<Point> points_not_sparse = points;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Sparsify point set if requested
|
||||||
|
//===========================================================================
|
||||||
|
if (sparsify)
|
||||||
|
{
|
||||||
|
std::size_t num_points_before = points.size();
|
||||||
|
points = sparsify_point_set(k, points, sparsity*sparsity);
|
||||||
|
std::cerr << "Number of points before/after sparsification: "
|
||||||
|
<< num_points_before << " / " << points.size() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Compute Tangential Complex
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
|
||||||
|
Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim,
|
||||||
|
points_not_sparse.begin(), points_not_sparse.end(), k, lk);
|
||||||
|
#else
|
||||||
|
Mesh mesh(points.begin(), points.end(), sparsity, intrinsic_dim, k, lk);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double init_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
std::vector<std::set<std::size_t> > uncertain_simplices;
|
||||||
|
mesh.compute_mesh(&uncertain_simplices);
|
||||||
|
double computation_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
mesh.display_stats();
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Export to OFF
|
||||||
|
//=========================================================================
|
||||||
|
t.reset();
|
||||||
|
bool exported = export_to_off(
|
||||||
|
mesh, input_name_stripped, "", &uncertain_simplices);
|
||||||
|
double export_time = (exported ? t.elapsed() : -1);
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Is the result a pure pseudomanifold?
|
||||||
|
//===========================================================================
|
||||||
|
std::size_t num_wrong_dim_simplices,
|
||||||
|
num_wrong_number_of_cofaces,
|
||||||
|
num_unconnected_stars;
|
||||||
|
std::set<std::set<std::size_t> > wrong_dim_simplices;
|
||||||
|
std::set<std::set<std::size_t> > wrong_number_of_cofaces_simplices;
|
||||||
|
std::set<std::set<std::size_t> > unconnected_stars_simplices;
|
||||||
|
bool is_pure_pseudomanifold = mesh.complex().is_pure_pseudomanifold(
|
||||||
|
intrinsic_dim, mesh.number_of_vertices(), false, false, 1,
|
||||||
|
&num_wrong_dim_simplices, &num_wrong_number_of_cofaces,
|
||||||
|
&num_unconnected_stars,
|
||||||
|
&wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
|
||||||
|
&unconnected_stars_simplices);
|
||||||
|
|
||||||
|
// Stats about the simplices
|
||||||
|
mesh.complex().display_stats();
|
||||||
|
std::size_t num_edges = mesh.complex().num_K_simplices<1>();
|
||||||
|
std::size_t num_triangles = mesh.complex().num_K_simplices<2>();
|
||||||
|
std::cerr << "Euler caract.: V - E + F = "
|
||||||
|
<< mesh.number_of_vertices()
|
||||||
|
<< " - " << (std::ptrdiff_t) num_edges
|
||||||
|
<< " + " << (std::ptrdiff_t) num_triangles
|
||||||
|
<< " = "
|
||||||
|
<< yellow
|
||||||
|
<< (std::ptrdiff_t) mesh.number_of_vertices()
|
||||||
|
- (std::ptrdiff_t) num_edges
|
||||||
|
+ (std::ptrdiff_t) num_triangles
|
||||||
|
<< white << "\n";
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Display info
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
std::cerr
|
||||||
|
<< "\n================================================\n"
|
||||||
|
<< "Number of vertices: " << mesh.number_of_vertices() << "\n"
|
||||||
|
<< "Pure pseudomanifold: " << yellow
|
||||||
|
<< (is_pure_pseudomanifold ? "YES" : "NO") << white << "\n"
|
||||||
|
<< "Computation times (seconds): \n"
|
||||||
|
<< " * Mesh: " << init_time + computation_time << "\n"
|
||||||
|
<< " - Init + kd-tree = " << init_time << "\n"
|
||||||
|
<< " - Mesh computation = " << computation_time << "\n"
|
||||||
|
//<< " * Export to OFF : " << export_before_time << "\n"
|
||||||
|
<< "================================================\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CGAL::set_error_behaviour(CGAL::ABORT);
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# ifdef _DEBUG
|
||||||
|
int num_threads = 1;
|
||||||
|
# else
|
||||||
|
int num_threads = 8;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int seed = static_cast<unsigned int>(time(NULL));
|
||||||
|
CGAL::default_random = CGAL::Random(seed);
|
||||||
|
std::cerr << "Random seed = " << seed << "\n";
|
||||||
|
|
||||||
|
std::ifstream script_file;
|
||||||
|
script_file.open(BENCHMARK_SCRIPT_FILENAME);
|
||||||
|
// Script?
|
||||||
|
// Script file format: each line gives
|
||||||
|
// - Filename (point set) or "generate_XXX" (point set generation)
|
||||||
|
// - Ambient dim
|
||||||
|
// - Intrinsic dim
|
||||||
|
// - Number of iterations with these parameters
|
||||||
|
if (script_file.is_open())
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# ifdef BENCHMARK_WITH_1_TO_MAX_THREADS
|
||||||
|
for(num_threads = 1 ;
|
||||||
|
num_threads <= tbb::task_scheduler_init::default_num_threads() ;
|
||||||
|
++num_threads)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
tbb::task_scheduler_init init(
|
||||||
|
num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME
|
||||||
|
<< "' found.\n";
|
||||||
|
script_file.seekg(0);
|
||||||
|
while (script_file.good())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
std::getline(script_file, line);
|
||||||
|
if (line.size() > 1 && line[0] != '#')
|
||||||
|
{
|
||||||
|
boost::replace_all(line, "\t", " ");
|
||||||
|
boost::trim_all(line);
|
||||||
|
std::cerr << "\n\n";
|
||||||
|
std::cerr << "*****************************************\n";
|
||||||
|
std::cerr << "******* " << line << "\n";
|
||||||
|
std::cerr << "*****************************************\n";
|
||||||
|
std::stringstream sstr(line);
|
||||||
|
|
||||||
|
std::string input;
|
||||||
|
std::string param1;
|
||||||
|
std::string param2;
|
||||||
|
std::string param3;
|
||||||
|
std::size_t num_points;
|
||||||
|
int ambient_dim;
|
||||||
|
int intrinsic_dim;
|
||||||
|
char sparsify;
|
||||||
|
double sparsity;
|
||||||
|
char perturb, add_high_dim_simpl, collapse;
|
||||||
|
double time_limit_for_perturb;
|
||||||
|
int num_iteration;
|
||||||
|
sstr >> input;
|
||||||
|
sstr >> param1;
|
||||||
|
sstr >> param2;
|
||||||
|
sstr >> param3;
|
||||||
|
sstr >> num_points;
|
||||||
|
sstr >> ambient_dim;
|
||||||
|
sstr >> intrinsic_dim;
|
||||||
|
sstr >> sparsify;
|
||||||
|
sstr >> sparsity;
|
||||||
|
sstr >> perturb;
|
||||||
|
sstr >> add_high_dim_simpl;
|
||||||
|
sstr >> collapse;
|
||||||
|
sstr >> time_limit_for_perturb;
|
||||||
|
sstr >> num_iteration;
|
||||||
|
|
||||||
|
for (int j = 0 ; j < num_iteration ; ++j)
|
||||||
|
{
|
||||||
|
std::string input_stripped = input;
|
||||||
|
size_t slash_index = input_stripped.find_last_of('/');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = input_stripped.find_last_of('\\');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = 0;
|
||||||
|
else
|
||||||
|
++slash_index;
|
||||||
|
input_stripped = input_stripped.substr(
|
||||||
|
slash_index, input_stripped.find_last_of('.') - slash_index);
|
||||||
|
|
||||||
|
std::cerr << "\nMesh #" << i << "...\n";
|
||||||
|
|
||||||
|
#ifdef CGAL_MESH_D_PROFILING
|
||||||
|
Wall_clock_timer t_gen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
Mesh::TS_container tangent_spaces;
|
||||||
|
|
||||||
|
if (input == "generate_moment_curve")
|
||||||
|
{
|
||||||
|
points = generate_points_on_moment_curve<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_plane")
|
||||||
|
{
|
||||||
|
points = generate_points_on_plane<Kernel>(
|
||||||
|
num_points, intrinsic_dim, ambient_dim);
|
||||||
|
}
|
||||||
|
else if (input == "generate_sphere_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_sphere_d<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()), // radius
|
||||||
|
std::atof(param2.c_str())); // radius_noise_percentage
|
||||||
|
}
|
||||||
|
else if (input == "generate_two_spheres_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_two_spheres_d<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()),
|
||||||
|
std::atof(param2.c_str()),
|
||||||
|
std::atof(param3.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_3sphere_and_circle_d")
|
||||||
|
{
|
||||||
|
CGAL_assertion(intrinsic_dim == 3);
|
||||||
|
CGAL_assertion(ambient_dim == 5);
|
||||||
|
points = generate_points_on_3sphere_and_circle<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_torus_3D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_torus_3D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()),
|
||||||
|
std::atof(param2.c_str()),
|
||||||
|
param3 == "Y");
|
||||||
|
}
|
||||||
|
else if (input == "generate_torus_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_torus_d<Kernel>(
|
||||||
|
num_points,
|
||||||
|
intrinsic_dim,
|
||||||
|
param1 == "Y", // uniform
|
||||||
|
std::atof(param2.c_str())); // radius_noise_percentage
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_3D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_3D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_4D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_4D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_variant_5D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_variant_5D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
load_points_from_file<Kernel, typename Mesh::Tangent_space_basis>(
|
||||||
|
input, std::back_inserter(points),
|
||||||
|
std::back_inserter(tangent_spaces),
|
||||||
|
ONLY_LOAD_THE_FIRST_N_POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_MESH_D_PROFILING
|
||||||
|
std::cerr << "Point set generated/loaded in " << t_gen.elapsed()
|
||||||
|
<< " seconds.\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!points.empty())
|
||||||
|
{
|
||||||
|
#if defined(MESH_D_INPUT_STRIDES) && MESH_D_INPUT_STRIDES > 1
|
||||||
|
auto p = points | boost::adaptors::strided(MESH_D_INPUT_STRIDES); // CJTODO C++11 (auto)
|
||||||
|
std::vector<Point> points(p.begin(), p.end());
|
||||||
|
std::cerr << "****************************************\n"
|
||||||
|
<< "WARNING: taking 1 point every " << MESH_D_INPUT_STRIDES
|
||||||
|
<< " points.\n"
|
||||||
|
<< "****************************************\n";
|
||||||
|
#endif
|
||||||
|
make_mesh(
|
||||||
|
points, intrinsic_dim, sparsify == 'Y', sparsity,
|
||||||
|
input.c_str());
|
||||||
|
|
||||||
|
std::cerr << "Mesh #" << i++ << " done.\n";
|
||||||
|
std::cerr << "\n---------------------------------\n\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Mesh #" << i++ << ": no points loaded.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script_file.seekg(0);
|
||||||
|
script_file.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
script_file.close();
|
||||||
|
}
|
||||||
|
// Or not script?
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
system("pause");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
#---------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSIFY SPARSITY PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS
|
||||||
|
#---------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------
|
||||||
|
#generate_sphere_d 1 0 - 8 2 1 Y 0.005 N Y N 3 1 #No noise => OK: 6 2d with a perturb sometimes
|
||||||
|
#generate_sphere_d 1 0 - 50 2 1 Y 0.005 N Y N 3 1 #No noise => OK: 49 1d
|
||||||
|
#generate_sphere_d 1 1 - 50 2 1 Y 0.005 N Y N 3 1 #Noise => OK: 45 2d + 3 3d
|
||||||
|
#generate_torus_d N - - 15 2 1 Y 0.05 N Y N 10 1
|
||||||
|
#generate_sphere_d 0.302 0 - 8 3 2 Y 0.005 N Y N 60 1 #No noise => OK: 7 3d with a perturb sometimes
|
||||||
|
#generate_sphere_d 0.302 0 - 50 3 2 Y 0.005 N Y N 60 1 #No noise => no inconsitencies
|
||||||
|
#generate_sphere_d 0.302 3 - 50 3 2 Y 0.005 N Y N 60 1 #Noise => OK: 90 2d + 3 3d
|
||||||
|
#generate_sphere_d 1 1 - 500 4 3 Y 0.005 N Y N 60 1 #Noise 1% => OK: 3113 3d + 35 4d
|
||||||
|
#generate_sphere_d 1 2 - 500 4 3 Y 0.005 N Y N 60 1 #Noise 2% => OK: 2969 3d + 91 4d
|
||||||
|
#generate_sphere_d 1 2 - 5000 4 3 Y 0.005 N Y N 60 1 #Noise 2% => OK: 27905 3d + 2485 4d
|
||||||
|
#generate_sphere_d 0.302 2 - 300 2 1 Y 0.005 N Y N 60 1
|
||||||
|
#generate_torus_3D 2 1 N 200 3 2 Y 0.05 N Y N 600 1 #OK: 1048 3d ~170s
|
||||||
|
#generate_torus_3D 2 1 N 2000 3 2 Y 0.05 N Y N 600 1 #OK: 3545 2d + 27 3d ~35s
|
||||||
|
#generate_torus_d N 1 - 50 4 2 Y 0.05 N Y N 3 1 #OK: 431 4d
|
||||||
|
#generate_torus_d N 1 - 500 4 2 Y 0.05 N Y N 3 1 #OK: 881 2d + 37 3d
|
||||||
|
#generate_torus_d Y 1 - 250 4 2 Y 0.05 N Y N 3 1 #OK: 80 d2 + 185 d3
|
||||||
|
#generate_torus_d N - - 50 6 3 Y 0.05 Y Y N 10 1 #
|
||||||
|
#generate_torus_d Y - - 700 6 3 Y 0.05 Y Y N 100 1 #Grid
|
||||||
|
#generate_torus_d N - - 50000 6 3 Y 0.05 Y Y N 0 1 #Too long...
|
||||||
|
#generate_moment_curve 0 1 - 10 3 1 Y 0.005 N Y N 60 1
|
||||||
|
#generate_two_spheres_d 3 4 - 500 3 2 Y 0.05 N Y N 10 1 #OK: 320 2d + 1167 3d
|
||||||
|
#generate_klein_bottle_4D 40 15 - 500 4 2 Y 0.2 N Y N 60 1 #OK: 901 d2 + 50 d3 + 1 d4
|
||||||
|
#data/SO3_10000.txt - - - 0 9 3 Y 0.05 Y Y N 300 1 #Too long. Be careful with the memory consumption!
|
||||||
|
#data/buddha_100kv.txt - - - 0 3 2 Y 0.005 Y Y N 120 1 #Too long...
|
||||||
|
#data/fandisk.txt - - - 0 3 2 Y 0.005 Y Y N 5 1 #NOT OK: Tq & V do not intersect
|
||||||
|
|
||||||
|
#---------------------------------------------------------------- Fixed-alpha TC tests ------------------------------------------------------------------------
|
||||||
|
#generate_sphere_d 0.302 - - 70 2 1 Y 0.005 N N N 60 1
|
||||||
|
#generate_sphere_d 0.304 0 - 100 3 2 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 0 - 100 4 3 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 0 - 1000 5 4 Y 0.05 N N N 60 1
|
||||||
|
#generate_two_spheres_d 3 4 - 1000 3 2 Y 0.05 N N N 10 1
|
||||||
|
#generate_two_spheres_d 3 10 - 1000 4 3 Y 0.05 N N N 10 1
|
||||||
|
#generate_two_spheres_d 3 10 - 2000 5 4 Y 0.05 N N N 10 1
|
||||||
|
#generate_3sphere_and_circle_d 3 - - 100000 5 3 Y 0.05 N N N 7000 1
|
||||||
|
#generate_plane - - - 100 4 3 Y 0.005 N N N 3000 1
|
||||||
|
#generate_plane - - - 10 5 4 Y 0.005 N N N 3000 1
|
||||||
|
#generate_klein_bottle_4D 40 15 - 500 4 2 Y 0.2 N N N 60 1
|
||||||
|
#generate_klein_bottle_4D 40 15 - 2000 4 2 Y 0.2 N N N 60 1
|
||||||
|
#generate_klein_bottle_4D 8 5 - 5000 4 2 Y 0.2 N N N 60 1 #Takes forever
|
||||||
|
#generate_torus_3D 2 1 Y 150 3 2 Y 0.05 N N N 600 1
|
||||||
|
#generate_torus_3D 2 1 N 100000 3 2 Y 0.55 N N N 600 1
|
||||||
|
#generate_torus_d N - - 18 2 1 Y 0.01 N N N 30 1
|
||||||
|
#generate_torus_d N - - 50000 2 1 Y 0.7 N N N 30 1
|
||||||
|
#generate_torus_d Y - - 2 2 1 N 0.01 N N N 30 1
|
||||||
|
#generate_torus_d Y - - 15 4 2 Y 0.05 N N N 30 1
|
||||||
|
#generate_torus_d N 0 - 150 4 2 Y 0.05 N N N 10 1
|
||||||
|
#generate_torus_d N - - 20000 4 2 Y 1.0 N N N 30 1
|
||||||
|
#generate_torus_d Y 0 - 5000 6 3 Y 0.05 N N N 300 1
|
||||||
|
#generate_torus_d N - - 20000 6 3 Y 0.05 N N N 60 1
|
||||||
|
#generate_torus_d N - - 100000 6 3 Y 0.05 N N N 3000 1
|
||||||
|
#generate_torus_d N - - 1000000 6 3 Y 0.3 N N N 3000 1
|
||||||
|
#generate_torus_d Y - - 1000 8 4 Y 0.05 N N N 60 1
|
||||||
|
#data/SO3_10000.txt - - - 0 9 3 Y 0.1 N N N 60 1
|
||||||
|
|
||||||
|
#---------------------------------------------------------- Spatial search benchmarking --------------------------------------------------------------
|
||||||
|
#generate_torus_3D 2 1 Y 10000 3 2 N 0 Y N N 600 1
|
||||||
|
#data/buddha_100kv.txt - - - 0 3 2 N 0 N Y N 120 1
|
||||||
|
#generate_torus_d N - - 10000 30 15 N 0 Y N N 3600 1
|
||||||
|
#generate_torus_d N - - 100000 12 6 N 0 Y N N 3600 1
|
||||||
|
#data/SO3_50000.txt - - - 0 9 3 N 0 Y N N 60 1
|
||||||
|
#data/Cy8.txt - - - 0 24 2 N 0 N Y N 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 2 1 N 0 N N Y 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 3 2 N 0 N N Y 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 4 3 N 0 N N Y 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 5 4 N 0 N N Y 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 6 5 N 0 N N Y 60 1
|
||||||
|
#generate_sphere_d 0.5 - - 10000 7 6 N 0 N N Y 60 1
|
||||||
|
|
||||||
|
#---------------------------------------------------------- Very small cases for Debug mode --------------------------------------------------------------
|
||||||
|
#generate_sphere_d 4 - - 20 3 2 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 - - 70 3 2 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 - - 1000 3 2 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 - - 70 4 3 Y 0.05 N N N 60 1
|
||||||
|
#generate_sphere_d 3 - - 70 5 4 Y 0.05 N N N 60 1
|
||||||
|
#generate_klein_bottle_variant_5D 4 3 - 70 5 2 Y 0.05 N N N 60 1
|
||||||
|
#data/SO3_10000.txt - - - 0 9 3 Y 0.7 N N N 60 1
|
||||||
|
#generate_moment_curve 0 1 - 30 3 1 Y 0.005 N N N 60 1
|
||||||
|
|
||||||
|
#------------------------------------------------------------------ From files --------------------------------------------------------------------------
|
||||||
|
#data/SO3_50000.txt - - - 0 9 3 Y 0.05 Y Y N 60 1
|
||||||
|
#data/SO3_10000.txt - - - 0 9 3 Y 0.05 Y N N 60 1
|
||||||
|
#data/cube3D_eps_0.1.txt - - - 0 3 2 Y 0.05 N Y N 3000 1
|
||||||
|
#data/cube4D_eps_0.1.txt - - - 0 4 3 Y 0.05 N Y N 3000 1
|
||||||
|
#data/cube5D_eps_0.1.txt - - - 0 5 4 Y 0.05 N Y N 3000 1
|
||||||
|
#data/Cy8.txt - - - 0 24 2 Y 0.1 N Y N 60 1
|
||||||
|
#data/Kl.txt - - - 0 5 2 Y 0.05 N Y N 60 1
|
||||||
|
#data/S3.txt - - - 0 4 3 Y 0.05 N Y N 60 1
|
||||||
|
|
||||||
|
data/Alvarez_variete_k2_D4_29700p.txt - - - 0 4 2 Y 0.01 Y N N 36000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.01 Y N N 36000 1
|
||||||
|
|
||||||
|
#data/Alvarez_variete_k2_D4_29700p.txt - - - 0 4 2 Y 0.01 Y N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_297k.txt - - - 0 4 2 Y 0.001 Y N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_297k.txt - - - 0 4 2 Y 0.5 Y N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.001 Y N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_300k_random.txt - - - 0 4 2 Y 0.2 Y N N 500000 1
|
||||||
|
|
||||||
|
# With pre-computed tangent spaces
|
||||||
|
#data/test.pwt - - - 0 4 2 Y 0.01 N N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_30000p.txt - - - 0 4 2 Y 0.01 Y N N 500000 1
|
||||||
|
#data/Alvarez_variete_k2_D4_30000p_with_TSB.pwt - - - 0 4 2 N 0.01 Y N N 500000 1
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------- 3D meshes -----------------------------------------------------------------------
|
||||||
|
#data/buddha_100kv.txt - - - 0 3 2 Y 0.005 N Y N 120 1
|
||||||
|
#data/fandisk.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
#data/fertility.txt - - - 0 3 2 Y 0.4 N Y N 60 1
|
||||||
|
#data/bunny.txt - - - 0 3 2 Y 0.5 Y N N 60 1
|
||||||
|
#data/blob.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
#data/3holes.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
#data/785_hand_2500v.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
#data/785_hand_50kv.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
#data/bumpy_sphere.txt - - - 0 3 2 Y 0.01 N Y N 60 1
|
||||||
|
|
||||||
|
#----------------------------------------------------------- Generated point sets -----------------------------------------------------------------------
|
||||||
|
#generate_sphere_d 3 - - 4 3 2 Y 0.05 N N N 3000 1
|
||||||
|
#generate_sphere_d 3 - - 30000 2 1 Y 0.005 N N N 3000 1
|
||||||
|
#generate_sphere_d 3 - - 30000 3 2 Y 0.005 N N N 3000 1
|
||||||
|
#generate_sphere_d 3 - - 30000 4 3 Y 0.05 N N N 3000 1
|
||||||
|
#generate_sphere_d 3 0 - 300 3 2 Y 0.005 N N N 60 1
|
||||||
|
#generate_sphere_d 3 4 - 3000 3 2 Y 0.005 N N N 60 1
|
||||||
|
#generate_sphere_d 3 7 - 3000 3 2 Y 0.005 N N N 60 1
|
||||||
|
#generate_plane - - - 30000 3 2 Y 0.005 N N N 3000 1
|
||||||
|
#generate_moment_curve 0 1 - 30000 6 1 Y 0.005 N N N 60 1
|
||||||
|
#generate_klein_bottle_4D 4 3 - 1000 4 2 Y 0.01 N N N 3 1
|
||||||
|
#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 Y 0.05 N N N 60 1
|
||||||
|
#generate_klein_bottle_4D 8 5 - 5000 4 2 Y 0.2 N N N 60 1 #Takes forever
|
||||||
|
|
||||||
|
#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------
|
||||||
|
# TC: 5.55 / 1st fix step : 0.2
|
||||||
|
#data/fertility.txt - - - 0 3 2 Y 0.1 N Y N 100 1
|
||||||
|
|
@ -0,0 +1,871 @@
|
||||||
|
//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP
|
||||||
|
|
||||||
|
// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
|
||||||
|
// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define TBB_USE_THREADING_TOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
//#define CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
|
||||||
|
//#define TC_PROTECT_POINT_SET_DELTA 0.003
|
||||||
|
//#define JUST_BENCHMARK_SPATIAL_SEARCH // CJTODO: test
|
||||||
|
//#define CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY
|
||||||
|
//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points
|
||||||
|
//#define TC_NO_EXPORT
|
||||||
|
//#define CGAL_TC_ALVAREZ_SURFACE_WINDOW 0.95 // 1.9 - 0.95
|
||||||
|
//#define CGAL_TC_EXPORT_SPARSIFIED_POINT_SET
|
||||||
|
//#define CGAL_TC_EXPORT_ALL_COORDS_IN_OFF
|
||||||
|
|
||||||
|
const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 500000; // 1e10
|
||||||
|
|
||||||
|
#include <CGAL/assertions_behaviour.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Tangential_complex.h>
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
#include <CGAL/Mesh_3/Profiling_tools.h>
|
||||||
|
|
||||||
|
#include "../../test/Tangential_complex/testing_utilities.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/algorithm/string/trim_all.hpp>
|
||||||
|
#include <boost/range/adaptor/strided.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# include <tbb/task_scheduler_init.h>
|
||||||
|
#endif
|
||||||
|
#include "XML_exporter.h"
|
||||||
|
#define CGAL_TC_EXPORT_PERFORMANCE_DATA
|
||||||
|
#define CGAL_TC_SET_PERFORMANCE_DATA(value_name, value) \
|
||||||
|
XML_perf_data::set(value_name, value);
|
||||||
|
|
||||||
|
const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt";
|
||||||
|
|
||||||
|
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
|
||||||
|
typedef Kernel::FT FT;
|
||||||
|
typedef Kernel::Point_d Point;
|
||||||
|
typedef Kernel::Vector_d Vector;
|
||||||
|
typedef CGAL::Tangential_complex<
|
||||||
|
Kernel, CGAL::Dynamic_dimension_tag,
|
||||||
|
CGAL::Parallel_tag> TC;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TC_PROTECT_POINT_SET_DELTA
|
||||||
|
# include <CGAL/Tangential_complex/protected_sets.h> // CJTODO TEST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JUST_BENCHMARK_SPATIAL_SEARCH
|
||||||
|
std::ofstream spatial_search_csv_file("benchmark_spatial_search.csv");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace CGAL::Tangential_complex_;
|
||||||
|
|
||||||
|
class XML_perf_data
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Streaming_XML_exporter<std::string> XML_exporter;
|
||||||
|
|
||||||
|
XML_perf_data(const std::string &filename)
|
||||||
|
: m_xml(filename, "ContainerPerformance", "Perf",
|
||||||
|
construct_subelements_names())
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual ~XML_perf_data()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static XML_perf_data &get()
|
||||||
|
{
|
||||||
|
static XML_perf_data singleton(build_filename());
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value_type>
|
||||||
|
static void set(const std::string &name, Value_type value)
|
||||||
|
{
|
||||||
|
get().set_data(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void commit()
|
||||||
|
{
|
||||||
|
get().commit_current_element();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::string build_filename()
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "perf_logs/Performance_log_" << time(0) << ".xml";
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> construct_subelements_names()
|
||||||
|
{
|
||||||
|
std::vector<std::string> subelements;
|
||||||
|
subelements.push_back("Input");
|
||||||
|
subelements.push_back("Intrinsic_dim");
|
||||||
|
subelements.push_back("Ambient_dim");
|
||||||
|
subelements.push_back("Sparsity");
|
||||||
|
subelements.push_back("Num_points_in_input");
|
||||||
|
subelements.push_back("Num_points");
|
||||||
|
subelements.push_back("Initial_num_inconsistent_local_tr");
|
||||||
|
subelements.push_back("Best_num_inconsistent_local_tr");
|
||||||
|
subelements.push_back("Final_num_inconsistent_local_tr");
|
||||||
|
subelements.push_back("Init_time");
|
||||||
|
subelements.push_back("Comput_time");
|
||||||
|
subelements.push_back("Perturb_successful");
|
||||||
|
subelements.push_back("Perturb_time");
|
||||||
|
subelements.push_back("Perturb_steps");
|
||||||
|
subelements.push_back("Add_higher_dim_simpl_time");
|
||||||
|
subelements.push_back("Result_pure_pseudomanifold");
|
||||||
|
subelements.push_back("Result_num_wrong_dim_simplices");
|
||||||
|
subelements.push_back("Result_num_wrong_number_of_cofaces");
|
||||||
|
subelements.push_back("Result_num_unconnected_stars");
|
||||||
|
subelements.push_back("Info");
|
||||||
|
|
||||||
|
return subelements;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_data(const std::string &name, const std::string &value)
|
||||||
|
{
|
||||||
|
m_current_element[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Value_type>
|
||||||
|
void set_data(const std::string &name, Value_type value)
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << value;
|
||||||
|
set_data(name, sstr.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void commit_current_element()
|
||||||
|
{
|
||||||
|
m_xml.add_element(m_current_element);
|
||||||
|
m_current_element.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
XML_exporter m_xml;
|
||||||
|
XML_exporter::Element_with_map m_current_element;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Test_dim
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Test_dim(
|
||||||
|
int min_allowed_dim = 0,
|
||||||
|
int max_allowed_dim = std::numeric_limits<int>::max())
|
||||||
|
: m_min_allowed_dim(min_allowed_dim), m_max_allowed_dim(max_allowed_dim)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename Simplex>
|
||||||
|
bool operator()(Simplex const& s)
|
||||||
|
{
|
||||||
|
return s.size() - 1 >= m_min_allowed_dim
|
||||||
|
&& s.size() - 1 <= m_max_allowed_dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_min_allowed_dim;
|
||||||
|
int m_max_allowed_dim;
|
||||||
|
};
|
||||||
|
|
||||||
|
// color_inconsistencies: only works if p_complex = NULL
|
||||||
|
template <typename TC>
|
||||||
|
bool export_to_off(
|
||||||
|
TC const& tc,
|
||||||
|
std::string const& input_name_stripped,
|
||||||
|
std::string const& suffix,
|
||||||
|
bool color_inconsistencies = false,
|
||||||
|
typename TC::Simplicial_complex const* p_complex = NULL,
|
||||||
|
std::set<std::set<std::size_t> > const *p_simpl_to_color_in_red = NULL,
|
||||||
|
std::set<std::set<std::size_t> > const *p_simpl_to_color_in_green = NULL,
|
||||||
|
std::set<std::set<std::size_t> > const *p_simpl_to_color_in_blue = NULL)
|
||||||
|
{
|
||||||
|
#ifdef TC_NO_EXPORT
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Kernel k;
|
||||||
|
FT center_pt[] = { -0.5, -CGAL::sqrt(3.) / 2, -0.5, CGAL::sqrt(3.) / 2 };
|
||||||
|
FT proj_pt[] = { 0., 0., 0., 0.2 };
|
||||||
|
S3_to_R3_stereographic_projection<Kernel>
|
||||||
|
proj_functor(0.2,
|
||||||
|
Point(4, ¢er_pt[0], ¢er_pt[4]),
|
||||||
|
k);
|
||||||
|
#else
|
||||||
|
CGAL::Identity<Point> proj_functor;
|
||||||
|
//Kernel k;
|
||||||
|
//std::array<int, 3> sel = { 1, 3, 5 };
|
||||||
|
//Orthogonal_projection<Kernel> proj_functor(sel, k);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tc.intrinsic_dimension() <= 3)
|
||||||
|
{
|
||||||
|
std::stringstream output_filename;
|
||||||
|
output_filename << "output/" << input_name_stripped << "_"
|
||||||
|
<< tc.intrinsic_dimension() << "_in_R"
|
||||||
|
<< tc.ambient_dimension() << "_"
|
||||||
|
<< tc.number_of_vertices() << "v"
|
||||||
|
<< suffix << ".off";
|
||||||
|
std::ofstream off_stream(output_filename.str().c_str());
|
||||||
|
|
||||||
|
if (p_complex)
|
||||||
|
{
|
||||||
|
#ifndef TC_NO_EXPORT
|
||||||
|
tc.export_to_off(
|
||||||
|
*p_complex, off_stream,
|
||||||
|
p_simpl_to_color_in_red,
|
||||||
|
p_simpl_to_color_in_green,
|
||||||
|
p_simpl_to_color_in_blue,
|
||||||
|
proj_functor);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*#ifdef CGAL_ALPHA_TC
|
||||||
|
TC::Simplicial_complex complex;
|
||||||
|
tc.export_TC(complex, false);
|
||||||
|
tc.export_to_off(
|
||||||
|
complex, off_stream,
|
||||||
|
p_simpl_to_color_in_red,
|
||||||
|
p_simpl_to_color_in_green,
|
||||||
|
p_simpl_to_color_in_blue);
|
||||||
|
#else*/
|
||||||
|
tc.export_to_off(
|
||||||
|
off_stream, color_inconsistencies,
|
||||||
|
p_simpl_to_color_in_red,
|
||||||
|
p_simpl_to_color_in_green,
|
||||||
|
p_simpl_to_color_in_blue,
|
||||||
|
NULL,
|
||||||
|
proj_functor);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_tc(std::vector<Point> &points,
|
||||||
|
TC::TS_container const& tangent_spaces, // can be empty
|
||||||
|
int intrinsic_dim,
|
||||||
|
bool sparsify = true,
|
||||||
|
double sparsity = 0.01,
|
||||||
|
bool perturb = true,
|
||||||
|
bool add_high_dim_simpl = false,
|
||||||
|
bool collapse = false,
|
||||||
|
double time_limit_for_perturb = 0.,
|
||||||
|
const char *input_name = "tc")
|
||||||
|
{
|
||||||
|
Kernel k;
|
||||||
|
|
||||||
|
if (sparsify && !tangent_spaces.empty())
|
||||||
|
{
|
||||||
|
std::cerr << "Error: cannot sparsify point set with pre-computed normals.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CJTODO TEMP TEST
|
||||||
|
//TC::Simplicial_complex compl;
|
||||||
|
//{std::size_t ss[] = {0, 1, 2}; compl.add_simplex(std::set<std::size_t>(ss, ss + 3)); }
|
||||||
|
//{std::size_t ss[] = {0, 2, 3}; compl.add_simplex(std::set<std::size_t>(ss, ss + 3)); }
|
||||||
|
//{std::size_t ss[] = {0, 3, 4}; compl.add_simplex(std::set<std::size_t>(ss, ss + 3)); }
|
||||||
|
//{std::size_t ss[] = {0, 4, 1}; compl.add_simplex(std::set<std::size_t>(ss, ss + 3)); }
|
||||||
|
//{std::size_t ss[] = {0, 5, 6}; compl.add_simplex(std::set<std::size_t>(ss, ss + 3)); }
|
||||||
|
//compl.is_pure_pseudomanifold(2, 7, false, 10);
|
||||||
|
|
||||||
|
//TC::Simplicial_complex compl;
|
||||||
|
//{std::size_t ss[] = {0, 1, 2, 5}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 2, 3, 5}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 3, 4, 5}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 4, 1, 5}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 1, 2, 6}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 2, 3, 6}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 3, 4, 6}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 4, 1, 6}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//{std::size_t ss[] = {0, 4, 7, 8}; compl.add_simplex(std::set<std::size_t>(ss, ss + 4)); }
|
||||||
|
//compl.is_pure_pseudomanifold(3, 9, false, 10);
|
||||||
|
// /CJTODO TEMP TEST
|
||||||
|
|
||||||
|
#ifdef JUST_BENCHMARK_SPATIAL_SEARCH
|
||||||
|
benchmark_spatial_search(points, k, spatial_search_csv_file);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Init
|
||||||
|
//===========================================================================
|
||||||
|
Wall_clock_timer t;
|
||||||
|
|
||||||
|
// Get input_name_stripped
|
||||||
|
std::string input_name_stripped(input_name);
|
||||||
|
size_t slash_index = input_name_stripped.find_last_of('/');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = input_name_stripped.find_last_of('\\');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = 0;
|
||||||
|
else
|
||||||
|
++slash_index;
|
||||||
|
input_name_stripped = input_name_stripped.substr(
|
||||||
|
slash_index, input_name_stripped.find_last_of('.') - slash_index);
|
||||||
|
|
||||||
|
int ambient_dim = k.point_dimension_d_object()(*points.begin());
|
||||||
|
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size());
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
|
||||||
|
std::vector<Point> points_not_sparse = points;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Sparsify point set if requested
|
||||||
|
//===========================================================================
|
||||||
|
if (sparsify)
|
||||||
|
{
|
||||||
|
std::size_t num_points_before = points.size();
|
||||||
|
points = sparsify_point_set(k, points, sparsity*sparsity);
|
||||||
|
std::cerr << "Number of points before/after sparsification: "
|
||||||
|
<< num_points_before << " / " << points.size() << "\n";
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_EXPORT_SPARSIFIED_POINT_SET
|
||||||
|
std::ofstream ps_stream("output/sparsified_point_set.txt");
|
||||||
|
export_point_set(k, points, ps_stream);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TC_PROTECT_POINT_SET_DELTA
|
||||||
|
// CJTODO TEST
|
||||||
|
# ifdef CGAL_TC_PROFILING
|
||||||
|
Wall_clock_timer t_protection;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
std::vector<Point> points2;
|
||||||
|
std::vector<int> dummy;
|
||||||
|
std::vector<std::vector<int> > dummy2;
|
||||||
|
landmark_choice_protected_delaunay(
|
||||||
|
points, points.size(), points2, dummy, TC_PROTECT_POINT_SET_DELTA, dummy2, false, true);
|
||||||
|
points = points2;
|
||||||
|
|
||||||
|
# ifdef CGAL_TC_PROFILING
|
||||||
|
std::cerr << "Point set protected in " << t_protection.elapsed()
|
||||||
|
<< " seconds.\n";
|
||||||
|
# endif
|
||||||
|
|
||||||
|
std::cerr << "Number of points after PROTECTION: " << points.size() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Num_points", points.size());
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Compute Tangential Complex
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
|
||||||
|
TC tc(points.begin(), points.end(), sparsity, intrinsic_dim,
|
||||||
|
points_not_sparse.begin(), points_not_sparse.end(), k);
|
||||||
|
#else
|
||||||
|
TC tc(points.begin(), points.end(), sparsity, intrinsic_dim, k);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!tangent_spaces.empty())
|
||||||
|
{
|
||||||
|
tc.set_tangent_planes(tangent_spaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
double init_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
tc.compute_tangential_complex();
|
||||||
|
double computation_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
#ifdef CHECK_IF_ALL_SIMPLICES_ARE_IN_THE_AMBIENT_DELAUNAY
|
||||||
|
if (ambient_dim <= 4)
|
||||||
|
tc.check_if_all_simplices_are_in_the_ambient_delaunay();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//tc.check_correlation_between_inconsistencies_and_fatness();
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Export to OFF
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
// Create complex
|
||||||
|
int max_dim = -1;
|
||||||
|
TC::Simplicial_complex complex;
|
||||||
|
std::set<std::set<std::size_t> > inconsistent_simplices;
|
||||||
|
max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices);
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
double export_before_time =
|
||||||
|
(export_to_off(tc, input_name_stripped, "_INITIAL_TC", true,
|
||||||
|
&complex, &inconsistent_simplices) ? t.elapsed() : -1);
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
unsigned int num_perturb_steps = 0;
|
||||||
|
double perturb_time = -1;
|
||||||
|
double export_after_perturb_time = -1.;
|
||||||
|
CGAL::Fix_inconsistencies_status perturb_ret = CGAL::FIX_NOT_PERFORMED;
|
||||||
|
if (perturb)
|
||||||
|
{
|
||||||
|
//=========================================================================
|
||||||
|
// Try to fix inconsistencies by perturbing points
|
||||||
|
//=========================================================================
|
||||||
|
t.reset();
|
||||||
|
std::size_t initial_num_inconsistent_local_tr;
|
||||||
|
std::size_t best_num_inconsistent_local_tr;
|
||||||
|
std::size_t final_num_inconsistent_local_tr;
|
||||||
|
perturb_ret = tc.fix_inconsistencies_using_perturbation(
|
||||||
|
num_perturb_steps, initial_num_inconsistent_local_tr,
|
||||||
|
best_num_inconsistent_local_tr, final_num_inconsistent_local_tr,
|
||||||
|
time_limit_for_perturb);
|
||||||
|
perturb_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr",
|
||||||
|
initial_num_inconsistent_local_tr);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr",
|
||||||
|
best_num_inconsistent_local_tr);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr",
|
||||||
|
final_num_inconsistent_local_tr);
|
||||||
|
|
||||||
|
//tc.check_correlation_between_inconsistencies_and_fatness();
|
||||||
|
|
||||||
|
// DEBUGGING: confirm that all stars were actually refreshed
|
||||||
|
//std::cerr << yellow << "FINAL CHECK...\n" << white;
|
||||||
|
//std::size_t num_inc = tc.number_of_inconsistent_simplices(true).second;
|
||||||
|
//tc.refresh_tangential_complex();
|
||||||
|
//if (CGAL::cpp11::get<1>(tc.number_of_inconsistent_simplices(true)) != num_inc)
|
||||||
|
// std::cerr << red << "FINAL CHECK: FAILED.\n" << white;
|
||||||
|
//else
|
||||||
|
// std::cerr << green << "FINAL CHECK: PASSED.\n" << white;
|
||||||
|
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Export to OFF
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
// Re-build the complex
|
||||||
|
std::set<std::set<std::size_t> > inconsistent_simplices;
|
||||||
|
max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices);
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
bool exported = export_to_off(
|
||||||
|
tc, input_name_stripped, "_AFTER_FIX", true, &complex,
|
||||||
|
&inconsistent_simplices);
|
||||||
|
double export_after_perturb_time = (exported ? t.elapsed() : -1);
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
//std::string fn = "output/inc_stars/";
|
||||||
|
//fn += input_name_stripped;
|
||||||
|
//tc.export_inconsistent_stars_to_OFF_files(fn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", "N/A");
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A");
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
// CJTODO TEST
|
||||||
|
//tc.check_and_solve_inconsistencies_by_filtering_simplices_out();
|
||||||
|
|
||||||
|
double fix2_time = -1;
|
||||||
|
double export_after_fix2_time = -1.;
|
||||||
|
if (add_high_dim_simpl)
|
||||||
|
{
|
||||||
|
//=========================================================================
|
||||||
|
// Try to fix inconsistencies by adding higher-dimension simplices
|
||||||
|
//=========================================================================
|
||||||
|
t.reset();
|
||||||
|
// Try to solve the remaining inconstencies
|
||||||
|
#ifdef CGAL_ALPHA_TC
|
||||||
|
tc.solve_inconsistencies_using_alpha_TC();
|
||||||
|
#else
|
||||||
|
tc.check_and_solve_inconsistencies_by_adding_higher_dim_simplices();
|
||||||
|
#endif
|
||||||
|
fix2_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
/*std::set<std::set<std::size_t> > not_delaunay_simplices;
|
||||||
|
if (ambient_dim <= 4)
|
||||||
|
{
|
||||||
|
tc.check_if_all_simplices_are_in_the_ambient_delaunay(
|
||||||
|
&complex, true, ¬_delaunay_simplices);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Export to OFF
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
// Re-build the complex
|
||||||
|
std::set<std::set<std::size_t> > inconsistent_simplices;
|
||||||
|
max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices);
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
bool exported = export_to_off(
|
||||||
|
tc, input_name_stripped, "_AFTER_FIX2", false, &complex,
|
||||||
|
&inconsistent_simplices);
|
||||||
|
double export_after_fix2_time = (exported ? t.elapsed() : -1);
|
||||||
|
t.reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::set<std::set<std::size_t> > inconsistent_simplices;
|
||||||
|
max_dim = tc.export_TC(complex, false, 2, &inconsistent_simplices);
|
||||||
|
}
|
||||||
|
|
||||||
|
complex.display_stats();
|
||||||
|
|
||||||
|
if (intrinsic_dim == 2)
|
||||||
|
complex.euler_characteristic(true);
|
||||||
|
|
||||||
|
// CJTODO TEMP: Export to OFF with higher-dim simplices colored
|
||||||
|
/*std::set<std::set<std::size_t> > higher_dim_simplices;
|
||||||
|
complex.get_simplices_matching_test(
|
||||||
|
Test_dim(intrinsic_dim + 1),
|
||||||
|
std::inserter(higher_dim_simplices, higher_dim_simplices.begin()));
|
||||||
|
export_to_off(
|
||||||
|
tc, input_name_stripped, "_BEFORE_COLLAPSE", false, &complex,
|
||||||
|
&inconsistent_simplices, &higher_dim_simplices);*/
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Collapse
|
||||||
|
//===========================================================================
|
||||||
|
if (collapse)
|
||||||
|
{
|
||||||
|
complex.collapse(max_dim);
|
||||||
|
complex.display_stats();
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Is the result a pure pseudomanifold?
|
||||||
|
//===========================================================================
|
||||||
|
std::size_t num_wrong_dim_simplices,
|
||||||
|
num_wrong_number_of_cofaces,
|
||||||
|
num_unconnected_stars;
|
||||||
|
std::set<std::set<std::size_t> > wrong_dim_simplices;
|
||||||
|
std::set<std::set<std::size_t> > wrong_number_of_cofaces_simplices;
|
||||||
|
std::set<std::set<std::size_t> > unconnected_stars_simplices;
|
||||||
|
bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold(
|
||||||
|
intrinsic_dim, tc.number_of_vertices(),
|
||||||
|
#ifdef CGAL_TC_ALVAREZ_SURFACE_WINDOW
|
||||||
|
true, // allow borders
|
||||||
|
#else
|
||||||
|
false, // do NOT allow borders
|
||||||
|
#endif
|
||||||
|
false, 1,
|
||||||
|
&num_wrong_dim_simplices, &num_wrong_number_of_cofaces,
|
||||||
|
&num_unconnected_stars,
|
||||||
|
&wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
|
||||||
|
&unconnected_stars_simplices);
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Export to OFF
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
double export_after_collapse_time = -1.;
|
||||||
|
if (collapse)
|
||||||
|
{
|
||||||
|
t.reset();
|
||||||
|
bool exported = export_to_off(
|
||||||
|
tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex,
|
||||||
|
&wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
|
||||||
|
&unconnected_stars_simplices);
|
||||||
|
std::cerr
|
||||||
|
<< " OFF colors:\n"
|
||||||
|
<< " * Red: wrong dim simplices\n"
|
||||||
|
<< " * Green: wrong number of cofaces simplices\n"
|
||||||
|
<< " * Blue: not-connected stars\n";
|
||||||
|
double export_after_collapse_time = (exported ? t.elapsed() : -1.);
|
||||||
|
t.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Display info
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
std::cerr
|
||||||
|
<< "\n================================================\n"
|
||||||
|
<< "Number of vertices: " << tc.number_of_vertices() << "\n"
|
||||||
|
<< "Computation times (seconds): \n"
|
||||||
|
<< " * Tangential complex: " << init_time + computation_time << "\n"
|
||||||
|
<< " - Init + kd-tree = " << init_time << "\n"
|
||||||
|
<< " - TC computation = " << computation_time << "\n"
|
||||||
|
<< " * Export to OFF (before perturb): " << export_before_time << "\n"
|
||||||
|
<< " * Fix inconsistencies 1: " << perturb_time
|
||||||
|
<< " (" << num_perturb_steps << " steps) ==> "
|
||||||
|
<< (perturb_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << "\n"
|
||||||
|
<< " * Fix inconsistencies 2: " << fix2_time << "\n"
|
||||||
|
<< " * Export to OFF (after perturb): " << export_after_perturb_time << "\n"
|
||||||
|
<< " * Export to OFF (after fix2): "<< export_after_fix2_time << "\n"
|
||||||
|
<< " * Export to OFF (after collapse): "
|
||||||
|
<< export_after_collapse_time << "\n"
|
||||||
|
<< "================================================\n";
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
// Export info
|
||||||
|
//===========================================================================
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Perturb_successful",
|
||||||
|
(perturb_ret == CGAL::TC_FIXED ? "Y" : "N"));
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Perturb_time", perturb_time);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Perturb_steps", num_perturb_steps);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Add_higher_dim_simpl_time", fix2_time);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Result_pure_pseudomanifold",
|
||||||
|
(is_pure_pseudomanifold ? "Y" : "N"));
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Result_num_wrong_dim_simplices",
|
||||||
|
num_wrong_dim_simplices);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Result_num_wrong_number_of_cofaces",
|
||||||
|
num_wrong_number_of_cofaces);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Result_num_unconnected_stars",
|
||||||
|
num_unconnected_stars);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Info", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CGAL::set_error_behaviour(CGAL::ABORT);
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# ifdef _DEBUG
|
||||||
|
int num_threads = 1;
|
||||||
|
# else
|
||||||
|
int num_threads = 8;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int seed = static_cast<unsigned int>(time(NULL));
|
||||||
|
CGAL::default_random = CGAL::Random(seed);
|
||||||
|
std::cerr << "Random seed = " << seed << "\n";
|
||||||
|
|
||||||
|
std::ifstream script_file;
|
||||||
|
script_file.open(BENCHMARK_SCRIPT_FILENAME);
|
||||||
|
// Script?
|
||||||
|
// Script file format: each line gives
|
||||||
|
// - Filename (point set) or "generate_XXX" (point set generation)
|
||||||
|
// - Ambient dim
|
||||||
|
// - Intrinsic dim
|
||||||
|
// - Number of iterations with these parameters
|
||||||
|
if (script_file.is_open())
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# ifdef BENCHMARK_WITH_1_TO_MAX_THREADS
|
||||||
|
for(num_threads = 1 ;
|
||||||
|
num_threads <= tbb::task_scheduler_init::default_num_threads() ;
|
||||||
|
++num_threads)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
/*for (Concurrent_mesher_config::get().num_work_items_per_batch = 5 ;
|
||||||
|
Concurrent_mesher_config::get().num_work_items_per_batch < 100 ;
|
||||||
|
Concurrent_mesher_config::get().num_work_items_per_batch += 5)*/
|
||||||
|
{
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
tbb::task_scheduler_init init(
|
||||||
|
num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found.\n";
|
||||||
|
script_file.seekg(0);
|
||||||
|
while (script_file.good())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
std::getline(script_file, line);
|
||||||
|
if (line.size() > 1 && line[0] != '#')
|
||||||
|
{
|
||||||
|
boost::replace_all(line, "\t", " ");
|
||||||
|
boost::trim_all(line);
|
||||||
|
std::cerr << "\n\n";
|
||||||
|
std::cerr << "*****************************************\n";
|
||||||
|
std::cerr << "******* " << line << "\n";
|
||||||
|
std::cerr << "*****************************************\n";
|
||||||
|
std::stringstream sstr(line);
|
||||||
|
|
||||||
|
std::string input;
|
||||||
|
std::string param1;
|
||||||
|
std::string param2;
|
||||||
|
std::string param3;
|
||||||
|
std::size_t num_points;
|
||||||
|
int ambient_dim;
|
||||||
|
int intrinsic_dim;
|
||||||
|
char sparsify;
|
||||||
|
double sparsity;
|
||||||
|
char perturb, add_high_dim_simpl, collapse;
|
||||||
|
double time_limit_for_perturb;
|
||||||
|
int num_iteration;
|
||||||
|
sstr >> input;
|
||||||
|
sstr >> param1;
|
||||||
|
sstr >> param2;
|
||||||
|
sstr >> param3;
|
||||||
|
sstr >> num_points;
|
||||||
|
sstr >> ambient_dim;
|
||||||
|
sstr >> intrinsic_dim;
|
||||||
|
sstr >> sparsify;
|
||||||
|
sstr >> sparsity;
|
||||||
|
sstr >> perturb;
|
||||||
|
sstr >> add_high_dim_simpl;
|
||||||
|
sstr >> collapse;
|
||||||
|
sstr >> time_limit_for_perturb;
|
||||||
|
sstr >> num_iteration;
|
||||||
|
|
||||||
|
for (int j = 0 ; j < num_iteration ; ++j)
|
||||||
|
{
|
||||||
|
std::string input_stripped = input;
|
||||||
|
size_t slash_index = input_stripped.find_last_of('/');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = input_stripped.find_last_of('\\');
|
||||||
|
if (slash_index == std::string::npos)
|
||||||
|
slash_index = 0;
|
||||||
|
else
|
||||||
|
++slash_index;
|
||||||
|
input_stripped = input_stripped.substr(
|
||||||
|
slash_index, input_stripped.find_last_of('.') - slash_index);
|
||||||
|
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Input", input_stripped);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", ambient_dim);
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", intrinsic_dim);
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA(
|
||||||
|
"Num_threads",
|
||||||
|
(num_threads == -1 ? tbb::task_scheduler_init::default_num_threads() : num_threads));
|
||||||
|
#else
|
||||||
|
CGAL_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cerr << "\nTC #" << i << "...\n";
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
Wall_clock_timer t_gen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
TC::TS_container tangent_spaces;
|
||||||
|
|
||||||
|
if (input == "generate_moment_curve")
|
||||||
|
{
|
||||||
|
points = generate_points_on_moment_curve<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_plane")
|
||||||
|
{
|
||||||
|
points = generate_points_on_plane<Kernel>(
|
||||||
|
num_points, intrinsic_dim, ambient_dim);
|
||||||
|
}
|
||||||
|
else if (input == "generate_sphere_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_sphere_d<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()), // radius
|
||||||
|
std::atof(param2.c_str())); // radius_noise_percentage
|
||||||
|
}
|
||||||
|
else if (input == "generate_two_spheres_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_two_spheres_d<Kernel>(
|
||||||
|
num_points, ambient_dim,
|
||||||
|
std::atof(param1.c_str()),
|
||||||
|
std::atof(param2.c_str()),
|
||||||
|
std::atof(param3.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_3sphere_and_circle_d")
|
||||||
|
{
|
||||||
|
CGAL_assertion(intrinsic_dim == 3);
|
||||||
|
CGAL_assertion(ambient_dim == 5);
|
||||||
|
points = generate_points_on_3sphere_and_circle<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_torus_3D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_torus_3D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()),
|
||||||
|
std::atof(param2.c_str()),
|
||||||
|
param3 == "Y");
|
||||||
|
}
|
||||||
|
else if (input == "generate_torus_d")
|
||||||
|
{
|
||||||
|
points = generate_points_on_torus_d<Kernel>(
|
||||||
|
num_points,
|
||||||
|
intrinsic_dim,
|
||||||
|
param1 == "Y", // uniform
|
||||||
|
std::atof(param2.c_str())); // radius_noise_percentage
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_3D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_3D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_4D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_4D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else if (input == "generate_klein_bottle_variant_5D")
|
||||||
|
{
|
||||||
|
points = generate_points_on_klein_bottle_variant_5D<Kernel>(
|
||||||
|
num_points,
|
||||||
|
std::atof(param1.c_str()), std::atof(param2.c_str()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
load_points_from_file<Kernel, typename TC::Tangent_space_basis>(
|
||||||
|
input, std::back_inserter(points),
|
||||||
|
std::back_inserter(tangent_spaces),
|
||||||
|
ONLY_LOAD_THE_FIRST_N_POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
std::cerr << "Point set generated/loaded in " << t_gen.elapsed()
|
||||||
|
<< " seconds.\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!points.empty())
|
||||||
|
{
|
||||||
|
#if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1
|
||||||
|
auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES); // CJTODO C++11 (auto)
|
||||||
|
std::vector<Point> points(p.begin(), p.end());
|
||||||
|
std::cerr << "****************************************\n"
|
||||||
|
<< "WARNING: taking 1 point every " << TC_INPUT_STRIDES
|
||||||
|
<< " points.\n"
|
||||||
|
<< "****************************************\n";
|
||||||
|
#endif
|
||||||
|
make_tc(points, tangent_spaces, intrinsic_dim, sparsify=='Y',
|
||||||
|
sparsity, perturb=='Y', add_high_dim_simpl=='Y',
|
||||||
|
collapse=='Y', time_limit_for_perturb, input.c_str());
|
||||||
|
|
||||||
|
std::cerr << "TC #" << i++ << " done.\n";
|
||||||
|
std::cerr << "\n---------------------------------\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "TC #" << i++ << ": no points loaded.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
XML_perf_data::commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script_file.seekg(0);
|
||||||
|
script_file.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
script_file.close();
|
||||||
|
}
|
||||||
|
// Or not script?
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
system("pause");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,400 @@
|
||||||
|
// Copyright (c) 2014 INRIA Sophia-Antipolis (France)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
|
||||||
|
#ifndef POINT_CLOUD_H
|
||||||
|
#define POINT_CLOUD_H
|
||||||
|
|
||||||
|
#include <CGAL/Orthogonal_k_neighbor_search.h>
|
||||||
|
#include <CGAL/Orthogonal_incremental_neighbor_search.h>
|
||||||
|
#include <CGAL/Search_traits.h>
|
||||||
|
#include <CGAL/Search_traits_adapter.h>
|
||||||
|
|
||||||
|
#include <boost/iterator/counting_iterator.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_ANN_IS_AVAILABLE
|
||||||
|
# include <ANN/ANN.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE
|
||||||
|
# include "nanoflann.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Tangential_complex_ {
|
||||||
|
|
||||||
|
template <typename K, typename Point_container_>
|
||||||
|
class Point_cloud_data_structure
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Point_container_::value_type Point;
|
||||||
|
typedef K Kernel;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
typedef CGAL::Search_traits<
|
||||||
|
FT, Point,
|
||||||
|
typename Kernel::Cartesian_const_iterator_d,
|
||||||
|
typename Kernel::Construct_cartesian_const_iterator_d> Traits_base;
|
||||||
|
// using a pointer as a special property map type
|
||||||
|
typedef CGAL::Search_traits_adapter<
|
||||||
|
std::ptrdiff_t, Point*, Traits_base> STraits;
|
||||||
|
|
||||||
|
typedef CGAL::Orthogonal_k_neighbor_search<STraits> K_neighbor_search;
|
||||||
|
typedef typename K_neighbor_search::Tree Tree;
|
||||||
|
typedef typename K_neighbor_search::Distance Distance;
|
||||||
|
typedef typename K_neighbor_search::iterator KNS_iterator;
|
||||||
|
typedef K_neighbor_search KNS_range;
|
||||||
|
|
||||||
|
typedef CGAL::Orthogonal_incremental_neighbor_search<
|
||||||
|
STraits, Distance, CGAL::Sliding_midpoint<STraits>, Tree>
|
||||||
|
Incremental_neighbor_search;
|
||||||
|
typedef typename Incremental_neighbor_search::iterator INS_iterator;
|
||||||
|
typedef Incremental_neighbor_search INS_range;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
Point_cloud_data_structure(Point_container_ const& points)
|
||||||
|
: m_points(points),
|
||||||
|
m_tree(boost::counting_iterator<std::ptrdiff_t>(0),
|
||||||
|
boost::counting_iterator<std::ptrdiff_t>(points.size()),
|
||||||
|
typename Tree::Splitter(),
|
||||||
|
STraits((Point*)&(points[0])) )
|
||||||
|
{
|
||||||
|
// Build the tree now (we don't want to wait for the first query)
|
||||||
|
m_tree.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
template <typename Point_indices_range>
|
||||||
|
Point_cloud_data_structure(
|
||||||
|
Point_container_ const& points,
|
||||||
|
Point_indices_range const& only_these_points)
|
||||||
|
: m_points(points),
|
||||||
|
m_tree(
|
||||||
|
only_these_points.begin(), only_these_points.end(),
|
||||||
|
typename Tree::Splitter(),
|
||||||
|
STraits((Point*)&(points[0])))
|
||||||
|
{
|
||||||
|
// Build the tree now (we don't want to wait for the first query)
|
||||||
|
m_tree.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
Point_cloud_data_structure(
|
||||||
|
Point_container_ const& points,
|
||||||
|
std::size_t begin_idx, std::size_t past_the_end_idx)
|
||||||
|
: m_points(points),
|
||||||
|
m_tree(
|
||||||
|
boost::counting_iterator<std::ptrdiff_t>(begin_idx),
|
||||||
|
boost::counting_iterator<std::ptrdiff_t>(past_the_end_idx),
|
||||||
|
typename Tree::Splitter(),
|
||||||
|
STraits((Point*)&(points[0])) )
|
||||||
|
{
|
||||||
|
// Build the tree now (we don't want to wait for the first query)
|
||||||
|
m_tree.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Point_container_ &points()
|
||||||
|
{
|
||||||
|
return m_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point_container_ &points() const
|
||||||
|
{
|
||||||
|
return m_points;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Be careful, this function invalidates the tree,
|
||||||
|
// which will be recomputed at the next query
|
||||||
|
void insert(std::ptrdiff_t point_idx)
|
||||||
|
{
|
||||||
|
m_tree.insert(point_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
KNS_range query_ANN(const
|
||||||
|
Point &sp,
|
||||||
|
unsigned int k,
|
||||||
|
bool sorted = true) const
|
||||||
|
{
|
||||||
|
// Initialize the search structure, and search all N points
|
||||||
|
// Note that we need to pass the Distance explicitly since it needs to
|
||||||
|
// know the property map
|
||||||
|
K_neighbor_search search(
|
||||||
|
m_tree,
|
||||||
|
sp,
|
||||||
|
k,
|
||||||
|
FT(0),
|
||||||
|
true,
|
||||||
|
Distance_adapter<std::ptrdiff_t,Point*,Euclidean_distance<Traits_base> >(
|
||||||
|
(Point*)&(m_points[0])),
|
||||||
|
sorted);
|
||||||
|
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
INS_range query_incremental_ANN(const Point &sp) const
|
||||||
|
{
|
||||||
|
// Initialize the search structure, and search all N points
|
||||||
|
// Note that we need to pass the Distance explicitly since it needs to
|
||||||
|
// know the property map
|
||||||
|
Incremental_neighbor_search search(
|
||||||
|
m_tree,
|
||||||
|
sp,
|
||||||
|
FT(0),
|
||||||
|
true,
|
||||||
|
Distance_adapter<std::ptrdiff_t,Point*,Euclidean_distance<Traits_base> >(
|
||||||
|
(Point*)&(m_points[0])) );
|
||||||
|
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Point_container_ const& m_points;
|
||||||
|
Tree m_tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//*****************************************************************************
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_NANOFLANN_IS_AVAILABLE
|
||||||
|
|
||||||
|
// "dataset to kd-tree" adaptor class
|
||||||
|
template <typename K, typename Point_container_>
|
||||||
|
class Point_cloud_adaptator__nanoflann
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Point_container_::value_type Point;
|
||||||
|
typedef K Kernel;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
/// The constructor that sets the data set source
|
||||||
|
Point_cloud_adaptator__nanoflann(Point_container_ const& points, Kernel const& k)
|
||||||
|
: m_points(points), m_k(k)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// CRTP helper method
|
||||||
|
inline Point_container_ const& points() const
|
||||||
|
{
|
||||||
|
return m_points;
|
||||||
|
}
|
||||||
|
inline Point_container_& points()
|
||||||
|
{
|
||||||
|
return m_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must return the number of data points
|
||||||
|
inline size_t kdtree_get_point_count() const
|
||||||
|
{
|
||||||
|
return m_points.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the distance between the vector "p1[0:size-1]"
|
||||||
|
// and the data point with index "idx_p2" stored in the class:
|
||||||
|
inline FT kdtree_distance(
|
||||||
|
const FT *p1, const size_t idx_p2, size_t size) const
|
||||||
|
{
|
||||||
|
Point sp(p1, p1 + size);
|
||||||
|
return m_k.squared_distance_d_object()(sp, points()[idx_p2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the dim'th component of the idx'th point in the class:
|
||||||
|
// Since this is inlined and the "dim" argument is typically an
|
||||||
|
// immediate value, the "if/else's" are actually solved at compile time.
|
||||||
|
inline FT kdtree_get_pt(const size_t idx, int dim) const
|
||||||
|
{
|
||||||
|
return m_k.compute_coordinate_d_object()(points()[idx], dim);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional bounding-box computation: return false to default to a standard
|
||||||
|
// bbox computation loop.
|
||||||
|
// Return true if the BBOX was already computed by the class and returned
|
||||||
|
// in "bb" so it can be avoided to redo it again.
|
||||||
|
// Look at bb.size() to find out the expected dimensionality
|
||||||
|
// (e.g. 2 or 3 for point clouds)
|
||||||
|
template <class Bbox>
|
||||||
|
bool kdtree_get_bbox(Bbox &bb) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel const& kernel() const
|
||||||
|
{
|
||||||
|
return m_k;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Point_container_ const& m_points; //!< A const ref to the data set origin
|
||||||
|
Kernel const& m_k; //!< A const ref to the kernel
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename K, typename Point_container_>
|
||||||
|
class Point_cloud_data_structure__nanoflann
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Point_container_::value_type Point;
|
||||||
|
typedef typename K Kernel;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// "points" must not be empty
|
||||||
|
Point_cloud_data_structure__nanoflann(
|
||||||
|
Point_container_ const& points, Kernel const& k)
|
||||||
|
: m_adaptor(points, k),
|
||||||
|
m_kd_tree(k.point_dimension_d_object()(*points.begin()),
|
||||||
|
m_adaptor,
|
||||||
|
nanoflann::KDTreeSingleIndexAdaptorParams(10 /* max leaf */) )
|
||||||
|
{
|
||||||
|
m_kd_tree.buildIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Point_container_ &points()
|
||||||
|
{
|
||||||
|
return m_adaptor.points();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point_container_ &points() const
|
||||||
|
{
|
||||||
|
return m_adaptor.points();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void query_ANN(const Point &sp,
|
||||||
|
std::size_t k,
|
||||||
|
size_t *neighbor_indices,
|
||||||
|
FT *squared_distance) const
|
||||||
|
{
|
||||||
|
std::vector<FT> sp_vec(
|
||||||
|
m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp),
|
||||||
|
m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));
|
||||||
|
nanoflann::KNNResultSet<FT> result_set(k);
|
||||||
|
result_set.init(neighbor_indices, squared_distance);
|
||||||
|
m_kd_tree.findNeighbors(result_set,
|
||||||
|
&sp_vec[0],
|
||||||
|
nanoflann::SearchParams());
|
||||||
|
|
||||||
|
/*std::cout << "knnSearch(nn="<< num_results <<"): \n";
|
||||||
|
for (int i = 0 ; i < num_results ; ++i)
|
||||||
|
{
|
||||||
|
std::cout << " * neighbor_indices = " << neighbor_indices [i]
|
||||||
|
<< " (out_dist_sqr = " << squared_distance[i] << ")"
|
||||||
|
<< std::endl;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_ball(const Point &sp,
|
||||||
|
const FT radius,
|
||||||
|
std::vector<std::pair<std::size_t, FT> > &neighbors,
|
||||||
|
bool sort_output = true)
|
||||||
|
{
|
||||||
|
std::vector<FT> sp_vec(
|
||||||
|
m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp),
|
||||||
|
m_adaptor.kernel().construct_cartesian_const_iterator_d_object()(sp, 0));
|
||||||
|
m_kd_tree.radiusSearch(&sp_vec[0],
|
||||||
|
radius,
|
||||||
|
neighbors,
|
||||||
|
nanoflann::SearchParams(32, 0.f, sort_output));
|
||||||
|
|
||||||
|
/*std::cout << "radiusSearch(num="<< neighbors.size() <<"): \n";
|
||||||
|
for (const auto idx_and_dist : neighbors)
|
||||||
|
{
|
||||||
|
std::cout << " * neighbor_indices = " << idx_and_dist.first
|
||||||
|
<< " (out_dist_sqr = " << idx_and_dist.second << ")"
|
||||||
|
<< std::endl;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef Point_cloud_adaptator__nanoflann<Kernel, Point_container_> Adaptor;
|
||||||
|
typedef nanoflann::KDTreeSingleIndexAdaptor<
|
||||||
|
nanoflann::L2_Simple_Adaptor<FT, Adaptor> ,
|
||||||
|
Adaptor,
|
||||||
|
-1 // dim
|
||||||
|
> Kd_tree;
|
||||||
|
|
||||||
|
Adaptor m_adaptor;
|
||||||
|
Kd_tree m_kd_tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CGAL_TC_NANOFLANN_IS_AVAILABLE
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//*****************************************************************************
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_ANN_IS_AVAILABLE
|
||||||
|
|
||||||
|
template <typename K, typename Point_container_>
|
||||||
|
class Point_cloud_data_structure__ANN
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Point_container_::value_type Point;
|
||||||
|
typedef K Kernel;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
Point_cloud_data_structure__ANN(
|
||||||
|
Point_container_ const& points, Kernel const& k)
|
||||||
|
: m_dim(k.point_dimension_d_object()(*points.begin())),
|
||||||
|
m_k(k),
|
||||||
|
m_points(annAllocPts(points.size(), m_dim)),
|
||||||
|
m_tree(m_points, points.size(), m_dim)
|
||||||
|
{
|
||||||
|
for (int i = 0 ; i < points.size() ; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0 ; j < m_dim ; ++j)
|
||||||
|
m_points[i][j] = m_k.compute_coordinate_d_object()(points[i], j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_ANN(
|
||||||
|
Point const& p,
|
||||||
|
unsigned int k,
|
||||||
|
ANNidxArray neighbors_indices,
|
||||||
|
ANNdistArray neighbors_sq_distances)
|
||||||
|
{
|
||||||
|
// Create an ANN query point
|
||||||
|
ANNpoint query_pt = annAllocPt(m_dim);
|
||||||
|
for (int j = 0 ; j < m_dim ; ++j)
|
||||||
|
query_pt[j] = m_k.compute_coordinate_d_object()(p, j);
|
||||||
|
|
||||||
|
m_tree.annkSearch( // search
|
||||||
|
query_pt, // query point
|
||||||
|
k, // number of near neighbors
|
||||||
|
neighbors_indices, // nearest neighbors (returned)
|
||||||
|
neighbors_sq_distances, // distance (returned)
|
||||||
|
0); // error bound
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int m_dim;
|
||||||
|
Kernel const& m_k;
|
||||||
|
ANNpointArray m_points;
|
||||||
|
ANNkd_tree m_tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CGAL_TC_ANN_IS_AVAILABLE
|
||||||
|
|
||||||
|
} // namespace Tangential_complex_
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // POINT_CLOUD_H
|
||||||
|
|
@ -0,0 +1,288 @@
|
||||||
|
// Copyright (c) 2016 INRIA Sophia-Antipolis (France)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
|
||||||
|
#ifndef CGAL_TC_WRITE_RIB_FILE_H
|
||||||
|
#define CGAL_TC_WRITE_RIB_FILE_H
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Tangential_complex_ {
|
||||||
|
|
||||||
|
template <typename PointRandomAccessRange, typename SimplexRange>
|
||||||
|
class RIB_exporter
|
||||||
|
{
|
||||||
|
typedef typename PointRandomAccessRange::value_type Point;
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::tuple<double, double, double, double> Color; // RGBA
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
RIB_exporter(
|
||||||
|
PointRandomAccessRange const& points,
|
||||||
|
SimplexRange const& simplices,
|
||||||
|
std::ofstream &out,
|
||||||
|
std::string const& rendered_image_filename = "export.tif",
|
||||||
|
bool is_preview = false, // low-quality
|
||||||
|
int image_width = 1920,
|
||||||
|
int image_height = 1080,
|
||||||
|
Color const& triangle_color = std::make_tuple(0., 1., 1., 1.),
|
||||||
|
bool ambient_light = true,
|
||||||
|
double ambient_intensity = 0.20,
|
||||||
|
bool shadow = true,
|
||||||
|
double shadow_intensity = 0.85)
|
||||||
|
: m_points(points),
|
||||||
|
m_simplices(simplices),
|
||||||
|
m_out(out),
|
||||||
|
m_rendered_image_filename(rendered_image_filename),
|
||||||
|
m_is_preview(is_preview),
|
||||||
|
m_image_width(image_width),
|
||||||
|
m_image_height(image_height),
|
||||||
|
m_current_color(0., 0., 0., 0.),
|
||||||
|
m_current_alpha(1),
|
||||||
|
m_triangle_color(triangle_color),
|
||||||
|
m_ambient_light(ambient_light),
|
||||||
|
m_ambient_intensity(ambient_intensity),
|
||||||
|
m_shadow(shadow),
|
||||||
|
m_shadow_intensity(shadow_intensity)
|
||||||
|
{
|
||||||
|
m_out.precision(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_file()
|
||||||
|
{
|
||||||
|
write_header();
|
||||||
|
write_lights();
|
||||||
|
write_triangles();
|
||||||
|
|
||||||
|
m_out << "WorldEnd\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void write_header()
|
||||||
|
{
|
||||||
|
m_out << "Option \"searchpath\" \"shader\" "
|
||||||
|
"\".:./shaders:%PIXIE_SHADERS%:%PIXIEHOME%/shaders\"\n";
|
||||||
|
|
||||||
|
if (m_is_preview)
|
||||||
|
{
|
||||||
|
m_out << "Attribute \"visibility\" \"specular\" 1\n"
|
||||||
|
<< "Attribute \"visibility\" \"transmission\" 1\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_out << "Display \"" << m_rendered_image_filename << "\" \"file\" \"rgb\"\n";
|
||||||
|
|
||||||
|
if (!m_is_preview)
|
||||||
|
{
|
||||||
|
m_out << "Format " << m_image_width << " " << m_image_height << " 1\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double ratio = double(m_image_height) / double(m_image_width);
|
||||||
|
|
||||||
|
int width = (ratio < 1.) ? 300 : int(300. / ratio);
|
||||||
|
int height = (ratio < 1.) ? int(ratio * 300.) : 300;
|
||||||
|
|
||||||
|
m_out << "Format " << width << " " << height << " 1\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (m_image_width > m_image_height)
|
||||||
|
{
|
||||||
|
double ratio = double(m_image_height) / double(m_image_width);
|
||||||
|
m_out << "ScreenWindow -1 1 " << -ratio << " " << ratio << "\n";
|
||||||
|
}
|
||||||
|
else if (m_image_height > m_image_width)
|
||||||
|
{
|
||||||
|
double ratio = double(m_image_width) / double(m_image_height);
|
||||||
|
m_out << "ScreenWindow " << -ratio << " " << ratio << " -1 1\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_out << "Projection \"perspective\" \"fov\" 45\n"
|
||||||
|
<< "Translate 0 0 15\n"
|
||||||
|
<< "PixelSamples 4 4\n"
|
||||||
|
<< "PixelFilter \"catmull-rom\" 3 3\n"
|
||||||
|
<< "ShadingInterpolation \"smooth\"\n"
|
||||||
|
<< "Rotate 180 0 0 1\n"
|
||||||
|
<< "WorldBegin\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_lights()
|
||||||
|
{
|
||||||
|
if (!m_is_preview)
|
||||||
|
{
|
||||||
|
// ShadowLight
|
||||||
|
m_out << "LightSource \"shadowdistant\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
|
||||||
|
<< " \"shadowname\" \"raytrace\" \"intensity\" "
|
||||||
|
<< m_shadow_intensity << "\n";
|
||||||
|
|
||||||
|
// Ambient light
|
||||||
|
m_out << "LightSource \"ambientlight\" 2 \"intensity\" "
|
||||||
|
<< m_ambient_intensity << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_out << "LightSource \"distantLight\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
|
||||||
|
<< " \"intensity\" 0.85\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Background light
|
||||||
|
m_out << "LightSource \"ambientlight\" 99 \"intensity\" 1\n";
|
||||||
|
|
||||||
|
// Turn background light OFF
|
||||||
|
turn_background_light(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void turn_background_light(bool turn_on)
|
||||||
|
{
|
||||||
|
if (!turn_on)
|
||||||
|
{
|
||||||
|
m_out << "Illuminate 1 1" << std::endl;
|
||||||
|
if (!m_is_preview)
|
||||||
|
m_out << "Illuminate 2 1" << std::endl;
|
||||||
|
m_out << "Illuminate 99 0" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_out << "Illuminate 1 0" << std::endl;
|
||||||
|
if (!m_is_preview)
|
||||||
|
m_out << "Illuminate 2 0" << std::endl;
|
||||||
|
m_out << "Illuminate 99 1" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CJTODO
|
||||||
|
void write_background(const Color& color)
|
||||||
|
{
|
||||||
|
write_turn_background_light(false);
|
||||||
|
|
||||||
|
/*m_out << "Surface \"constant\"" << std::endl;
|
||||||
|
write_color(color, false);
|
||||||
|
|
||||||
|
double corner = zmax_ * 2.;
|
||||||
|
double depth_pos = zmax_ * 1.6;
|
||||||
|
|
||||||
|
m_out << "Polygon \"P\" [";
|
||||||
|
m_out << " " << -corner << " " << -corner << " " << depth_pos << " ";
|
||||||
|
m_out << " " << corner << " " << -corner << " " << depth_pos << " ";
|
||||||
|
m_out << " " << corner << " " << corner << " " << depth_pos << " ";
|
||||||
|
m_out << " " << -corner << " " << corner << " " << depth_pos << " ";
|
||||||
|
m_out << "]" << std::endl;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_color(Color const& color, bool use_transparency)
|
||||||
|
{
|
||||||
|
if (m_current_color == color)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_current_color = color;
|
||||||
|
|
||||||
|
// Write opacity data
|
||||||
|
if (use_transparency)
|
||||||
|
write_opacity(std::get<3>(color));
|
||||||
|
|
||||||
|
// Write color data
|
||||||
|
m_out << "Color [ " << std::get<0>(color) << " " << std::get<1>(color)
|
||||||
|
<< " " << std::get<2>(color) << " ]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_opacity(const double alpha)
|
||||||
|
{
|
||||||
|
if (m_current_alpha == alpha)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_current_alpha = alpha;
|
||||||
|
|
||||||
|
// Write opacity data
|
||||||
|
m_out << "Opacity " << alpha << " " << alpha << " " << alpha << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_point(Point const& p)
|
||||||
|
{
|
||||||
|
m_out << " " << p[0] << " " << p[1] << " " << p[2] << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_triangles()
|
||||||
|
{
|
||||||
|
m_out << "Surface \"plastic\" \"Ka\" 0.65 \"Kd\" 0.85 \"Ks\" 0.25 \"roughness\" 0.1" << std::endl;
|
||||||
|
|
||||||
|
for (auto simplex : m_simplices)
|
||||||
|
{
|
||||||
|
std::vector<std::set<std::size_t> > triangles;
|
||||||
|
// Get the triangles composing the simplex
|
||||||
|
combinations(simplex, 3, std::back_inserter(triangles));
|
||||||
|
for (auto const& t : triangles)
|
||||||
|
write_triangle(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PointIndexRange>
|
||||||
|
void write_triangle(PointIndexRange const& t)
|
||||||
|
{
|
||||||
|
// Color
|
||||||
|
write_color(m_triangle_color, true);
|
||||||
|
|
||||||
|
// Triangle
|
||||||
|
m_out << "Polygon \"P\" [";
|
||||||
|
for (auto idx : t)
|
||||||
|
write_point(m_points[idx]);
|
||||||
|
m_out << "]" << std::endl;
|
||||||
|
|
||||||
|
// Edges (will be drawn later on)
|
||||||
|
/*add_edge(p, q, edge_color);
|
||||||
|
add_edge(p, r, edge_color);
|
||||||
|
add_edge(q, r, edge_color);
|
||||||
|
|
||||||
|
// Vertices (will be drawn later on)
|
||||||
|
add_vertex(p, edge_color);
|
||||||
|
add_vertex(q, edge_color);
|
||||||
|
add_vertex(r, edge_color);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
PointRandomAccessRange const& m_points;
|
||||||
|
SimplexRange const& m_simplices;
|
||||||
|
std::ofstream &m_out;
|
||||||
|
std::string m_rendered_image_filename;
|
||||||
|
bool m_is_preview;
|
||||||
|
int m_image_width;
|
||||||
|
int m_image_height;
|
||||||
|
Color m_current_color;
|
||||||
|
Color m_triangle_color;
|
||||||
|
double m_current_alpha;
|
||||||
|
bool m_ambient_light;
|
||||||
|
double m_ambient_intensity;
|
||||||
|
bool m_shadow;
|
||||||
|
double m_shadow_intensity;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Tangential_complex_
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_TC_WRITE_RIB_FILE_H
|
||||||
|
|
@ -0,0 +1,643 @@
|
||||||
|
// Copyright (c) 2014 INRIA Sophia-Antipolis (France)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SIMPLICIAL_COMPLEX_H
|
||||||
|
#define SIMPLICIAL_COMPLEX_H
|
||||||
|
|
||||||
|
#include <CGAL/Tangential_complex/config.h>
|
||||||
|
#include <CGAL/Tangential_complex/utilities.h>
|
||||||
|
#include "CGAL/Tangential_complex/console_color.h"
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
// For is_pure_pseudomanifold
|
||||||
|
#include <boost/graph/graph_traits.hpp>
|
||||||
|
#include <boost/graph/adjacency_list.hpp>
|
||||||
|
#include <boost/graph/connected_components.hpp>
|
||||||
|
#include <boost/container/flat_map.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Tangential_complex_ {
|
||||||
|
|
||||||
|
class Simplicial_complex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::set<std::size_t> Simplex;
|
||||||
|
typedef std::set<Simplex> Simplex_set;
|
||||||
|
|
||||||
|
// If perform_checks = true, the function:
|
||||||
|
// - won't insert the simplex if it is already in a higher dim simplex
|
||||||
|
// - will erase any lower-dim simplices that are faces of the new simplex
|
||||||
|
// Returns true if the simplex was added
|
||||||
|
bool add_simplex(
|
||||||
|
const std::set<std::size_t> &s, bool perform_checks = true)
|
||||||
|
{
|
||||||
|
if (perform_checks)
|
||||||
|
{
|
||||||
|
unsigned int num_pts = static_cast<int>(s.size());
|
||||||
|
std::vector<Complex::iterator> to_erase;
|
||||||
|
bool check_higher_dim_simpl = true;
|
||||||
|
for (Complex::iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
// Check if the simplex is not already in a higher dim simplex
|
||||||
|
if (check_higher_dim_simpl
|
||||||
|
&& it_simplex->size() > num_pts
|
||||||
|
&& std::includes(it_simplex->begin(), it_simplex->end(),
|
||||||
|
s.begin(), s.end()))
|
||||||
|
{
|
||||||
|
// No need to insert it, then
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check if the simplex includes some lower-dim simplices
|
||||||
|
if (it_simplex->size() < num_pts
|
||||||
|
&& std::includes(s.begin(), s.end(),
|
||||||
|
it_simplex->begin(), it_simplex->end()))
|
||||||
|
{
|
||||||
|
to_erase.push_back(it_simplex);
|
||||||
|
// We don't need to check higher-sim simplices any more
|
||||||
|
check_higher_dim_simpl = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::vector<Complex::iterator>::const_iterator it= to_erase.begin();
|
||||||
|
it != to_erase.end() ; ++it)
|
||||||
|
{
|
||||||
|
m_complex.erase(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_complex.insert(s).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore the point coordinates
|
||||||
|
bool load_simplices_from_OFF(const char *filename)
|
||||||
|
{
|
||||||
|
std::ifstream in(filename);
|
||||||
|
if (!in.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Could not open '" << filename << "'" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::getline(in, line); // Skip first line
|
||||||
|
std::size_t num_points, num_triangles, dummy;
|
||||||
|
in >> num_points;
|
||||||
|
in >> num_triangles;
|
||||||
|
std::getline(in, line); // Skip the rest of the line
|
||||||
|
|
||||||
|
// Skip points
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; ++i)
|
||||||
|
std::getline(in, line);
|
||||||
|
|
||||||
|
// Read triangles
|
||||||
|
for (std::size_t i = 0 ; i < num_triangles ; ++i)
|
||||||
|
{
|
||||||
|
in >> dummy;
|
||||||
|
CGAL_assertion(dummy == 3);
|
||||||
|
std::set<std::size_t> tri;
|
||||||
|
std::size_t idx;
|
||||||
|
for (int j = 0 ; j < 3 ; ++j)
|
||||||
|
{
|
||||||
|
in >> idx;
|
||||||
|
tri.insert(idx);
|
||||||
|
}
|
||||||
|
std::getline(in, line); // Skip the rest of the line
|
||||||
|
|
||||||
|
add_simplex(tri, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Simplex_set &simplex_range() const
|
||||||
|
{
|
||||||
|
return m_complex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
return m_complex.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_complex.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Test, typename Output_it>
|
||||||
|
void get_simplices_matching_test(Test test, Output_it out)
|
||||||
|
{
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
if (test(*it_simplex))
|
||||||
|
*out++ = *it_simplex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a simplex S has only one co-face C, we can remove S and C
|
||||||
|
// without changing the topology
|
||||||
|
void collapse(int max_simplex_dim, bool quiet = false)
|
||||||
|
{
|
||||||
|
#ifdef CGAL_TC_VERBOSE
|
||||||
|
if (!quiet)
|
||||||
|
std::cerr << "Collapsing... ";
|
||||||
|
#endif
|
||||||
|
// We note k = max_simplex_dim - 1
|
||||||
|
int k = max_simplex_dim - 1;
|
||||||
|
|
||||||
|
typedef Complex::iterator Simplex_iterator;
|
||||||
|
typedef std::vector<Simplex_iterator> Simplex_iterator_list;
|
||||||
|
typedef std::map<Simplex, Simplex_iterator_list> Cofaces_map;
|
||||||
|
|
||||||
|
std::size_t num_collapsed_maximal_simplices = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
num_collapsed_maximal_simplices = 0;
|
||||||
|
// Create a map associating each non-maximal k-faces to the list of its
|
||||||
|
// maximal cofaces
|
||||||
|
Cofaces_map cofaces_map;
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
if (it_simplex->size() > k + 1)
|
||||||
|
{
|
||||||
|
std::vector<Simplex> k_faces;
|
||||||
|
// Get the k-faces composing the simplex
|
||||||
|
combinations(*it_simplex, k + 1, std::back_inserter(k_faces));
|
||||||
|
for (const auto &comb : k_faces) // CJTODO C++1
|
||||||
|
cofaces_map[comb].push_back(it_simplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each non-maximal k-face F, if F has only one maximal coface Cf:
|
||||||
|
// - Look for the other k-faces F2, F3... of Cf in the map and:
|
||||||
|
// * if the list contains only Cf, clear the list (we don't remove the
|
||||||
|
// list since it creates troubles with the iterators) and add the F2,
|
||||||
|
// F3... to the complex
|
||||||
|
// * otherwise, remove Cf from the associated list
|
||||||
|
// - Remove Cf from the complex
|
||||||
|
for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(),
|
||||||
|
it_map_end = cofaces_map.end() ;
|
||||||
|
it_map_elt != it_map_end ;
|
||||||
|
++it_map_elt)
|
||||||
|
{
|
||||||
|
if (it_map_elt->second.size() == 1)
|
||||||
|
{
|
||||||
|
std::vector<Simplex> k_faces;
|
||||||
|
const Simplex_iterator_list::value_type &it_Cf =
|
||||||
|
*it_map_elt->second.begin();
|
||||||
|
CGAL_assertion(it_Cf->size() == max_simplex_dim + 1);
|
||||||
|
// Get the k-faces composing the simplex
|
||||||
|
combinations(*it_Cf, k + 1, std::back_inserter(k_faces));
|
||||||
|
for (const auto &f2 : k_faces) // CJTODO C++1
|
||||||
|
{
|
||||||
|
// Skip F
|
||||||
|
if (f2 != it_map_elt->first)
|
||||||
|
{
|
||||||
|
Cofaces_map::iterator it_comb_in_map = cofaces_map.find(f2);
|
||||||
|
if (it_comb_in_map->second.size() == 1)
|
||||||
|
{
|
||||||
|
it_comb_in_map->second.clear();
|
||||||
|
m_complex.insert(f2);
|
||||||
|
}
|
||||||
|
else // it_comb_in_map->second.size() > 1
|
||||||
|
{
|
||||||
|
Simplex_iterator_list::iterator it = std::find(
|
||||||
|
it_comb_in_map->second.begin(),
|
||||||
|
it_comb_in_map->second.end(),
|
||||||
|
it_Cf);
|
||||||
|
CGAL_assertion(it != it_comb_in_map->second.end());
|
||||||
|
it_comb_in_map->second.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_complex.erase(it_Cf);
|
||||||
|
++num_collapsed_maximal_simplices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Repeat until no maximal simplex got removed
|
||||||
|
} while (num_collapsed_maximal_simplices > 0);
|
||||||
|
|
||||||
|
// Collapse the lower dimension simplices
|
||||||
|
if (k > 0)
|
||||||
|
collapse(max_simplex_dim - 1, true);
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_VERBOSE
|
||||||
|
if (!quiet)
|
||||||
|
std::cerr << "done.\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_stats() const
|
||||||
|
{
|
||||||
|
std::cerr << yellow << "Complex stats:\n" << white;
|
||||||
|
|
||||||
|
if (m_complex.empty())
|
||||||
|
{
|
||||||
|
std::cerr << " * No simplices.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Number of simplex for each dimension
|
||||||
|
std::map<int, std::size_t> simplex_stats;
|
||||||
|
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
++simplex_stats[static_cast<int>(it_simplex->size()) - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<int, std::size_t>::const_iterator it_map = simplex_stats.begin() ;
|
||||||
|
it_map != simplex_stats.end() ; ++it_map)
|
||||||
|
{
|
||||||
|
std::cerr << " * " << it_map->first << "-simplices: "
|
||||||
|
<< it_map->second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verbose_level = 0, 1 or 2
|
||||||
|
bool is_pure_pseudomanifold__do_not_check_if_stars_are_connected(
|
||||||
|
int simplex_dim,
|
||||||
|
bool allow_borders = false,
|
||||||
|
bool exit_at_the_first_problem = false,
|
||||||
|
int verbose_level = 0,
|
||||||
|
std::size_t *p_num_wrong_dim_simplices = NULL,
|
||||||
|
std::size_t *p_num_wrong_number_of_cofaces = NULL) const
|
||||||
|
{
|
||||||
|
typedef std::set<std::size_t> K_1_face;
|
||||||
|
typedef std::map<K_1_face, std::size_t> Cofaces_map;
|
||||||
|
|
||||||
|
std::size_t num_wrong_dim_simplices = 0;
|
||||||
|
std::size_t num_wrong_number_of_cofaces = 0;
|
||||||
|
|
||||||
|
// Counts the number of cofaces of each K_1_face
|
||||||
|
|
||||||
|
// Create a map associating each non-maximal k-faces to the list of its
|
||||||
|
// maximal cofaces
|
||||||
|
Cofaces_map cofaces_map;
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
if (it_simplex->size() != simplex_dim + 1)
|
||||||
|
{
|
||||||
|
if (verbose_level >= 2)
|
||||||
|
std::cerr << "Found a simplex with dim = "
|
||||||
|
<< it_simplex->size() - 1 << "\n";
|
||||||
|
++num_wrong_dim_simplices;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<K_1_face> k_1_faces;
|
||||||
|
// Get the facets composing the simplex
|
||||||
|
combinations(
|
||||||
|
*it_simplex, simplex_dim, std::back_inserter(k_1_faces));
|
||||||
|
for (const auto &k_1_face : k_1_faces) // CJTODO C++1
|
||||||
|
{
|
||||||
|
++cofaces_map[k_1_face];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Cofaces_map::const_iterator it_map_elt = cofaces_map.begin(),
|
||||||
|
it_map_end = cofaces_map.end() ;
|
||||||
|
it_map_elt != it_map_end ;
|
||||||
|
++it_map_elt)
|
||||||
|
{
|
||||||
|
if (it_map_elt->second != 2
|
||||||
|
&& (!allow_borders || it_map_elt->second != 1))
|
||||||
|
{
|
||||||
|
if (verbose_level >= 2)
|
||||||
|
std::cerr << "Found a k-1-face with "
|
||||||
|
<< it_map_elt->second << " cofaces\n";
|
||||||
|
|
||||||
|
if (exit_at_the_first_problem)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
++num_wrong_number_of_cofaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = num_wrong_dim_simplices == 0 && num_wrong_number_of_cofaces == 0;
|
||||||
|
|
||||||
|
if (verbose_level >= 1)
|
||||||
|
{
|
||||||
|
std::cerr << "Pure pseudo-manifold: ";
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
std::cerr << green << "YES" << white << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << red << "NO" << white << "\n"
|
||||||
|
<< " * Number of wrong dimension simplices: "
|
||||||
|
<< num_wrong_dim_simplices << "\n"
|
||||||
|
<< " * Number of wrong number of cofaces: "
|
||||||
|
<< num_wrong_number_of_cofaces << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_num_wrong_dim_simplices)
|
||||||
|
*p_num_wrong_dim_simplices = num_wrong_dim_simplices;
|
||||||
|
if (p_num_wrong_number_of_cofaces)
|
||||||
|
*p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int K>
|
||||||
|
std::size_t num_K_simplices() const
|
||||||
|
{
|
||||||
|
std::set<Simplex> k_simplices;
|
||||||
|
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
if (it_simplex->size() == K + 1)
|
||||||
|
{
|
||||||
|
k_simplices.insert(*it_simplex);
|
||||||
|
}
|
||||||
|
else if (it_simplex->size() > K + 1)
|
||||||
|
{
|
||||||
|
// Get the k-faces composing the simplex
|
||||||
|
combinations(
|
||||||
|
*it_simplex, K + 1, std::inserter(k_simplices, k_simplices.begin()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return k_simplices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ptrdiff_t euler_characteristic(bool verbose = false) const
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
std::cerr << "\nComputing Euler characteristic of the complex...\n";
|
||||||
|
|
||||||
|
std::size_t num_vertices = num_K_simplices<0>();
|
||||||
|
std::size_t num_edges = num_K_simplices<1>();
|
||||||
|
std::size_t num_triangles = num_K_simplices<2>();
|
||||||
|
|
||||||
|
std::ptrdiff_t ec =
|
||||||
|
(std::ptrdiff_t) num_vertices
|
||||||
|
- (std::ptrdiff_t) num_edges
|
||||||
|
+ (std::ptrdiff_t) num_triangles;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
std::cerr << "Euler characteristic: V - E + F = "
|
||||||
|
<< num_vertices << " - " << num_edges << " + " << num_triangles << " = "
|
||||||
|
<< blue
|
||||||
|
<< ec
|
||||||
|
<< white << "\n";
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CJTODO: ADD COMMENTS
|
||||||
|
bool is_pure_pseudomanifold(
|
||||||
|
int simplex_dim,
|
||||||
|
std::size_t num_vertices,
|
||||||
|
bool allow_borders = false,
|
||||||
|
bool exit_at_the_first_problem = false,
|
||||||
|
int verbose_level = 0,
|
||||||
|
std::size_t *p_num_wrong_dim_simplices = NULL,
|
||||||
|
std::size_t *p_num_wrong_number_of_cofaces = NULL,
|
||||||
|
std::size_t *p_num_unconnected_stars = NULL,
|
||||||
|
Simplex_set *p_wrong_dim_simplices = NULL,
|
||||||
|
Simplex_set *p_wrong_number_of_cofaces_simplices = NULL,
|
||||||
|
Simplex_set *p_unconnected_stars_simplices = NULL) const
|
||||||
|
{
|
||||||
|
// If simplex_dim == 1, we do not need to check if stars are connected
|
||||||
|
if (simplex_dim == 1)
|
||||||
|
{
|
||||||
|
if (p_num_unconnected_stars)
|
||||||
|
*p_num_unconnected_stars = 0;
|
||||||
|
return is_pure_pseudomanifold__do_not_check_if_stars_are_connected(
|
||||||
|
simplex_dim,
|
||||||
|
allow_borders,
|
||||||
|
exit_at_the_first_problem,
|
||||||
|
verbose_level,
|
||||||
|
p_num_wrong_dim_simplices,
|
||||||
|
p_num_wrong_number_of_cofaces);
|
||||||
|
}
|
||||||
|
// Associates each vertex (= the index in the vector)
|
||||||
|
// to its star (list of simplices)
|
||||||
|
typedef std::vector<std::vector<Complex::const_iterator> > Stars;
|
||||||
|
std::size_t num_wrong_dim_simplices = 0;
|
||||||
|
std::size_t num_wrong_number_of_cofaces = 0;
|
||||||
|
std::size_t num_unconnected_stars = 0;
|
||||||
|
|
||||||
|
// Fills a Stars data structure
|
||||||
|
Stars stars;
|
||||||
|
stars.resize(num_vertices);
|
||||||
|
for (Complex::const_iterator it_simplex = m_complex.begin(),
|
||||||
|
it_simplex_end = m_complex.end() ;
|
||||||
|
it_simplex != it_simplex_end ;
|
||||||
|
++it_simplex)
|
||||||
|
{
|
||||||
|
if (it_simplex->size() != simplex_dim + 1)
|
||||||
|
{
|
||||||
|
if (verbose_level >= 2)
|
||||||
|
std::cerr << "Found a simplex with dim = "
|
||||||
|
<< it_simplex->size() - 1 << "\n";
|
||||||
|
++num_wrong_dim_simplices;
|
||||||
|
if (p_wrong_dim_simplices)
|
||||||
|
p_wrong_dim_simplices->insert(*it_simplex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (Simplex::const_iterator it_point_idx = it_simplex->begin() ;
|
||||||
|
it_point_idx != it_simplex->end() ;
|
||||||
|
++it_point_idx)
|
||||||
|
{
|
||||||
|
stars[*it_point_idx].push_back(it_simplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, for each star, we have a vector of its d-simplices
|
||||||
|
// i.e. one index for each d-simplex
|
||||||
|
// Boost Graph only deals with indexes, so we also need indexes for the
|
||||||
|
// (d-1)-simplices
|
||||||
|
std::size_t center_vertex_index = 0;
|
||||||
|
for (Stars::const_iterator it_star = stars.begin() ;
|
||||||
|
it_star != stars.end() ;
|
||||||
|
++it_star, ++center_vertex_index)
|
||||||
|
{
|
||||||
|
typedef std::map<Simplex, std::vector<std::size_t> >
|
||||||
|
Dm1_faces_to_adj_D_faces;
|
||||||
|
Dm1_faces_to_adj_D_faces dm1_faces_to_adj_d_faces;
|
||||||
|
|
||||||
|
for (int i_dsimpl = 0 ; i_dsimpl < it_star->size() ; ++i_dsimpl)
|
||||||
|
{
|
||||||
|
Simplex dm1_simpl_of_link = *((*it_star)[i_dsimpl]);
|
||||||
|
dm1_simpl_of_link.erase(center_vertex_index);
|
||||||
|
// Copy it to a vector so that we can use operator[] on it
|
||||||
|
std::vector<std::size_t> dm1_simpl_of_link_vec(
|
||||||
|
dm1_simpl_of_link.begin(), dm1_simpl_of_link.end());
|
||||||
|
|
||||||
|
CGAL::Combination_enumerator<int> dm2_simplices(
|
||||||
|
simplex_dim - 1, 0, simplex_dim);
|
||||||
|
for ( ; !dm2_simplices.finished() ; ++dm2_simplices)
|
||||||
|
{
|
||||||
|
Simplex dm2_simpl;
|
||||||
|
for (int j = 0 ; j < simplex_dim - 1 ; ++j)
|
||||||
|
dm2_simpl.insert(dm1_simpl_of_link_vec[dm2_simplices[j]]);
|
||||||
|
dm1_faces_to_adj_d_faces[dm2_simpl].push_back(i_dsimpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adj_graph adj_graph;
|
||||||
|
std::vector<Graph_vertex> d_faces_descriptors;
|
||||||
|
d_faces_descriptors.resize(it_star->size());
|
||||||
|
for (int j = 0 ; j < it_star->size() ; ++j)
|
||||||
|
d_faces_descriptors[j] = boost::add_vertex(adj_graph);
|
||||||
|
|
||||||
|
Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it =
|
||||||
|
dm1_faces_to_adj_d_faces.begin();
|
||||||
|
Dm1_faces_to_adj_D_faces::const_iterator dm1_to_d_it_end =
|
||||||
|
dm1_faces_to_adj_d_faces.end();
|
||||||
|
for (std::size_t i_km1_face = 0 ;
|
||||||
|
dm1_to_d_it != dm1_to_d_it_end ;
|
||||||
|
++dm1_to_d_it, ++i_km1_face)
|
||||||
|
{
|
||||||
|
Graph_vertex km1_gv = boost::add_vertex(adj_graph);
|
||||||
|
|
||||||
|
for (std::vector<std::size_t>::const_iterator kface_it =
|
||||||
|
dm1_to_d_it->second.begin() ;
|
||||||
|
kface_it != dm1_to_d_it->second.end() ;
|
||||||
|
++kface_it)
|
||||||
|
{
|
||||||
|
boost::add_edge(km1_gv, *kface_it, adj_graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dm1_to_d_it->second.size() != 2
|
||||||
|
&& (!allow_borders || dm1_to_d_it->second.size() != 1))
|
||||||
|
{
|
||||||
|
++num_wrong_number_of_cofaces;
|
||||||
|
if (p_wrong_number_of_cofaces_simplices)
|
||||||
|
{
|
||||||
|
for (auto idx : dm1_to_d_it->second)
|
||||||
|
p_wrong_number_of_cofaces_simplices->insert(*((*it_star)[idx]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// What is left is to check the connexity
|
||||||
|
bool is_connected = true;
|
||||||
|
if (boost::num_vertices(adj_graph) > 0)
|
||||||
|
{
|
||||||
|
std::vector<int> components(boost::num_vertices(adj_graph));
|
||||||
|
is_connected =
|
||||||
|
(boost::connected_components(adj_graph, &components[0]) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_connected)
|
||||||
|
{
|
||||||
|
if (verbose_level >= 2)
|
||||||
|
std::cerr << "Error: star #" << center_vertex_index
|
||||||
|
<< " is not connected\n";
|
||||||
|
++num_unconnected_stars;
|
||||||
|
if (p_unconnected_stars_simplices)
|
||||||
|
{
|
||||||
|
for (std::vector<Complex::const_iterator>::const_iterator
|
||||||
|
it_simpl = it_star->begin(),
|
||||||
|
it_simpl_end = it_star->end();
|
||||||
|
it_simpl != it_simpl_end ;
|
||||||
|
++it_simpl)
|
||||||
|
{
|
||||||
|
p_unconnected_stars_simplices->insert(**it_simpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each one has been counted several times ("simplex_dim" times)
|
||||||
|
num_wrong_number_of_cofaces /= simplex_dim;
|
||||||
|
|
||||||
|
bool ret =
|
||||||
|
num_wrong_dim_simplices == 0
|
||||||
|
&& num_wrong_number_of_cofaces == 0
|
||||||
|
&& num_unconnected_stars == 0;
|
||||||
|
|
||||||
|
if (verbose_level >= 1)
|
||||||
|
{
|
||||||
|
std::cerr << "Pure pseudo-manifold: ";
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
std::cerr << green << "YES" << white << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << red << "NO" << white << "\n"
|
||||||
|
<< " * Number of wrong dimension simplices: "
|
||||||
|
<< num_wrong_dim_simplices << "\n"
|
||||||
|
<< " * Number of wrong number of cofaces: "
|
||||||
|
<< num_wrong_number_of_cofaces << "\n"
|
||||||
|
<< " * Number of not-connected stars: "
|
||||||
|
<< num_unconnected_stars << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_num_wrong_dim_simplices)
|
||||||
|
*p_num_wrong_dim_simplices = num_wrong_dim_simplices;
|
||||||
|
if (p_num_wrong_number_of_cofaces)
|
||||||
|
*p_num_wrong_number_of_cofaces = num_wrong_number_of_cofaces;
|
||||||
|
if (p_num_unconnected_stars)
|
||||||
|
*p_num_unconnected_stars = num_unconnected_stars;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef Simplex_set Complex;
|
||||||
|
|
||||||
|
// graph is an adjacency list
|
||||||
|
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> Adj_graph;
|
||||||
|
// map that gives to a certain simplex its node in graph and its dimension
|
||||||
|
typedef boost::graph_traits<Adj_graph>::vertex_descriptor Graph_vertex;
|
||||||
|
typedef boost::graph_traits<Adj_graph>::edge_descriptor Graph_edge;
|
||||||
|
|
||||||
|
Complex m_complex;
|
||||||
|
|
||||||
|
}; // /class Simplicial_complex
|
||||||
|
|
||||||
|
} // namespace Tangential_complex_
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // SIMPLICIAL_COMPLEX_H
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright (c) 2014 INRIA Sophia-Antipolis (France)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
|
||||||
|
#ifndef CGAL_TC_CONFIG_H
|
||||||
|
#define CGAL_TC_CONFIG_H
|
||||||
|
|
||||||
|
#include <CGAL/config.h>
|
||||||
|
|
||||||
|
// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false
|
||||||
|
// positives in Intel TBB
|
||||||
|
// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define TBB_USE_THREADING_TOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=========================== Alpha-TC or not? ================================
|
||||||
|
|
||||||
|
//#define CGAL_ALPHA_TC
|
||||||
|
//#define CGAL_USE_A_FIXED_ALPHA
|
||||||
|
const double CGAL_TC_ALPHA_VALUE = 0.3;
|
||||||
|
|
||||||
|
//========================= Debugging & profiling =============================
|
||||||
|
#define CGAL_TC_PROFILING
|
||||||
|
#define CGAL_TC_VERBOSE
|
||||||
|
//#define CGAL_TC_VERY_VERBOSE
|
||||||
|
//#define CGAL_TC_PERFORM_EXTRA_CHECKS
|
||||||
|
#define CGAL_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES
|
||||||
|
|
||||||
|
// Solving inconsistencies: only perturb the vertex, the simplex or more?
|
||||||
|
//#define CGAL_TC_PERTURB_THE_CENTER_VERTEX_ONLY
|
||||||
|
//#define CGAL_TC_PERTURB_THE_SIMPLEX_ONLY
|
||||||
|
//#define CGAL_TC_PERTURB_THE_1_STAR
|
||||||
|
#define CGAL_TC_PERTURB_N_CLOSEST_POINTS // perturb the CGAL_TC_NUMBER_OF_PERTURBED_POINTS closest points
|
||||||
|
// Otherwise, perturb one random point of the simplex
|
||||||
|
|
||||||
|
// Only used if CGAL_TC_PERTURB_N_CLOSEST_POINTS is defined
|
||||||
|
#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (1)
|
||||||
|
//#define CGAL_TC_NUMBER_OF_PERTURBED_POINTS(intr_dim) (intr_dim + 2)
|
||||||
|
|
||||||
|
#define CGAL_MESH_D_PROFILING
|
||||||
|
#define CGAL_MESH_D_VERBOSE
|
||||||
|
|
||||||
|
//========================= Strategy ==========================================
|
||||||
|
#define CGAL_TC_NANOFLANN_IS_AVAILABLE
|
||||||
|
//#define CGAL_TC_ANN_IS_AVAILABLE
|
||||||
|
//#define CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
#define CGAL_TC_GLOBAL_REFRESH
|
||||||
|
//#define CGAL_TC_ON_DEMAND_REFRESH // CJTODO: not implemented yet
|
||||||
|
// The idea is to perform a global refresh + some local refreshes, just
|
||||||
|
// for local tri where there are some inconsistencies
|
||||||
|
// But be careful: refreshing the TC may invalidate cells, so the
|
||||||
|
// incident cells have to be recomputed again
|
||||||
|
#define CGAL_TC_PERTURB_POSITION
|
||||||
|
# define CGAL_TC_PERTURB_POSITION_TANGENTIAL // default
|
||||||
|
//# define CGAL_TC_PERTURB_POSITION_GLOBAL
|
||||||
|
//#define CGAL_TC_PERTURB_WEIGHT
|
||||||
|
//#define CGAL_TC_PERTURB_TANGENT_SPACE
|
||||||
|
|
||||||
|
//========================= Parameters ========================================
|
||||||
|
|
||||||
|
// PCA will use BASE_VALUE_FOR_PCA^intrinsic_dim points
|
||||||
|
const std::size_t BASE_VALUE_FOR_PCA = 5;
|
||||||
|
const unsigned int BASE_VALUE_FOR_ALPHA_TC_NEIGHBORHOOD = 5;
|
||||||
|
|
||||||
|
#endif // CGAL_TC_CONFIG_H
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef CONSOLE_COLOR_H_
|
||||||
|
#define CONSOLE_COLOR_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline std::ostream& blue(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout,
|
||||||
|
FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;34m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& red(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout, FOREGROUND_RED|FOREGROUND_INTENSITY);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;31m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& green(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN|FOREGROUND_INTENSITY);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;32m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& yellow(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout,
|
||||||
|
FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;33m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& white(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout,
|
||||||
|
FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;37m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& black_on_white(std::ostream &s)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
SetConsoleTextAttribute(hStdout,
|
||||||
|
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
||||||
|
#else
|
||||||
|
s << "\x1b[0;33m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,564 @@
|
||||||
|
#ifndef PROTECTED_SETS_H
|
||||||
|
#define PROTECTED_SETS_H
|
||||||
|
|
||||||
|
#include <CGAL/Cartesian_d.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Euclidean_distance.h>
|
||||||
|
#include <CGAL/Kernel_d/Sphere_d.h>
|
||||||
|
#include <CGAL/Kernel_d/Hyperplane_d.h>
|
||||||
|
#include <CGAL/Kernel_d/Vector_d.h>
|
||||||
|
#include <CGAL/Delaunay_triangulation.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <list>
|
||||||
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
|
||||||
|
typedef K::FT FT;
|
||||||
|
typedef K::Point_d Point_d;
|
||||||
|
typedef K::Vector_d Vector_d;
|
||||||
|
typedef K::Oriented_side_d Oriented_side_d;
|
||||||
|
typedef K::Has_on_positive_side_d Has_on_positive_side_d;
|
||||||
|
typedef K::Sphere_d Sphere_d;
|
||||||
|
typedef K::Hyperplane_d Hyperplane_d;
|
||||||
|
|
||||||
|
typedef CGAL::Delaunay_triangulation<K> Delaunay_triangulation;
|
||||||
|
typedef Delaunay_triangulation::Facet Facet;
|
||||||
|
typedef Delaunay_triangulation::Vertex_handle Delaunay_vertex;
|
||||||
|
typedef Delaunay_triangulation::Full_cell_handle Full_cell_handle;
|
||||||
|
|
||||||
|
typedef std::vector<Point_d> Point_Vector;
|
||||||
|
typedef CGAL::Euclidean_distance<K> Euclidean_distance;
|
||||||
|
|
||||||
|
FT _sfty = pow(10,-14);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AUXILLARY FUNCTIONS
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** Insert a point in Delaunay triangulation. If you are working in a flat torus, the procedure adds all the 3^d copies in adjacent cubes as well
|
||||||
|
*
|
||||||
|
* W is the initial point vector
|
||||||
|
* chosen_landmark is the index of the chosen point in W
|
||||||
|
* landmarks_ind is the vector of indices of already chosen points in W
|
||||||
|
* delaunay is the Delaunay triangulation
|
||||||
|
* landmark_count is the current number of chosen vertices
|
||||||
|
* torus is true iff you are working on a flat torus [-1,1]^d
|
||||||
|
* OUT: Vertex handle to the newly inserted point
|
||||||
|
*/
|
||||||
|
Delaunay_vertex insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector<int>& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count, bool torus)
|
||||||
|
{
|
||||||
|
if (!torus)
|
||||||
|
{
|
||||||
|
Delaunay_vertex v =delaunay.insert(W[chosen_landmark]);
|
||||||
|
landmarks_ind.push_back(chosen_landmark);
|
||||||
|
landmark_count++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int D = W[0].size();
|
||||||
|
int nb_cells = pow(3, D);
|
||||||
|
Delaunay_vertex v;
|
||||||
|
for (int i = 0; i < nb_cells; ++i)
|
||||||
|
{
|
||||||
|
std::vector<FT> point;
|
||||||
|
int cell_i = i;
|
||||||
|
for (int l = 0; l < D; ++l)
|
||||||
|
{
|
||||||
|
point.push_back(W[chosen_landmark][l] + 2.0*(cell_i%3-1));
|
||||||
|
cell_i /= 3;
|
||||||
|
}
|
||||||
|
v = delaunay.insert(point);
|
||||||
|
}
|
||||||
|
landmarks_ind.push_back(chosen_landmark);
|
||||||
|
landmark_count++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Small check if the vertex v is in the full cell fc
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool vertex_is_in_full_cell(Delaunay_triangulation::Vertex_handle v, Full_cell_handle fc)
|
||||||
|
{
|
||||||
|
for (auto v_it = fc->vertices_begin(); v_it != fc->vertices_end(); ++v_it)
|
||||||
|
if (*v_it == v)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fill chosen point vector from indices with copies if you are working on a flat torus
|
||||||
|
*
|
||||||
|
* IN: W is the point vector
|
||||||
|
* OUT: landmarks is the output vector
|
||||||
|
* IN: landmarks_ind is the vector of indices
|
||||||
|
* IN: torus is true iff you are working on a flat torus [-1,1]^d
|
||||||
|
*/
|
||||||
|
|
||||||
|
void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector<int>& landmarks_ind, bool torus)
|
||||||
|
{
|
||||||
|
if (!torus)
|
||||||
|
for (unsigned j = 0; j < landmarks_ind.size(); ++j)
|
||||||
|
landmarks.push_back(W[landmarks_ind[j]]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int D = W[0].size();
|
||||||
|
int nb_cells = pow(3, D);
|
||||||
|
int nbL = landmarks_ind.size();
|
||||||
|
// Fill landmarks
|
||||||
|
for (int i = 0; i < nb_cells-1; ++i)
|
||||||
|
for (int j = 0; j < nbL; ++j)
|
||||||
|
{
|
||||||
|
int cell_i = i;
|
||||||
|
Point_d point;
|
||||||
|
for (int l = 0; l < D; ++l)
|
||||||
|
{
|
||||||
|
point.push_back(W[landmarks_ind[j]][l] + 2.0*(cell_i-1));
|
||||||
|
cell_i /= 3;
|
||||||
|
}
|
||||||
|
landmarks.push_back(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fill a vector of all simplices in the Delaunay triangulation giving integer indices to vertices
|
||||||
|
*
|
||||||
|
* IN: t is the Delaunay triangulation
|
||||||
|
* OUT: full_cells is the output vector
|
||||||
|
*/
|
||||||
|
|
||||||
|
void fill_full_cell_vector(Delaunay_triangulation& t, std::vector<std::vector<int>>& full_cells)
|
||||||
|
{
|
||||||
|
// Store vertex indices in a map
|
||||||
|
int ind = 0; //index of a vertex
|
||||||
|
std::map<Delaunay_triangulation::Vertex_handle, int> index_of_vertex;
|
||||||
|
for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
|
||||||
|
if (t.is_infinite(v_it))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
index_of_vertex[v_it] = ind++;
|
||||||
|
// Write full cells as vectors in full_cells
|
||||||
|
for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it)
|
||||||
|
{
|
||||||
|
if (t.is_infinite(fc_it))
|
||||||
|
continue;
|
||||||
|
Point_Vector vertices;
|
||||||
|
for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it)
|
||||||
|
vertices.push_back((*fc_v_it)->point());
|
||||||
|
Sphere_d cs( vertices.begin(), vertices.end());
|
||||||
|
Point_d csc = cs.center();
|
||||||
|
bool in_cube = true;
|
||||||
|
for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi)
|
||||||
|
if (*xi > 1.0 || *xi < -1.0)
|
||||||
|
{
|
||||||
|
in_cube = false; break;
|
||||||
|
}
|
||||||
|
if (!in_cube)
|
||||||
|
continue;
|
||||||
|
std::vector<int> cell;
|
||||||
|
for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it)
|
||||||
|
cell.push_back(index_of_vertex[*v_it]);
|
||||||
|
full_cells.push_back(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IS VIOLATED TEST
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** Check if a newly created cell is protected from old vertices
|
||||||
|
*
|
||||||
|
* t is the Delaunay triangulation
|
||||||
|
* vertices is the vector containing the point to insert and a facet f in t
|
||||||
|
* v1 is the vertex of t, such that f and v1 form a simplex
|
||||||
|
* v2 is the vertex of t, such that f and v2 form another simplex
|
||||||
|
* delta is the protection constant
|
||||||
|
* power_protection is true iff the delta-power protection is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool new_cell_is_violated(Delaunay_triangulation& t, std::vector<Point_d>& vertices, const Delaunay_vertex& v1, const Delaunay_vertex v2, FT delta, bool power_protection)
|
||||||
|
{
|
||||||
|
assert(vertices.size() == vertices[0].size() ||
|
||||||
|
vertices.size() == vertices[0].size() + 1); //simplex size = d | d+1
|
||||||
|
assert(v1 != v2);
|
||||||
|
if (vertices.size() == vertices[0].size() + 1)
|
||||||
|
// FINITE CASE
|
||||||
|
{
|
||||||
|
Sphere_d cs(vertices.begin(), vertices.end());
|
||||||
|
Point_d center_cs = cs.center();
|
||||||
|
FT r = sqrt(Euclidean_distance().transformed_distance(center_cs, vertices[0]));
|
||||||
|
/*
|
||||||
|
for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
|
||||||
|
if (!t.is_infinite(v_it))
|
||||||
|
{
|
||||||
|
//CGAL::Oriented_side side = Oriented_side_d()(cs, (v_it)->point());
|
||||||
|
if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end())
|
||||||
|
{
|
||||||
|
FT dist2 = Euclidean_distance().transformed_distance(center_cs, (v_it)->point());
|
||||||
|
if (!power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta))
|
||||||
|
return true;
|
||||||
|
if (power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (!t.is_infinite(v1))
|
||||||
|
{
|
||||||
|
FT dist2 = Euclidean_distance().transformed_distance(center_cs, v1->point());
|
||||||
|
if (!power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta))
|
||||||
|
return true;
|
||||||
|
if (power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!t.is_infinite(v2))
|
||||||
|
{
|
||||||
|
FT dist2 = Euclidean_distance().transformed_distance(center_cs, v2->point());
|
||||||
|
if (!power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta))
|
||||||
|
return true;
|
||||||
|
if (power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// INFINITE CASE
|
||||||
|
{
|
||||||
|
Delaunay_triangulation::Vertex_iterator v = t.vertices_begin();
|
||||||
|
while (t.is_infinite(v) || std::find(vertices.begin(), vertices.end(), v->point()) == vertices.end())
|
||||||
|
v++;
|
||||||
|
Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v->point(), CGAL::ON_POSITIVE_SIDE);
|
||||||
|
Vector_d orth_v = facet_plane.orthogonal_vector();
|
||||||
|
/*
|
||||||
|
for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
|
||||||
|
if (!t.is_infinite(v_it))
|
||||||
|
if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end())
|
||||||
|
{
|
||||||
|
std::vector<FT> coords;
|
||||||
|
Point_d p = v_it->point();
|
||||||
|
auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
|
||||||
|
for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
|
||||||
|
coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length()));
|
||||||
|
Point_d p_delta = Point_d(coords);
|
||||||
|
bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
|
||||||
|
bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
|
||||||
|
if (!p_is_inside && p_delta_is_inside)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (!t.is_infinite(v1))
|
||||||
|
{
|
||||||
|
std::vector<FT> coords;
|
||||||
|
Point_d p = v1->point();
|
||||||
|
auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
|
||||||
|
for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
|
||||||
|
coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length()));
|
||||||
|
Point_d p_delta = Point_d(coords);
|
||||||
|
bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
|
||||||
|
bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
|
||||||
|
if (!p_is_inside && p_delta_is_inside)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!t.is_infinite(v2))
|
||||||
|
{
|
||||||
|
std::vector<FT> coords;
|
||||||
|
Point_d p = v2->point();
|
||||||
|
auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
|
||||||
|
for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
|
||||||
|
coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length()));
|
||||||
|
Point_d p_delta = Point_d(coords);
|
||||||
|
bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
|
||||||
|
bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
|
||||||
|
if (!p_is_inside && p_delta_is_inside)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Auxillary recursive function to check if the point p violates the protection of the cell c and
|
||||||
|
* if there is a violation of an eventual new cell
|
||||||
|
*
|
||||||
|
* p is the point to insert
|
||||||
|
* t is the current triangulation
|
||||||
|
* c is the current cell (simplex)
|
||||||
|
* parent_cell is the parent cell (simplex)
|
||||||
|
* index is the index of the facet between c and parent_cell from parent_cell's point of view
|
||||||
|
* D is the dimension of the triangulation
|
||||||
|
* delta is the protection constant
|
||||||
|
* marked_cells is the vector of all visited cells containing p in their circumscribed ball
|
||||||
|
* power_protection is true iff you are working with delta-power protection
|
||||||
|
*
|
||||||
|
* OUT: true iff inserting p hasn't produced any violation so far
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, Full_cell_handle c, Full_cell_handle parent_cell, int index, int D, FT delta, std::vector<Full_cell_handle>& marked_cells, bool power_protection)
|
||||||
|
{
|
||||||
|
Euclidean_distance ed;
|
||||||
|
std::vector<Point_d> vertices;
|
||||||
|
if (!t.is_infinite(c))
|
||||||
|
{
|
||||||
|
// if the cell is finite, we look if the protection is violated
|
||||||
|
for (auto v_it = c->vertices_begin(); v_it != c->vertices_end(); ++v_it)
|
||||||
|
vertices.push_back((*v_it)->point());
|
||||||
|
Sphere_d cs( vertices.begin(), vertices.end());
|
||||||
|
Point_d center_cs = cs.center();
|
||||||
|
FT r = sqrt(ed.transformed_distance(center_cs, vertices[0]));
|
||||||
|
FT dist2 = ed.transformed_distance(center_cs, p);
|
||||||
|
// if the new point is inside the protection ball of a non conflicting simplex
|
||||||
|
if (!power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta))
|
||||||
|
return true;
|
||||||
|
if (power_protection)
|
||||||
|
if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta)
|
||||||
|
return true;
|
||||||
|
// if the new point is inside the circumscribing ball : continue violation searching on neighbours
|
||||||
|
//if (dist2 < r*r)
|
||||||
|
//if (dist2 < (5*r+delta)*(5*r+delta))
|
||||||
|
if (dist2 < r*r)
|
||||||
|
{
|
||||||
|
c->tds_data().mark_visited();
|
||||||
|
marked_cells.push_back(c);
|
||||||
|
for (int i = 0; i < D+1; ++i)
|
||||||
|
{
|
||||||
|
Full_cell_handle next_c = c->neighbor(i);
|
||||||
|
if (next_c->tds_data().is_clear() &&
|
||||||
|
is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells, power_protection))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the new point is outside the protection sphere
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// facet f is on the border of the conflict zone : check protection of simplex {p,f}
|
||||||
|
// the new simplex is guaranteed to be finite
|
||||||
|
vertices.clear(); vertices.push_back(p);
|
||||||
|
for (int i = 0; i < D+1; ++i)
|
||||||
|
if (i != index)
|
||||||
|
vertices.push_back(parent_cell->vertex(i)->point());
|
||||||
|
Delaunay_vertex vertex_to_check = t.infinite_vertex();
|
||||||
|
for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
|
||||||
|
if (!vertex_is_in_full_cell(*vh_it, parent_cell))
|
||||||
|
{
|
||||||
|
vertex_to_check = *vh_it; break;
|
||||||
|
}
|
||||||
|
if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta, power_protection))
|
||||||
|
//if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Inside of the convex hull is + side. Outside is - side.
|
||||||
|
for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
|
||||||
|
if (!t.is_infinite(*vh_it))
|
||||||
|
vertices.push_back((*vh_it)->point());
|
||||||
|
Delaunay_triangulation::Vertex_iterator v_it = t.vertices_begin();
|
||||||
|
while (t.is_infinite(v_it) || vertex_is_in_full_cell(v_it, c))
|
||||||
|
v_it++;
|
||||||
|
Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v_it->point(), CGAL::ON_POSITIVE_SIDE);
|
||||||
|
//CGAL::Oriented_side outside = Oriented_side_d()(facet_plane, v_it->point());
|
||||||
|
Vector_d orth_v = facet_plane.orthogonal_vector();
|
||||||
|
std::vector<FT> coords;
|
||||||
|
auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
|
||||||
|
for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
|
||||||
|
coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length()));
|
||||||
|
Point_d p_delta = Point_d(coords);
|
||||||
|
bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p) && (Oriented_side_d()(facet_plane, p) != CGAL::ZERO);
|
||||||
|
bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
|
||||||
|
|
||||||
|
if (!p_is_inside && p_delta_is_inside)
|
||||||
|
return true;
|
||||||
|
//if the cell is infinite we look at the neighbours regardless
|
||||||
|
if (p_is_inside)
|
||||||
|
{
|
||||||
|
c->tds_data().mark_visited();
|
||||||
|
marked_cells.push_back(c);
|
||||||
|
for (int i = 0; i < D+1; ++i)
|
||||||
|
{
|
||||||
|
Full_cell_handle next_c = c->neighbor(i);
|
||||||
|
if (next_c->tds_data().is_clear() &&
|
||||||
|
is_violating_protection(p, t, next_c, c, i, D, delta, marked_cells, power_protection))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// facet f is on the border of the conflict zone : check protection of simplex {p,f}
|
||||||
|
// the new simplex is finite if the parent cell is finite
|
||||||
|
vertices.clear(); vertices.push_back(p);
|
||||||
|
for (int i = 0; i < D+1; ++i)
|
||||||
|
if (i != index)
|
||||||
|
if (!t.is_infinite(parent_cell->vertex(i)))
|
||||||
|
vertices.push_back(parent_cell->vertex(i)->point());
|
||||||
|
Delaunay_vertex vertex_to_check = t.infinite_vertex();
|
||||||
|
for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
|
||||||
|
if (!vertex_is_in_full_cell(*vh_it, parent_cell))
|
||||||
|
{
|
||||||
|
vertex_to_check = *vh_it; break;
|
||||||
|
}
|
||||||
|
if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta, power_protection))
|
||||||
|
//if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//c->tds_data().clear_visited();
|
||||||
|
//marked_cells.pop_back();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if inserting the point p in t will make conflicts
|
||||||
|
*
|
||||||
|
* p is the point to insert
|
||||||
|
* t is the current triangulation
|
||||||
|
* D is the dimension of triangulation
|
||||||
|
* delta is the protection constant
|
||||||
|
* power_protection is true iff you are working with delta-power protection
|
||||||
|
* OUT: true iff inserting p produces a violation of delta-protection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta, bool power_protection)
|
||||||
|
{
|
||||||
|
Euclidean_distance ed;
|
||||||
|
Delaunay_triangulation::Vertex_handle v;
|
||||||
|
Delaunay_triangulation::Face f(t.current_dimension());
|
||||||
|
Delaunay_triangulation::Facet ft;
|
||||||
|
Delaunay_triangulation::Full_cell_handle c;
|
||||||
|
Delaunay_triangulation::Locate_type lt;
|
||||||
|
std::vector<Full_cell_handle> marked_cells;
|
||||||
|
c = t.locate(p, lt, f, ft, v);
|
||||||
|
bool violation_existing_cells = is_violating_protection(p, t, c, c, 0, D, delta, marked_cells, power_protection);
|
||||||
|
for (Full_cell_handle fc : marked_cells)
|
||||||
|
fc->tds_data().clear();
|
||||||
|
return violation_existing_cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//!!!!!!!!!!!!! THE INTERFACE FOR LANDMARK CHOICE IS BELOW !!!!!!!!!!//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// LANDMARK CHOICE PROCEDURE
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** Procedure to compute a maximal protected subset from a point cloud. All OUTs should be empty at call.
|
||||||
|
*
|
||||||
|
* IN: W is the initial point cloud having type Epick_d<Dynamic_dimension_tag>::Point_d
|
||||||
|
* IN: nbP is the size of W
|
||||||
|
* OUT: landmarks is the output vector for the points
|
||||||
|
* OUT: landmarks_ind is the output vector for the indices of the selected points in W
|
||||||
|
* IN: delta is the constant of protection
|
||||||
|
* OUT: full_cells is the output vector of the simplices in the final Delaunay triangulation
|
||||||
|
* IN: torus is true iff you are working on a flat torus [-1,1]^d
|
||||||
|
*/
|
||||||
|
|
||||||
|
void landmark_choice_protected_delaunay(Point_Vector& W, int nbP, Point_Vector& landmarks, std::vector<int>& landmarks_ind, FT delta, std::vector<std::vector<int>>& full_cells, bool torus, bool power_protection)
|
||||||
|
{
|
||||||
|
unsigned D = W[0].size();
|
||||||
|
Euclidean_distance ed;
|
||||||
|
Delaunay_triangulation t(D);
|
||||||
|
CGAL::Random rand;
|
||||||
|
int landmark_count = 0;
|
||||||
|
std::list<int> index_list;
|
||||||
|
// shuffle the list of indexes (via a vector)
|
||||||
|
{
|
||||||
|
std::vector<int> temp_vector;
|
||||||
|
for (int i = 0; i < nbP; ++i)
|
||||||
|
temp_vector.push_back(i);
|
||||||
|
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||||
|
std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed));
|
||||||
|
//CGAL::spatial_sort(temp_vector.begin(), temp_vector.end());
|
||||||
|
for (std::vector<int>::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it)
|
||||||
|
index_list.push_front(*it);
|
||||||
|
}
|
||||||
|
if (!torus)
|
||||||
|
for (unsigned pos1 = 0; pos1 < D+1; ++pos1)
|
||||||
|
{
|
||||||
|
std::vector<FT> point;
|
||||||
|
for (unsigned i = 0; i < pos1; ++i)
|
||||||
|
point.push_back(-1);
|
||||||
|
if (pos1 != D)
|
||||||
|
point.push_back(1);
|
||||||
|
for (unsigned i = pos1+1; i < D; ++i)
|
||||||
|
point.push_back(0);
|
||||||
|
assert(point.size() == D);
|
||||||
|
W[index_list.front()] = Point_d(point);
|
||||||
|
insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus);
|
||||||
|
index_list.pop_front();
|
||||||
|
}
|
||||||
|
else if (D == 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 2; ++j)
|
||||||
|
{
|
||||||
|
W[index_list.front()] = Point_d(std::vector<FT>{i*0.5, j*1.0});
|
||||||
|
insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus);
|
||||||
|
index_list.pop_front();
|
||||||
|
W[index_list.front()] = Point_d(std::vector<FT>{0.25+i*0.5, 0.5+j});
|
||||||
|
insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus);
|
||||||
|
index_list.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout << "No torus starter available for dim>2\n";
|
||||||
|
std::list<int>::iterator list_it = index_list.begin();
|
||||||
|
while (list_it != index_list.end())
|
||||||
|
{
|
||||||
|
if (!is_violating_protection(W[*list_it], t, D, delta, power_protection))
|
||||||
|
{
|
||||||
|
// If no conflicts then insert in every copy of T^3
|
||||||
|
|
||||||
|
insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count, torus);
|
||||||
|
index_list.erase(list_it);
|
||||||
|
list_it = index_list.begin();
|
||||||
|
/*
|
||||||
|
// PIECE OF CODE FOR DEBUGGING PURPOSES
|
||||||
|
|
||||||
|
Delaunay_vertex inserted_v = insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count);
|
||||||
|
if (triangulation_is_protected(t, delta))
|
||||||
|
{
|
||||||
|
index_list.erase(list_it);
|
||||||
|
list_it = index_list.begin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //THAT'S WHERE SOMETHING'S WRONG
|
||||||
|
t.remove(inserted_v);
|
||||||
|
landmarks_ind.pop_back();
|
||||||
|
landmark_count--;
|
||||||
|
write_delaunay_mesh(t, W[*list_it], is2d);
|
||||||
|
is_violating_protection(W[*list_it], t_old, D, delta); //Called for encore
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//std::cout << "index_list_size() = " << index_list.size() << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list_it++;
|
||||||
|
//std::cout << "!!!!!WARNING!!!!! A POINT HAS BEEN OMITTED!!!\n";
|
||||||
|
}
|
||||||
|
//if (list_it != index_list.end())
|
||||||
|
// write_delaunay_mesh(t, W[*list_it], is2d);
|
||||||
|
}
|
||||||
|
fill_landmarks(W, landmarks, landmarks_ind, torus);
|
||||||
|
fill_full_cell_vector(t, full_cells);
|
||||||
|
/*
|
||||||
|
if (triangulation_is_protected(t, delta))
|
||||||
|
std::cout << "Triangulation is ok\n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Triangulation is BAD!! T_T しくしく!\n";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//write_delaunay_mesh(t, W[0], is2d);
|
||||||
|
//std::cout << t << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,632 @@
|
||||||
|
// Copyright (c) 2014 INRIA Sophia-Antipolis (France)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
|
||||||
|
#ifndef CGAL_TC_UTILITIES_H
|
||||||
|
#define CGAL_TC_UTILITIES_H
|
||||||
|
|
||||||
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/Dimension.h>
|
||||||
|
#include <CGAL/Combination_enumerator.h>
|
||||||
|
|
||||||
|
#include <Eigen/Core>
|
||||||
|
#include <Eigen/Eigen>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <atomic> // CJTODO: this is C++11 => use boost.Atomic (but it's too recent)
|
||||||
|
// or tbb::atomic (works for doubles, but not officially)
|
||||||
|
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
namespace Tangential_complex_ {
|
||||||
|
|
||||||
|
// Provides copy constructors to std::atomic so that
|
||||||
|
// it can be used in a vector
|
||||||
|
template <typename T>
|
||||||
|
struct Atomic_wrapper
|
||||||
|
: public std::atomic<T>
|
||||||
|
{
|
||||||
|
typedef std::atomic<T> Base;
|
||||||
|
|
||||||
|
Atomic_wrapper() {}
|
||||||
|
Atomic_wrapper(const T &t) : Base(t) {}
|
||||||
|
Atomic_wrapper(const std::atomic<T> &a) : Base(a.load()) {}
|
||||||
|
Atomic_wrapper(const Atomic_wrapper &other) : Base(other.load())
|
||||||
|
{}
|
||||||
|
|
||||||
|
Atomic_wrapper &operator=(const T &other)
|
||||||
|
{
|
||||||
|
Base::store(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Atomic_wrapper &operator=(const std::atomic<T> &other)
|
||||||
|
{
|
||||||
|
Base::store(other.load());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Atomic_wrapper &operator=(const Atomic_wrapper &other)
|
||||||
|
{
|
||||||
|
Base::store(other.load());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*template <typename T>
|
||||||
|
struct Atomic_wrapper
|
||||||
|
{
|
||||||
|
std::atomic<T> _a;
|
||||||
|
|
||||||
|
Atomic_wrapper()
|
||||||
|
:_a()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Atomic_wrapper(const std::atomic<T> &other)
|
||||||
|
:_a(other.load())
|
||||||
|
{}
|
||||||
|
|
||||||
|
Atomic_wrapper(const Atomic_wrapper &other)
|
||||||
|
:_a(other._a.load())
|
||||||
|
{}
|
||||||
|
|
||||||
|
Atomic_wrapper(const T &other)
|
||||||
|
:_a(other)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Atomic_wrapper &operator=(const std::atomic<T> &other)
|
||||||
|
{
|
||||||
|
_a.store(other._a.load());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Atomic_wrapper &operator=(const Atomic_wrapper &other)
|
||||||
|
{
|
||||||
|
_a.store(other._a.load());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Atomic_wrapper &operator=(const T &other)
|
||||||
|
{
|
||||||
|
_a.store(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
return _a.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator std::atomic<T>() const
|
||||||
|
{
|
||||||
|
return _a;
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
|
||||||
|
// Modifies v in-place
|
||||||
|
template <typename K>
|
||||||
|
typename K::Vector_d& normalize_vector(typename K::Vector_d& v,
|
||||||
|
K const& k)
|
||||||
|
{
|
||||||
|
v = k.scaled_vector_d_object()(
|
||||||
|
v, typename K::FT(1)/CGAL::sqrt(k.squared_length_d_object()(v)));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Kernel>
|
||||||
|
struct Basis
|
||||||
|
{
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::Vector_d Vector;
|
||||||
|
typedef typename std::vector<Vector>::const_iterator const_iterator;
|
||||||
|
|
||||||
|
std::size_t m_origin;
|
||||||
|
std::vector<Vector> m_vectors;
|
||||||
|
|
||||||
|
std::size_t origin() const { return m_origin; }
|
||||||
|
void set_origin(std::size_t o) { m_origin = o; }
|
||||||
|
const_iterator begin() const { return m_vectors.begin(); }
|
||||||
|
const_iterator end() const { return m_vectors.end(); }
|
||||||
|
std::size_t size() const { return m_vectors.size(); }
|
||||||
|
|
||||||
|
Vector& operator[](const std::size_t i)
|
||||||
|
{
|
||||||
|
return m_vectors[i];
|
||||||
|
}
|
||||||
|
const Vector& operator[](const std::size_t i) const
|
||||||
|
{
|
||||||
|
return m_vectors[i];
|
||||||
|
}
|
||||||
|
void push_back(const Vector& v)
|
||||||
|
{
|
||||||
|
m_vectors.push_back(v);
|
||||||
|
}
|
||||||
|
void reserve(const std::size_t s)
|
||||||
|
{
|
||||||
|
m_vectors.reserve(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Basis() { }
|
||||||
|
Basis(std::size_t origin) : m_origin(origin) { }
|
||||||
|
Basis(std::size_t origin, const std::vector<Vector>& vectors)
|
||||||
|
: m_origin(origin), m_vectors(vectors)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#ifdef CGAL_ALPHA_TC
|
||||||
|
// Thickening vectors...
|
||||||
|
|
||||||
|
struct Thickening_vector
|
||||||
|
{
|
||||||
|
Thickening_vector()
|
||||||
|
: alpha_minus(FT(0)), alpha_plus(FT(0)) {}
|
||||||
|
Thickening_vector(Vector const& v, FT am, FT ap)
|
||||||
|
: vec(v), alpha_minus(am), alpha_plus(ap) {}
|
||||||
|
|
||||||
|
Vector vec;
|
||||||
|
FT alpha_minus;
|
||||||
|
FT alpha_plus;
|
||||||
|
};
|
||||||
|
typedef std::vector<Thickening_vector> Thickening_vectors;
|
||||||
|
|
||||||
|
Thickening_vectors m_thickening_vectors;
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t num_thickening_vectors() const
|
||||||
|
{
|
||||||
|
return m_thickening_vectors.size();
|
||||||
|
}
|
||||||
|
Thickening_vectors const& thickening_vectors() const
|
||||||
|
{
|
||||||
|
return m_thickening_vectors;
|
||||||
|
}
|
||||||
|
void add_thickening_vector(
|
||||||
|
Vector const& vec, FT alpha_minus = FT(0), FT alpha_plus = FT(0))
|
||||||
|
{
|
||||||
|
m_thickening_vectors.push_back(
|
||||||
|
Thickening_vector(vec, alpha_minus, alpha_plus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_alpha_values_of_thickening_vectors(
|
||||||
|
Vector const& vec, Kernel const& k)
|
||||||
|
{
|
||||||
|
typename Kernel::Scalar_product_d k_scalar_pdct =
|
||||||
|
k.scalar_product_d_object();
|
||||||
|
|
||||||
|
for (Thickening_vectors::iterator it_v = m_thickening_vectors.begin(),
|
||||||
|
it_v_end = m_thickening_vectors.end() ;
|
||||||
|
it_v != it_v_end ; ++it_v)
|
||||||
|
{
|
||||||
|
const FT MARGIN_RATIO = 1.001; // CJTODO TEMP
|
||||||
|
FT alpha_i = k_scalar_pdct(it_v->vec, vec);
|
||||||
|
if (alpha_i * MARGIN_RATIO > it_v->alpha_plus)
|
||||||
|
{
|
||||||
|
#ifdef CGAL_TC_VERY_VERBOSE
|
||||||
|
std::cerr << "OLD alpha+ = " << it_v->alpha_plus << std::endl;
|
||||||
|
#endif
|
||||||
|
it_v->alpha_plus = alpha_i * MARGIN_RATIO;
|
||||||
|
#ifdef CGAL_TC_VERY_VERBOSE
|
||||||
|
std::cerr << "NEW alpha+ = " << it_v->alpha_plus << std::endl;
|
||||||
|
std::cerr << "NOT MODIFIED alpha- = " << it_v->alpha_minus << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (alpha_i * MARGIN_RATIO < it_v->alpha_minus)
|
||||||
|
{
|
||||||
|
#ifdef CGAL_TC_VERY_VERBOSE
|
||||||
|
std::cerr << "OLD alpha- = " << it_v->alpha_minus << std::endl;
|
||||||
|
#endif
|
||||||
|
it_v->alpha_minus = alpha_i * MARGIN_RATIO;
|
||||||
|
#ifdef CGAL_TC_VERY_VERBOSE
|
||||||
|
std::cerr << "NEW alpha- = " << it_v->alpha_minus << std::endl;
|
||||||
|
std::cerr << "NOT MODIFIED alpha+ = " << it_v->alpha_plus << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT alpha_minus(std::size_t i) const
|
||||||
|
{
|
||||||
|
return m_thickening_vectors[i].alpha_minus;
|
||||||
|
}
|
||||||
|
FT alpha_plus(std::size_t i) const
|
||||||
|
{
|
||||||
|
return m_thickening_vectors[i].alpha_plus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns 0 if no thickening vectors
|
||||||
|
FT max_absolute_alpha() const
|
||||||
|
{
|
||||||
|
FT max = FT(0);
|
||||||
|
|
||||||
|
for (Thickening_vectors::const_iterator
|
||||||
|
it_v = m_thickening_vectors.begin(),
|
||||||
|
it_v_end = m_thickening_vectors.end() ;
|
||||||
|
it_v != it_v_end ;
|
||||||
|
++it_v)
|
||||||
|
{
|
||||||
|
if (it_v->alpha_plus > max)
|
||||||
|
max = it_v->alpha_plus;
|
||||||
|
if (-it_v->alpha_minus > max)
|
||||||
|
max = -it_v->alpha_minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dimension() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_vectors.size() + m_thickening_vectors.size());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int dimension() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_vectors.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Using Gram-Schmidt
|
||||||
|
// * If the resulting vector after G-S algorithm is below "sqlen_threshold",
|
||||||
|
// the vector considered linearly dependend to the existing vectors
|
||||||
|
// and is not added to the basis
|
||||||
|
// * Returns true if the vector was added to the basis
|
||||||
|
template <typename K>
|
||||||
|
bool add_vector_to_orthonormal_basis(
|
||||||
|
Basis<K> & basis, typename K::Vector_d const& v, K const& k,
|
||||||
|
typename K::FT sqlen_threshold = typename K::FT(1e-13)
|
||||||
|
#ifdef CGAL_ALPHA_TC
|
||||||
|
, bool add_to_thickening_vectors = false
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
typedef Basis<K> Basis;
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
typedef typename K::Vector_d Vector;
|
||||||
|
|
||||||
|
// Kernel functors
|
||||||
|
typename K::Scaled_vector_d scaled_vec = k.scaled_vector_d_object();
|
||||||
|
typename K::Scalar_product_d scalar_pdct = k.scalar_product_d_object();
|
||||||
|
typename K::Difference_of_vectors_d diff_vec = k.difference_of_vectors_d_object();
|
||||||
|
|
||||||
|
Vector u = v;
|
||||||
|
for (int j = 0 ; j < basis.size() ; ++j)
|
||||||
|
{
|
||||||
|
Vector const& ej = basis[j];
|
||||||
|
Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej));
|
||||||
|
u = diff_vec(u, u_proj);
|
||||||
|
}
|
||||||
|
for (int j = 0 ; j < basis.num_thickening_vectors() ; ++j)
|
||||||
|
{
|
||||||
|
Vector const& ej = basis.thickening_vectors()[j].vec;
|
||||||
|
Vector u_proj = scaled_vec(ej, scalar_pdct(u, ej) / scalar_pdct(ej, ej));
|
||||||
|
u = diff_vec(u, u_proj);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT sqlen_new_v = k.squared_length_d_object()(u);
|
||||||
|
bool add_it = (sqlen_new_v > sqlen_threshold);
|
||||||
|
if (add_it)
|
||||||
|
{
|
||||||
|
Vector new_v = scaled_vec(u, FT(1)/CGAL::sqrt(sqlen_new_v));
|
||||||
|
|
||||||
|
// If new_v is small, run the Gram-Schmidt once more to
|
||||||
|
// re-orthogonalize it
|
||||||
|
if (sqlen_new_v < 0.01)
|
||||||
|
{
|
||||||
|
for (int j = 0 ; j < basis.size() ; ++j)
|
||||||
|
{
|
||||||
|
Vector const& ej = basis[j];
|
||||||
|
Vector new_v_proj = scaled_vec(
|
||||||
|
ej, scalar_pdct(new_v, ej) / scalar_pdct(ej, ej));
|
||||||
|
new_v = diff_vec(new_v, new_v_proj);
|
||||||
|
}
|
||||||
|
for (int j = 0 ; j < basis.num_thickening_vectors() ; ++j)
|
||||||
|
{
|
||||||
|
Vector const& ej = basis.thickening_vectors()[j].vec;
|
||||||
|
Vector new_v_proj = scaled_vec(
|
||||||
|
ej, scalar_pdct(new_v, ej) / scalar_pdct(ej, ej));
|
||||||
|
new_v = diff_vec(new_v, new_v_proj);
|
||||||
|
}
|
||||||
|
sqlen_new_v = k.squared_length_d_object()(new_v);
|
||||||
|
new_v = scaled_vec(new_v, FT(1)/CGAL::sqrt(sqlen_new_v));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_ALPHA_TC
|
||||||
|
if (add_to_thickening_vectors)
|
||||||
|
basis.add_thickening_vector(new_v);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
basis.push_back(new_v);
|
||||||
|
}
|
||||||
|
return add_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename Kernel, typename Tangent_space_basis,
|
||||||
|
typename OutputIteratorPoints, typename OutputIteratorTS>
|
||||||
|
bool load_points_from_file(
|
||||||
|
const std::string &filename,
|
||||||
|
OutputIteratorPoints points,
|
||||||
|
OutputIteratorTS tangent_spaces,
|
||||||
|
std::size_t only_first_n_points = std::numeric_limits<std::size_t>::max())
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::Vector_d Vector;
|
||||||
|
|
||||||
|
std::ifstream in(filename);
|
||||||
|
if (!in.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Could not open '" << filename << "'" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_tangent_spaces =
|
||||||
|
(filename.substr(filename.size() - 3) == "pwt");
|
||||||
|
|
||||||
|
Kernel k;
|
||||||
|
Point p;
|
||||||
|
int num_ppints;
|
||||||
|
in >> num_ppints;
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < only_first_n_points && in >> p)
|
||||||
|
{
|
||||||
|
*points++ = p;
|
||||||
|
if (contains_tangent_spaces)
|
||||||
|
{
|
||||||
|
Tangent_space_basis tsb(i);
|
||||||
|
for (int d = 0 ; d < 2 ; ++d) // CJTODO : pas toujours "2"
|
||||||
|
{
|
||||||
|
Vector v;
|
||||||
|
in >> v;
|
||||||
|
tsb.push_back(CGAL::Tangential_complex_::normalize_vector(v, k));
|
||||||
|
}
|
||||||
|
*tangent_spaces++ = tsb;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_VERBOSE
|
||||||
|
std::cerr << "'" << filename << "' loaded." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1st line: number of points
|
||||||
|
// Then one point per line
|
||||||
|
template <typename Kernel, typename Point_range>
|
||||||
|
std::ostream &export_point_set(
|
||||||
|
Kernel const& k,
|
||||||
|
Point_range const& points,
|
||||||
|
std::ostream & os,
|
||||||
|
const char *coord_separator = " ")
|
||||||
|
{
|
||||||
|
// Kernel functors
|
||||||
|
typename Kernel::Construct_cartesian_const_iterator_d ccci =
|
||||||
|
k.construct_cartesian_const_iterator_d_object();
|
||||||
|
|
||||||
|
os << points.size() << "\n";
|
||||||
|
|
||||||
|
typename Point_range::const_iterator it_p = points.begin();
|
||||||
|
typename Point_range::const_iterator it_p_end = points.end();
|
||||||
|
// For each point p
|
||||||
|
for ( ; it_p != it_p_end ; ++it_p)
|
||||||
|
{
|
||||||
|
for (auto it = ccci(*it_p) ; it != ccci(*it_p, 0) ; ++it) // CJTODO: C++11
|
||||||
|
os << CGAL::to_double(*it) << coord_separator;
|
||||||
|
|
||||||
|
os << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
Basis<K> compute_gram_schmidt_basis(Basis<K> const& input_basis, K const& k)
|
||||||
|
{
|
||||||
|
typedef Basis<K> Basis;
|
||||||
|
|
||||||
|
Basis output_basis(input_basis.origin());
|
||||||
|
|
||||||
|
// Add vector one by one
|
||||||
|
typename Basis::const_iterator inb_it = input_basis.begin();
|
||||||
|
typename Basis::const_iterator inb_it_end = input_basis.end();
|
||||||
|
for (int i = 0 ; inb_it != inb_it_end ; ++inb_it, ++i)
|
||||||
|
add_vector_to_orthonormal_basis(output_basis, *inb_it, k);
|
||||||
|
|
||||||
|
return output_basis;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor to compute stereographic projection from S^3(sphere_radius) to R^3
|
||||||
|
template <typename K>
|
||||||
|
class Orthogonal_projection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
typedef typename K::Point_d Point;
|
||||||
|
|
||||||
|
// center_of_projection will be sent to infinity by the projection
|
||||||
|
Orthogonal_projection(
|
||||||
|
std::array<int, 3> const& selected_coords, K const& k)
|
||||||
|
: m_selected_coords(selected_coords), m_k(k)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Point operator()(Point const& p) const
|
||||||
|
{
|
||||||
|
typedef K::FT FT;
|
||||||
|
typedef K::Point_d Point;
|
||||||
|
|
||||||
|
typename K::Construct_point_d constr_pt = m_k.construct_point_d_object();
|
||||||
|
typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
|
||||||
|
|
||||||
|
std::vector<FT> projected_p;
|
||||||
|
projected_p.reserve(3);
|
||||||
|
|
||||||
|
for (int i = 0 ; i < 3 ; ++i)
|
||||||
|
projected_p.push_back(coord(p, m_selected_coords[i]));
|
||||||
|
|
||||||
|
return constr_pt(3, projected_p.begin(), projected_p.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<int, 3> m_selected_coords; // CJTODO C++11
|
||||||
|
K const& m_k;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Functor to compute radial projection from R^4 to S^3(sphere_radius)
|
||||||
|
// The returned point coordinates are expressed with the origin
|
||||||
|
// at `center_of_sphere`, i.e. the new points are all on the sphere
|
||||||
|
// S^3{(0,0,0,0), sphere_radius}
|
||||||
|
template <typename K>
|
||||||
|
class R4_to_S3_radial_projection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
typedef typename K::Point_d Point;
|
||||||
|
|
||||||
|
// center_of_projection will be sent to infinity by the projection
|
||||||
|
R4_to_S3_radial_projection(
|
||||||
|
FT sphere_radius, Point const& center_of_sphere, K const& k)
|
||||||
|
: m_sphere_radius(sphere_radius), m_center_of_sphere(center_of_sphere),
|
||||||
|
m_k(k) {}
|
||||||
|
|
||||||
|
Point operator()(Point const& p) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(m_k.point_dimension_d_object()(p) == 4);
|
||||||
|
|
||||||
|
typedef K::FT FT;
|
||||||
|
typedef K::Point_d Point;
|
||||||
|
typedef K::Vector_d Vector;
|
||||||
|
|
||||||
|
typename K::Translated_point_d transl = m_k.translated_point_d_object();
|
||||||
|
typename K::Point_to_vector_d pt_to_vec = m_k.point_to_vector_d_object();
|
||||||
|
typename K::Vector_to_point_d vec_to_pt = m_k.vector_to_point_d_object();
|
||||||
|
typename K::Squared_length_d sqlen = m_k.squared_length_d_object();
|
||||||
|
typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object();
|
||||||
|
|
||||||
|
Point transl_p = transl(p, scaled_vec(pt_to_vec(m_center_of_sphere), FT(-1)));
|
||||||
|
Vector v = pt_to_vec(transl_p);
|
||||||
|
v = scaled_vec(v, m_sphere_radius / CGAL::sqrt(sqlen(v)));
|
||||||
|
|
||||||
|
return vec_to_pt(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FT m_sphere_radius;
|
||||||
|
Point m_center_of_sphere;
|
||||||
|
K const& m_k;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Functor to compute stereographic projection from S^3(sphere_radius) to R^3
|
||||||
|
template <typename K>
|
||||||
|
class S3_to_R3_stereographic_projection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
typedef typename K::Point_d Point;
|
||||||
|
|
||||||
|
// center_of_projection will be sent to infinity by the projection
|
||||||
|
S3_to_R3_stereographic_projection(
|
||||||
|
FT sphere_radius, Point const& center_of_projection, K const& k)
|
||||||
|
: m_sphere_radius(sphere_radius), m_center_of_proj(center_of_projection),
|
||||||
|
m_k(k) {}
|
||||||
|
|
||||||
|
Point operator()(Point const& p) const
|
||||||
|
{
|
||||||
|
CGAL_assertion(m_k.point_dimension_d_object()(p) == 4);
|
||||||
|
|
||||||
|
typedef K::FT FT;
|
||||||
|
typedef K::Point_d Point;
|
||||||
|
|
||||||
|
typename K::Construct_point_d constr_pt = m_k.construct_point_d_object();
|
||||||
|
typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
|
||||||
|
|
||||||
|
std::vector<FT> stereo_proj;
|
||||||
|
stereo_proj.reserve(3);
|
||||||
|
|
||||||
|
FT t = (2 * m_sphere_radius + coord(m_center_of_proj, 3))
|
||||||
|
/ (m_sphere_radius - (coord(p, 3) - coord(m_center_of_proj, 3)));
|
||||||
|
for (int i = 0 ; i < 3 ; ++i)
|
||||||
|
stereo_proj.push_back(coord(m_center_of_proj, i) + t*(coord(p, i) - coord(m_center_of_proj, i)));
|
||||||
|
|
||||||
|
return constr_pt(3, stereo_proj.begin(), stereo_proj.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FT m_sphere_radius;
|
||||||
|
Point m_center_of_proj;
|
||||||
|
K const& m_k;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Functor to project R^4 points to R^3
|
||||||
|
template <typename K>
|
||||||
|
class R4_to_R3_using_radial_then_stereographic_projection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
typedef typename K::Point_d Point;
|
||||||
|
|
||||||
|
// sphere_radius and center_of_projection are for the stereographic
|
||||||
|
// projection
|
||||||
|
R4_to_R3_using_radial_then_stereographic_projection(
|
||||||
|
FT sphere_radius, Point const& center_of_sphere,
|
||||||
|
Point const& center_of_projection, K const& k)
|
||||||
|
: m_R4toS3(sphere_radius, center_of_sphere, k),
|
||||||
|
m_S3toR3(sphere_radius, center_of_projection, k),
|
||||||
|
m_k(k) {}
|
||||||
|
|
||||||
|
Point operator()(Point const& p) const
|
||||||
|
{
|
||||||
|
return m_S3toR3(m_R4toS3(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
R4_to_S3_radial_projection<K> m_R4toS3;
|
||||||
|
S3_to_R3_stereographic_projection<K> m_S3toR3;
|
||||||
|
K const& m_k;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CJTODO: use CGAL::Combination_enumerator<int> (cf. Tangential_complex.h)
|
||||||
|
// Compute all the k-combinations of elements
|
||||||
|
// Output_iterator::value_type must be std::set<std::size_t> >
|
||||||
|
template <typename Elements_container, typename Output_iterator>
|
||||||
|
void combinations(const Elements_container elements, int k,
|
||||||
|
Output_iterator combinations)
|
||||||
|
{
|
||||||
|
std::size_t n = elements.size();
|
||||||
|
std::vector<bool> booleans(n, false);
|
||||||
|
std::fill(booleans.begin() + n - k, booleans.end(), true);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::set<std::size_t> combination;
|
||||||
|
typename Elements_container::const_iterator it_elt = elements.begin();
|
||||||
|
for (std::size_t i = 0 ; i < n ; ++i, ++it_elt)
|
||||||
|
{
|
||||||
|
if (booleans[i])
|
||||||
|
combination.insert(*it_elt);
|
||||||
|
}
|
||||||
|
*combinations++ = combination;
|
||||||
|
|
||||||
|
} while (std::next_permutation(booleans.begin(), booleans.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tangential_complex_
|
||||||
|
} //namespace CGAL
|
||||||
|
|
||||||
|
#endif // CGAL_TC_UTILITIES_H
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
INRIA Sophia-Antipolis (France)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Tangential complex
|
||||||
|
|
||||||
|
This CGAL component provides an implementation of the tangential complex.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
GPL (v3 or later)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clément Jamin <clement.jamin.pro@gmail.com>
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Created by the script cgal_create_cmake_script
|
||||||
|
# This is the CMake script for compiling a CGAL application.
|
||||||
|
|
||||||
|
|
||||||
|
project( Tangential_complex_test )
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.6.2)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
|
||||||
|
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
|
||||||
|
cmake_policy(VERSION 2.8.4)
|
||||||
|
else()
|
||||||
|
cmake_policy(VERSION 2.6)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Creates a new CMake option, turned ON by default
|
||||||
|
option(ACTIVATE_MSVC_PRECOMPILED_HEADERS
|
||||||
|
"Activate precompiled headers in MSVC"
|
||||||
|
OFF)
|
||||||
|
|
||||||
|
# Macro to add precompiled headers for MSVC
|
||||||
|
# This function does two things:
|
||||||
|
# 1. Enable precompiled headers on each file which is listed in "SourcesVar".
|
||||||
|
# 2. Add the content of "PrecompiledSource" (e.g. "StdAfx.cpp") to "SourcesVar".
|
||||||
|
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
|
||||||
|
IF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS)
|
||||||
|
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
|
||||||
|
SET(Sources ${${SourcesVar}})
|
||||||
|
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
|
||||||
|
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\"")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(${Sources}
|
||||||
|
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeader}\"")
|
||||||
|
# Add precompiled header to SourcesVar
|
||||||
|
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
|
||||||
|
ENDIF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS)
|
||||||
|
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
|
||||||
|
|
||||||
|
# The compiler might need more memory because of precompiled headers
|
||||||
|
if(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS AND NOT(MSVC_VERSION LESS 1310))
|
||||||
|
set(CGAL_C_FLAGS "${CGAL_C_FLAGS} /Zm1000")
|
||||||
|
set(CGAL_CXX_FLAGS "${CGAL_CXX_FLAGS} /Zm1000")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(CGAL QUIET COMPONENTS Core )
|
||||||
|
|
||||||
|
if ( CGAL_FOUND )
|
||||||
|
include( ${CGAL_USE_FILE} )
|
||||||
|
|
||||||
|
find_package( TBB QUIET )
|
||||||
|
|
||||||
|
if( TBB_FOUND )
|
||||||
|
include(${TBB_USE_FILE})
|
||||||
|
list(APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
include( CGAL_CreateSingleSourceCGALProgram )
|
||||||
|
|
||||||
|
find_package(Eigen3 3.1.0)
|
||||||
|
if (EIGEN3_FOUND)
|
||||||
|
include( ${EIGEN3_USE_FILE} )
|
||||||
|
include_directories (BEFORE "../../include")
|
||||||
|
include_directories (BEFORE "include")
|
||||||
|
include_directories(../../../Anisotropic_mesh_TC/include)
|
||||||
|
|
||||||
|
set (SOURCE_FILES "test_tangential_complex.cpp")
|
||||||
|
ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES)
|
||||||
|
create_single_source_cgal_program( ${SOURCE_FILES} )
|
||||||
|
|
||||||
|
create_single_source_cgal_program( "aniso_TC.cpp" )
|
||||||
|
create_single_source_cgal_program( "test_utilities.cpp" )
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "This program requires the CGAL library, and will not be compiled.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Build the precompiled headers.
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef STDAFX_H
|
||||||
|
#define STDAFX_H
|
||||||
|
|
||||||
|
// CGAL
|
||||||
|
#include <CGAL/Tangential_complex/config.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Regular_triangulation_euclidean_traits.h>
|
||||||
|
#include <CGAL/Regular_triangulation.h>
|
||||||
|
#include <CGAL/Delaunay_triangulation.h>
|
||||||
|
#include <CGAL/Tangential_complex/utilities.h>
|
||||||
|
#include <CGAL/Tangential_complex/Point_cloud.h>
|
||||||
|
#include <CGAL/Combination_enumerator.h>
|
||||||
|
|
||||||
|
#endif //STDAFX_H
|
||||||
|
|
@ -0,0 +1,297 @@
|
||||||
|
#include <CGAL/assertions_behaviour.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Tangential_complex.h>
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
|
||||||
|
#include "../../test/Tangential_complex/testing_utilities.h"
|
||||||
|
|
||||||
|
#include <CGAL/Metric_field.h> // Anisotropic metrics
|
||||||
|
#include <Metric_field/Euclidean_metric_field.h>
|
||||||
|
#include <Metric_field/Custom_metric_field.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
const int k = 2; // intrinsic
|
||||||
|
const int d = 5; // ambiant
|
||||||
|
|
||||||
|
typedef CGAL::Epick_d< CGAL::Dimension_tag<k> > Kk;
|
||||||
|
typedef CGAL::Epick_d< CGAL::Dimension_tag<d> > Kd;
|
||||||
|
typedef Kk::FT FT;
|
||||||
|
typedef Kk::Point_d Point_k;
|
||||||
|
typedef Kd::Point_d Point_d;
|
||||||
|
typedef Kd::Weighted_point_d Weighted_point_d;
|
||||||
|
typedef Kd::Vector_d Vector_d;
|
||||||
|
typedef CGAL::Tangential_complex<Kd,
|
||||||
|
CGAL::Dimension_tag<k>,
|
||||||
|
CGAL::Parallel_tag> TC;
|
||||||
|
|
||||||
|
typedef CGAL::Tangential_complex_::Basis<Kd> Basis;
|
||||||
|
typedef CGAL::Anisotropic_mesh_TC::Metric_base<Kk> Metric;
|
||||||
|
typedef CGAL::Anisotropic_mesh_TC::Metric_field<Kk> Metric_field;
|
||||||
|
|
||||||
|
typedef typename Metric::E_Matrix E_Matrix_k;
|
||||||
|
typedef typename Metric::E_Vector E_Vector_k;
|
||||||
|
typedef Eigen::Matrix<FT, d, 1> E_Vector_d;
|
||||||
|
typedef Eigen::Matrix<FT, d, k> E_Matrix_dk;
|
||||||
|
|
||||||
|
typedef CGAL::Anisotropic_mesh_TC::Euclidean_metric_field<Kk> Euclidean_mf;
|
||||||
|
typedef CGAL::Anisotropic_mesh_TC::Custom_metric_field<Kk> Custom_mf;
|
||||||
|
|
||||||
|
void read_points(std::vector<Point_k>& points,
|
||||||
|
const Kk kerk = Kk())
|
||||||
|
{
|
||||||
|
std::ifstream in("../../../../Anisotropic_mesh_2/examples/Anisotropic_mesh_2/bambimboum.mesh");
|
||||||
|
// std::ifstream in("aniso_regular.mesh");
|
||||||
|
std::string word;
|
||||||
|
int useless, nv, dd;
|
||||||
|
FT x;
|
||||||
|
|
||||||
|
in >> word >> useless; //MeshVersionFormatted i
|
||||||
|
in >> word >> dd; //Dimension d
|
||||||
|
in >> word >> nv;
|
||||||
|
|
||||||
|
assert(dd == Kk::Dimension::value);
|
||||||
|
|
||||||
|
for(int i=0; i<nv; ++i)
|
||||||
|
{
|
||||||
|
std::vector<FT> ids;
|
||||||
|
for(int j=0; j<k; ++j)
|
||||||
|
{
|
||||||
|
in >> x;
|
||||||
|
ids.push_back(x);
|
||||||
|
}
|
||||||
|
in >> useless;
|
||||||
|
points.push_back(kerk.construct_point_d_object()(ids.begin(), ids.begin() + k));
|
||||||
|
|
||||||
|
if(points.size() == 200)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << points.size() << " points" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the corresponding point on the paraboloid (these points will be the
|
||||||
|
// points at which we compute tangent planes)
|
||||||
|
Point_d to_Q(const Point_k& p)
|
||||||
|
{
|
||||||
|
typename Kk::Compute_coordinate_d k_coord = Kk().compute_coordinate_d_object();
|
||||||
|
|
||||||
|
E_Vector_d p_on_Q;
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
p_on_Q(i) = k_coord(p, i);
|
||||||
|
|
||||||
|
int ind = k;
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
for(int j=i; j<k; ++j)
|
||||||
|
p_on_Q(ind++) = k_coord(p,i) * k_coord(p,j);
|
||||||
|
|
||||||
|
return Kd().construct_point_d_object()(d, p_on_Q.data(), p_on_Q.data() + d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the corresponding point on the metric manifold (these points will be
|
||||||
|
// the seeds of the global power diagram)
|
||||||
|
Weighted_point_d to_S(const Point_k& p,
|
||||||
|
const Metric& met,
|
||||||
|
const Kd kerd = Kd())
|
||||||
|
{
|
||||||
|
const E_Matrix_k m = met.get_mat();
|
||||||
|
E_Vector_k e_p, p_bar;
|
||||||
|
|
||||||
|
typename Kk::Compute_coordinate_d k_coord = Kk().compute_coordinate_d_object();
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
e_p(i) = k_coord(p, i);
|
||||||
|
|
||||||
|
p_bar = m * e_p;
|
||||||
|
|
||||||
|
E_Vector_d p_on_S;
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
p_on_S(i) = p_bar(i);
|
||||||
|
|
||||||
|
int ind = k;
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
{
|
||||||
|
for(int j=i; j<k; ++j)
|
||||||
|
{
|
||||||
|
if(j==i)
|
||||||
|
p_on_S(ind++) = -0.5*m(i,i);
|
||||||
|
else
|
||||||
|
p_on_S(ind++) = -m(i,j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT n = p_on_S.norm();
|
||||||
|
FT w = n * n - e_p.transpose() * p_bar;
|
||||||
|
|
||||||
|
return kerd.construct_weighted_point_d_object()
|
||||||
|
(kerd.construct_point_d_object()(d, p_on_S.data(),p_on_S.data()+d), w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_points_in_ambiant_space(std::vector<Point_k> const & points_k,
|
||||||
|
Metric_field const * const mf,
|
||||||
|
std::vector<Point_d>& points_d,
|
||||||
|
std::vector<FT>& weights,
|
||||||
|
Kd const kerd = Kd())
|
||||||
|
{
|
||||||
|
typename Kd::Point_drop_weight_d k_drop_w = kerd.point_drop_weight_d_object();
|
||||||
|
typename Kd::Point_weight_d k_point_weight = kerd.point_weight_d_object();
|
||||||
|
|
||||||
|
for(std::size_t i=0; i<points_k.size(); ++i)
|
||||||
|
{
|
||||||
|
Point_k const & p = points_k[i];
|
||||||
|
Metric met = mf->compute_metric(p);
|
||||||
|
Weighted_point_d wp = to_S(p, met, kerd);
|
||||||
|
points_d.push_back(k_drop_w(wp));
|
||||||
|
weights.push_back(k_point_weight(wp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_and_set_tangent_planes(TC& tc,
|
||||||
|
const std::vector<Point_k>& points_k,
|
||||||
|
Kd const kerd = Kd())
|
||||||
|
{
|
||||||
|
typedef TC::TS_container TS_container;
|
||||||
|
typedef TC::OS_container OS_container;
|
||||||
|
|
||||||
|
typename Kd::Compute_coordinate_d coord = kerd.compute_coordinate_d_object();
|
||||||
|
typename Kd::Construct_vector_d constr_vec = kerd.construct_vector_d_object();
|
||||||
|
TS_container tsc;
|
||||||
|
OS_container osc;
|
||||||
|
std::size_t n = tc.number_of_vertices();
|
||||||
|
CGAL_assertion(n == points_k.size());
|
||||||
|
|
||||||
|
for(std::size_t c=0; c<n; ++c)
|
||||||
|
{
|
||||||
|
// origin of the basis is the point moved the paraboloid
|
||||||
|
Point_d origin = to_Q(points_k[c]);
|
||||||
|
|
||||||
|
// compute the tsc; the vectors are given by the partial derivatives
|
||||||
|
// of the parametrization of the paraboloid
|
||||||
|
Basis ts(origin);
|
||||||
|
|
||||||
|
// filling all the vectors at the same time through a (d,k)-matrix
|
||||||
|
E_Matrix_dk ts_m = E_Matrix_dk::Zero();
|
||||||
|
// 'first' part: x y z etc. derivates
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
for(int j=0; j<k; ++j)
|
||||||
|
ts_m(i,j) = (i==j);
|
||||||
|
|
||||||
|
// 'second' part: x² xy xz y² yz z² etc. derivatives
|
||||||
|
int pos = k;
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
{
|
||||||
|
for(int j=i; j<k; ++j)
|
||||||
|
{
|
||||||
|
if(i == j)
|
||||||
|
ts_m(pos, i) = 2*coord(origin, i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ts_m(pos, i) = coord(origin, j);
|
||||||
|
ts_m(pos, j) = coord(origin, i);
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<k; ++i)
|
||||||
|
{
|
||||||
|
Vector_d v = constr_vec(d, ts_m.col(i).data(), ts_m.col(i).data() + d);
|
||||||
|
ts.push_back(v);
|
||||||
|
}
|
||||||
|
tsc.push_back(CGAL::Tangential_complex_::compute_gram_schmidt_basis(ts, kerd));
|
||||||
|
|
||||||
|
#ifdef CGAL_FIXED_ALPHA_TC
|
||||||
|
// compute the osc
|
||||||
|
Basis os(origin);
|
||||||
|
|
||||||
|
// todo
|
||||||
|
osc.push_back(CGAL::Tangential_complex_::compute_gram_schmidt_basis(os, kerd));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tc.set_tangent_planes(tsc
|
||||||
|
#ifdef CGAL_FIXED_ALPHA_TC
|
||||||
|
, osc
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate the connectivity of the stars back to the original points
|
||||||
|
void export_complex_in_origin_space(const TC& tc,
|
||||||
|
const TC::Simplicial_complex& complex,
|
||||||
|
const std::vector<Point_k>& points_k)
|
||||||
|
{
|
||||||
|
std::ofstream out("aniso.off");
|
||||||
|
std::stringstream output;
|
||||||
|
std::size_t num_simplices;
|
||||||
|
|
||||||
|
typename Kk::Compute_coordinate_d k_coord = Kk().compute_coordinate_d_object();
|
||||||
|
|
||||||
|
|
||||||
|
for(std::size_t i=0; i<points_k.size(); ++i)
|
||||||
|
{
|
||||||
|
const Point_k& p = points_k[i];
|
||||||
|
output << k_coord(p, 0) << " " << k_coord(p, 1) << " 0" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
tc.export_simplices_to_off(complex, output, num_simplices);
|
||||||
|
|
||||||
|
out << "OFF" << std::endl;
|
||||||
|
out << points_k.size() << " " << num_simplices << " 0" << std::endl;
|
||||||
|
out << output.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_tc(std::vector<Point_k>& points_k,
|
||||||
|
Metric_field const * const mf)
|
||||||
|
{
|
||||||
|
Kd ker_d;
|
||||||
|
|
||||||
|
std::vector<Point_d> points_d;
|
||||||
|
std::vector<FT> weights;
|
||||||
|
compute_points_in_ambiant_space(points_k, mf, points_d, weights, ker_d);
|
||||||
|
|
||||||
|
TC tc(points_d.begin(), points_d.end(), 0./*sparsity*/, k /*intr dim*/, ker_d);
|
||||||
|
tc.set_weights(weights);
|
||||||
|
compute_and_set_tangent_planes(tc, points_k, ker_d);
|
||||||
|
|
||||||
|
tc.compute_tangential_complex();
|
||||||
|
|
||||||
|
TC::Simplicial_complex complex;
|
||||||
|
int max_dim = tc.export_TC(complex, false);
|
||||||
|
complex.display_stats();
|
||||||
|
{
|
||||||
|
std::ofstream off_stream("aniso_alpha_complex.off");
|
||||||
|
tc.export_to_off(complex, off_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collapse
|
||||||
|
complex.collapse(max_dim);
|
||||||
|
{
|
||||||
|
std::ofstream off_stream("aniso_after_collapse.off");
|
||||||
|
tc.export_to_off(complex, off_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t num_wrong_dim_simplices, num_wrong_number_of_cofaces;
|
||||||
|
bool pure_manifold = complex.is_pure_manifold(k, false, 1,
|
||||||
|
&num_wrong_dim_simplices,
|
||||||
|
&num_wrong_number_of_cofaces);
|
||||||
|
complex.display_stats();
|
||||||
|
|
||||||
|
export_complex_in_origin_space(tc, complex, points_k);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CGAL::default_random = CGAL::Random();
|
||||||
|
std::vector<Point_k> points_k;
|
||||||
|
|
||||||
|
//Custom_mf* mf = new Custom_mf();
|
||||||
|
Euclidean_mf* mf = new Euclidean_mf();
|
||||||
|
|
||||||
|
read_points(points_k);
|
||||||
|
make_tc(points_k, mf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
//#undef CGAL_LINKED_WITH_TBB // CJTODO TEMP
|
||||||
|
|
||||||
|
// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
|
||||||
|
// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define TBB_USE_THREADING_TOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <CGAL/assertions_behaviour.h>
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Tangential_complex.h>
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
#include <CGAL/Mesh_3/Profiling_tools.h>
|
||||||
|
|
||||||
|
#include "testing_utilities.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# include <tbb/task_scheduler_init.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============== Constants =================
|
||||||
|
const double INPUT_SPARSITY = 0.05;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
const int NUM_POINTS = 50;
|
||||||
|
#else
|
||||||
|
const int NUM_POINTS = 30000;
|
||||||
|
#endif
|
||||||
|
//===========================================
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#if defined(CHECK_MEMORY_LEAKS_ON_MSVC) && defined(_MSC_VER)
|
||||||
|
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||||
|
#endif
|
||||||
|
CGAL::set_error_behaviour(CGAL::ABORT);
|
||||||
|
|
||||||
|
#ifdef CGAL_LINKED_WITH_TBB
|
||||||
|
# ifdef _DEBUG
|
||||||
|
tbb::task_scheduler_init init(1);
|
||||||
|
# else
|
||||||
|
tbb::task_scheduler_init init(10);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const int INTRINSIC_DIMENSION = 3;
|
||||||
|
const int AMBIENT_DIMENSION = 9;
|
||||||
|
|
||||||
|
typedef CGAL::Epick_d<CGAL::Dimension_tag<AMBIENT_DIMENSION> > Kernel;
|
||||||
|
typedef Kernel::FT FT;
|
||||||
|
typedef Kernel::Point_d Point;
|
||||||
|
typedef CGAL::Tangential_complex<
|
||||||
|
Kernel, CGAL::Dimension_tag<INTRINSIC_DIMENSION>,
|
||||||
|
CGAL::Parallel_tag> TC;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
bool stop = false;
|
||||||
|
//for ( ; !stop ; ++i)
|
||||||
|
{
|
||||||
|
Kernel k;
|
||||||
|
Wall_clock_timer t;
|
||||||
|
CGAL::default_random = CGAL::Random(i);
|
||||||
|
std::cerr << "Random seed = " << i << std::endl;
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
Wall_clock_timer t_gen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*std::vector<Point> points =
|
||||||
|
//generate_points_on_circle_2<Kernel>(NUM_POINTS, 3.);
|
||||||
|
//generate_points_on_moment_curve<Kernel>(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.);
|
||||||
|
//generate_points_on_plane<Kernel>(NUM_POINTS);
|
||||||
|
//generate_points_on_sphere_3<Kernel>(NUM_POINTS, 3.0);
|
||||||
|
//generate_points_on_sphere_d<Kernel>(NUM_POINTS, AMBIENT_DIMENSION, 3.0);
|
||||||
|
//generate_points_on_klein_bottle_3D<Kernel>(NUM_POINTS, 4., 3.);
|
||||||
|
generate_points_on_klein_bottle_4D<Kernel>(NUM_POINTS, 4., 3.);
|
||||||
|
//generate_points_on_klein_bottle_variant_5D<Kernel>(NUM_POINTS, 4., 3.);*/
|
||||||
|
|
||||||
|
// LOAD FROM A FILE
|
||||||
|
std::vector<Point> points;
|
||||||
|
load_points_from_file<Point>(
|
||||||
|
"data/SO3_10000.txt", std::back_inserter(points));
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
std::cerr << "Point set generated in " << t_gen.elapsed()
|
||||||
|
<< " seconds." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::size_t num_points_before = points.size();
|
||||||
|
points = sparsify_point_set(
|
||||||
|
k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY));
|
||||||
|
std::cerr << "Number of points before/after sparsification: "
|
||||||
|
<< num_points_before << " / " << points.size() << std::endl;
|
||||||
|
|
||||||
|
TC tc(points.begin(), points.end(), INPUT_SPARSITY, INTRINSIC_DIMENSION, k);
|
||||||
|
double init_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
tc.compute_tangential_complex();
|
||||||
|
double computation_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
if (ambient_dim <= 4)
|
||||||
|
tc.check_if_all_simplices_are_in_the_ambient_delaunay();
|
||||||
|
|
||||||
|
double export_before_time = -1.;
|
||||||
|
if (INTRINSIC_DIMENSION <= 3)
|
||||||
|
{
|
||||||
|
t.reset();
|
||||||
|
std::stringstream output_filename;
|
||||||
|
output_filename << "output/test_tc_" << INTRINSIC_DIMENSION
|
||||||
|
<< "_in_R" << AMBIENT_DIMENSION << "_BEFORE_FIX.off";
|
||||||
|
std::ofstream off_stream(output_filename.str().c_str());
|
||||||
|
tc.export_to_off(off_stream, true);
|
||||||
|
export_before_time = t.elapsed(); t.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
unsigned int num_fix_steps;
|
||||||
|
std::size_t initial_num_inconsistent_local_tr;
|
||||||
|
std::size_t best_num_inconsistent_local_tr;
|
||||||
|
std::size_t final_num_inconsistent_local_tr;
|
||||||
|
CGAL::Fix_inconsistencies_status fix_ret =
|
||||||
|
tc.fix_inconsistencies_using_perturbation(
|
||||||
|
num_fix_steps, initial_num_inconsistent_local_tr,
|
||||||
|
best_num_inconsistent_local_tr, final_num_inconsistent_local_tr, 1000.);
|
||||||
|
double fix_time = t.elapsed(); t.reset();
|
||||||
|
|
||||||
|
double export_after_time = -1.;
|
||||||
|
if (INTRINSIC_DIMENSION <= 3)
|
||||||
|
{
|
||||||
|
t.reset();
|
||||||
|
std::stringstream output_filename;
|
||||||
|
output_filename << "output/test_tc_" << INTRINSIC_DIMENSION
|
||||||
|
<< "_in_R" << AMBIENT_DIMENSION << "_AFTER_FIX.off";
|
||||||
|
std::ofstream off_stream(output_filename.str().c_str());
|
||||||
|
tc.export_to_off(off_stream, true);
|
||||||
|
export_after_time = t.elapsed(); t.reset();
|
||||||
|
}
|
||||||
|
/*else
|
||||||
|
tc.number_of_inconsistent_simplices();*/
|
||||||
|
|
||||||
|
|
||||||
|
std::cerr << std::endl
|
||||||
|
<< "================================================" << std::endl
|
||||||
|
<< "Number of vertices: " << tc.number_of_vertices() << std::endl
|
||||||
|
<< "Computation times (seconds): " << std::endl
|
||||||
|
<< " * Tangential complex: " << init_time + computation_time
|
||||||
|
<< std::endl
|
||||||
|
<< " - Init + kd-tree = " << init_time << std::endl
|
||||||
|
<< " - TC computation = " << computation_time << std::endl
|
||||||
|
<< " * Export to OFF (before fix): " << export_before_time << std::endl
|
||||||
|
<< " * Fix inconsistencies: " << fix_time
|
||||||
|
<< " (" << num_fix_steps << " steps) ==> "
|
||||||
|
<< (fix_ret == CGAL::TC_FIXED ? "FIXED" : "NOT fixed") << std::endl
|
||||||
|
<< " * Export to OFF (after fix): " << export_after_time << std::endl
|
||||||
|
<< "================================================" << std::endl
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
|
||||||
|
// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define TBB_USE_THREADING_TOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <CGAL/Epick_d.h>
|
||||||
|
#include <CGAL/Tangential_complex/utilities.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace CGAL::Tangential_complex_;
|
||||||
|
|
||||||
|
void test_does_voronoi_face_and_alpha_tangent_subspace_intersect()
|
||||||
|
{
|
||||||
|
typedef CGAL::Epick_d<CGAL::Dimension_tag<2> > K;
|
||||||
|
typedef K::Point_d Pt;
|
||||||
|
typedef K::Vector_d Vec;
|
||||||
|
std::vector<std::size_t> P;
|
||||||
|
std::vector<std::size_t> Q;
|
||||||
|
std::vector<Vec> osb;
|
||||||
|
|
||||||
|
K k;
|
||||||
|
|
||||||
|
std::vector<Pt> points;
|
||||||
|
points.push_back(Pt(0.02, -0.03));
|
||||||
|
points.push_back(Pt(0.005, 2.3));
|
||||||
|
points.push_back(Pt(4.5, 1.12));
|
||||||
|
points.push_back(Pt(-3.5, 1.02));
|
||||||
|
|
||||||
|
P.push_back(0);
|
||||||
|
P.push_back(1);
|
||||||
|
|
||||||
|
Q.push_back(2);
|
||||||
|
Q.push_back(3);
|
||||||
|
|
||||||
|
osb.push_back(Vec(0.01, 0.995));
|
||||||
|
|
||||||
|
assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect(
|
||||||
|
points, 0, P, Q, osb, 0.0, k) == false);
|
||||||
|
|
||||||
|
assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect(
|
||||||
|
points, 0, P, Q, osb, 0.5, k) == false);
|
||||||
|
|
||||||
|
assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect(
|
||||||
|
points, 0, P, Q, osb, 1.0, k) == false);
|
||||||
|
|
||||||
|
assert(does_voronoi_face_and_fixed_alpha_tangent_subspace_intersect(
|
||||||
|
points, 0, P, Q, osb, 1.5, k) == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_does_voronoi_face_and_alpha_tangent_subspace_intersect();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,846 @@
|
||||||
|
// Copyright (c) 2014 INRIA Sophia-Antipolis (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// 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) : Clement Jamin
|
||||||
|
//
|
||||||
|
//******************************************************************************
|
||||||
|
// File Description :
|
||||||
|
//
|
||||||
|
//******************************************************************************
|
||||||
|
|
||||||
|
#ifndef CGAL_TC_TEST_TEST_UTILITIES_H
|
||||||
|
#define CGAL_TC_TEST_TEST_UTILITIES_H
|
||||||
|
|
||||||
|
#include <CGAL/Random.h>
|
||||||
|
#include <CGAL/point_generators_2.h>
|
||||||
|
#include <CGAL/point_generators_3.h>
|
||||||
|
#include <CGAL/point_generators_d.h>
|
||||||
|
#include <CGAL/function_objects.h>
|
||||||
|
#include <CGAL/Tangential_complex/Point_cloud.h>
|
||||||
|
#include <CGAL/Tangential_complex/utilities.h>
|
||||||
|
#include <CGAL/IO/Triangulation_off_ostream.h>
|
||||||
|
#include <CGAL/iterator.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
// Actually, this is very slow because the "m_points_ds->insert"
|
||||||
|
// cleans the tree, which is thus built at each query_ANN call
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
template <typename Kernel, typename Point_container>
|
||||||
|
class Point_sparsifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
typedef typename Point_container::value_type Point;
|
||||||
|
typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure<
|
||||||
|
Kernel, Point_container> Points_ds;
|
||||||
|
typedef typename Points_ds::KNS_range KNS_range;
|
||||||
|
|
||||||
|
// We can't instantiate m_points_ds right now since it requires that
|
||||||
|
// points is not empty (which be the case here)
|
||||||
|
Point_sparsifier(Point_container &points,
|
||||||
|
FT sparsity = FT(0.05*0.05))
|
||||||
|
: m_points(points), m_sparsity(sparsity), m_points_ds(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool try_to_insert_point(const Point &p)
|
||||||
|
{
|
||||||
|
if (m_points_ds == NULL)
|
||||||
|
{
|
||||||
|
m_points.push_back(p);
|
||||||
|
m_points_ds = new Points_ds(m_points);
|
||||||
|
m_points_ds->insert(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KNS_range kns_range = m_points_ds->query_ANN(p, 1, false);
|
||||||
|
if (kns_range.begin()->second >= m_sparsity)
|
||||||
|
{
|
||||||
|
m_points.push_back(p);
|
||||||
|
m_points_ds->insert(m_points.size() - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Point_container & m_points;
|
||||||
|
Points_ds * m_points_ds;
|
||||||
|
FT m_sparsity;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// construct_point: dim 2
|
||||||
|
template <typename Kernel>
|
||||||
|
typename Kernel::Point_d construct_point(
|
||||||
|
const Kernel &k,
|
||||||
|
typename Kernel::FT x1, typename Kernel::FT x2)
|
||||||
|
{
|
||||||
|
typename Kernel::FT tab[2];
|
||||||
|
tab[0] = x1; tab[1] = x2;
|
||||||
|
return k.construct_point_d_object()(2, &tab[0], &tab[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct_point: dim 3
|
||||||
|
template <typename Kernel>
|
||||||
|
typename Kernel::Point_d construct_point(
|
||||||
|
const Kernel &k,
|
||||||
|
typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3)
|
||||||
|
{
|
||||||
|
typename Kernel::FT tab[3];
|
||||||
|
tab[0] = x1; tab[1] = x2; tab[2] = x3;
|
||||||
|
return k.construct_point_d_object()(3, &tab[0], &tab[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct_point: dim 4
|
||||||
|
template <typename Kernel>
|
||||||
|
typename Kernel::Point_d construct_point(
|
||||||
|
const Kernel &k,
|
||||||
|
typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
|
||||||
|
typename Kernel::FT x4)
|
||||||
|
{
|
||||||
|
typename Kernel::FT tab[4];
|
||||||
|
tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4;
|
||||||
|
return k.construct_point_d_object()(4, &tab[0], &tab[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct_point: dim 5
|
||||||
|
template <typename Kernel>
|
||||||
|
typename Kernel::Point_d construct_point(
|
||||||
|
const Kernel &k,
|
||||||
|
typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
|
||||||
|
typename Kernel::FT x4, typename Kernel::FT x5)
|
||||||
|
{
|
||||||
|
typename Kernel::FT tab[5];
|
||||||
|
tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4; tab[4] = x5;
|
||||||
|
return k.construct_point_d_object()(5, &tab[0], &tab[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct_point: dim 6
|
||||||
|
template <typename Kernel>
|
||||||
|
typename Kernel::Point_d construct_point(
|
||||||
|
const Kernel &k,
|
||||||
|
typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3,
|
||||||
|
typename Kernel::FT x4, typename Kernel::FT x5, typename Kernel::FT x6)
|
||||||
|
{
|
||||||
|
typename Kernel::FT tab[6];
|
||||||
|
tab[0] = x1; tab[1] = x2; tab[2] = x3; tab[3] = x4; tab[4] = x5; tab[5] = x6;
|
||||||
|
return k.construct_point_d_object()(6, &tab[0], &tab[6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel, typename Point_container>
|
||||||
|
std::vector<typename Point_container::value_type>
|
||||||
|
sparsify_point_set(
|
||||||
|
const Kernel &k, Point_container const& input_pts,
|
||||||
|
typename Kernel::FT min_squared_dist)
|
||||||
|
{
|
||||||
|
typedef typename CGAL::Tangential_complex_::Point_cloud_data_structure<
|
||||||
|
Kernel, Point_container> Points_ds;
|
||||||
|
typedef typename Points_ds::INS_iterator INS_iterator;
|
||||||
|
typedef typename Points_ds::INS_range INS_range;
|
||||||
|
|
||||||
|
typename Kernel::Squared_distance_d sqdist = k.squared_distance_d_object();
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
Wall_clock_timer t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create the output container
|
||||||
|
std::vector<typename Point_container::value_type> output;
|
||||||
|
|
||||||
|
Points_ds points_ds(input_pts);
|
||||||
|
|
||||||
|
std::vector<bool> dropped_points(input_pts.size(), false);
|
||||||
|
|
||||||
|
// Parse the input points, and add them if they are not too close to
|
||||||
|
// the other points
|
||||||
|
std::size_t pt_idx = 0;
|
||||||
|
for (typename Point_container::const_iterator it_pt = input_pts.begin() ;
|
||||||
|
it_pt != input_pts.end();
|
||||||
|
++it_pt, ++pt_idx)
|
||||||
|
{
|
||||||
|
if (dropped_points[pt_idx])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
output.push_back(*it_pt);
|
||||||
|
|
||||||
|
INS_range ins_range = points_ds.query_incremental_ANN(*it_pt);
|
||||||
|
|
||||||
|
// If another point Q is closer that min_squared_dist, mark Q to be dropped
|
||||||
|
for (INS_iterator nn_it = ins_range.begin() ;
|
||||||
|
nn_it != ins_range.end() ;
|
||||||
|
++nn_it)
|
||||||
|
{
|
||||||
|
std::size_t neighbor_point_idx = nn_it->first;
|
||||||
|
// If the neighbor is too close, we drop the neighbor
|
||||||
|
if (nn_it->second < min_squared_dist)
|
||||||
|
{
|
||||||
|
// N.B.: If neighbor_point_idx < pt_idx,
|
||||||
|
// dropped_points[neighbor_point_idx] is already true but adding a
|
||||||
|
// test doesn't make things faster, so why bother?
|
||||||
|
dropped_points[neighbor_point_idx] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_PROFILING
|
||||||
|
std::cerr << "Point set sparsified in " << t.elapsed()
|
||||||
|
<< " seconds." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_plane(
|
||||||
|
std::size_t num_points, int intrinsic_dim, int ambient_dim)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
std::vector<FT> pt(ambient_dim, FT(0));
|
||||||
|
for (int j = 0 ; j < intrinsic_dim ; ++j)
|
||||||
|
pt[j] = rng.get_double(-5., 5.);
|
||||||
|
/*for (int j = intrinsic_dim ; j < ambient_dim ; ++j)
|
||||||
|
pt[j] = rng.get_double(-0.01, 0.01);*/
|
||||||
|
|
||||||
|
Point p = k.construct_point_d_object()(ambient_dim, pt.begin(), pt.end());
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_moment_curve(
|
||||||
|
std::size_t num_points, int dim,
|
||||||
|
typename Kernel::FT min_x , typename Kernel::FT max_x)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
FT x = rng.get_double(min_x, max_x);
|
||||||
|
std::vector<FT> coords;
|
||||||
|
coords.reserve(dim);
|
||||||
|
for (int p = 1 ; p <= dim ; ++p)
|
||||||
|
coords.push_back(std::pow(CGAL::to_double(x), p));
|
||||||
|
Point p = k.construct_point_d_object()(
|
||||||
|
dim, coords.begin(), coords.end());
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// R = big radius, r = small radius
|
||||||
|
template <typename Kernel/*, typename TC_basis*/>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_torus_3D(
|
||||||
|
std::size_t num_points, double R, double r, bool uniform = false
|
||||||
|
/*, std::vector<TC_basis> *p_tangent_planes = NULL*/)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::Vector_d Vector;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
|
||||||
|
//typename Kernel::Construct_vector_d cstr_vec = k.construct_vector_d_object();
|
||||||
|
|
||||||
|
// if uniform
|
||||||
|
std::size_t num_lines = (std::size_t)sqrt(num_points);
|
||||||
|
std::size_t num_cols = num_points/num_lines + 1;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
FT u, v;
|
||||||
|
if (uniform)
|
||||||
|
{
|
||||||
|
std::size_t k1 = i / num_lines;
|
||||||
|
std::size_t k2 = i % num_lines;
|
||||||
|
u = 6.2832 * k1 / num_lines;
|
||||||
|
v = 6.2832 * k2 / num_lines;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = rng.get_double(0, 6.2832);
|
||||||
|
v = rng.get_double(0, 6.2832);
|
||||||
|
}
|
||||||
|
double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v);
|
||||||
|
Point p = construct_point(k,
|
||||||
|
(R + r * std::cos(u)) * std::cos(v),
|
||||||
|
(R + r * std::cos(u)) * std::sin(v),
|
||||||
|
r * std::sin(u));
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
/*if (p_tangent_planes)
|
||||||
|
{
|
||||||
|
TC_basis tp(p);
|
||||||
|
tp.push_back(cstr_vec(
|
||||||
|
-r * std::cos(v) * std::sin(u),
|
||||||
|
-r * std::sin(v) * std::sin(u),
|
||||||
|
r * std::cos(u)));
|
||||||
|
tp.push_back(cstr_vec(
|
||||||
|
-(R + r * std::cos(u)) * std::sin(v),
|
||||||
|
(R + r * std::cos(u)) * std::cos(v),
|
||||||
|
0));
|
||||||
|
p_tangent_planes->push_back(
|
||||||
|
CGAL::Tangential_complex_::compute_gram_schmidt_basis(sp, k));
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel, typename OutputIterator>
|
||||||
|
static void generate_uniform_points_on_torus_d(
|
||||||
|
const Kernel &k, int dim, std::size_t num_slices,
|
||||||
|
OutputIterator out,
|
||||||
|
double radius_noise_percentage = 0.,
|
||||||
|
std::vector<typename Kernel::FT> current_point = std::vector<typename Kernel::FT>())
|
||||||
|
{
|
||||||
|
static CGAL::Random rng;
|
||||||
|
if (current_point.size() == 2*dim)
|
||||||
|
{
|
||||||
|
*out++ = k.construct_point_d_object()(
|
||||||
|
static_cast<int>(current_point.size()),
|
||||||
|
current_point.begin(), current_point.end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (std::size_t slice_idx = 0 ; slice_idx < num_slices ; ++slice_idx)
|
||||||
|
{
|
||||||
|
double radius_noise_ratio = 1.;
|
||||||
|
if (radius_noise_percentage > 0.)
|
||||||
|
{
|
||||||
|
radius_noise_ratio = rng.get_double(
|
||||||
|
(100. - radius_noise_percentage)/100.,
|
||||||
|
(100. + radius_noise_percentage)/100.);
|
||||||
|
}
|
||||||
|
std::vector<typename Kernel::FT> cp2 = current_point;
|
||||||
|
FT alpha = 6.2832 * slice_idx / num_slices;
|
||||||
|
cp2.push_back(radius_noise_ratio*std::cos(alpha));
|
||||||
|
cp2.push_back(radius_noise_ratio*std::sin(alpha));
|
||||||
|
generate_uniform_points_on_torus_d(
|
||||||
|
k, dim, num_slices, out, radius_noise_percentage, cp2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_torus_d(
|
||||||
|
std::size_t num_points, int dim, bool uniform = false,
|
||||||
|
double radius_noise_percentage = 0.)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
static CGAL::Random rng;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
if (uniform)
|
||||||
|
{
|
||||||
|
std::size_t num_slices = (std::size_t)std::pow(num_points, 1./dim);
|
||||||
|
generate_uniform_points_on_torus_d(
|
||||||
|
k, dim, num_slices, std::back_inserter(points), radius_noise_percentage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
double radius_noise_ratio = 1.;
|
||||||
|
if (radius_noise_percentage > 0.)
|
||||||
|
{
|
||||||
|
radius_noise_ratio = rng.get_double(
|
||||||
|
(100. - radius_noise_percentage)/100.,
|
||||||
|
(100. + radius_noise_percentage)/100.);
|
||||||
|
}
|
||||||
|
std::vector<typename Kernel::FT> pt;
|
||||||
|
pt.reserve(dim*2);
|
||||||
|
for (int curdim = 0 ; curdim < dim ; ++curdim)
|
||||||
|
{
|
||||||
|
FT alpha = rng.get_double(0, 6.2832);
|
||||||
|
pt.push_back(radius_noise_ratio*std::cos(alpha));
|
||||||
|
pt.push_back(radius_noise_ratio*std::sin(alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
Point p = k.construct_point_d_object()(pt.begin(), pt.end());
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_sphere_d(
|
||||||
|
std::size_t num_points, int dim, double radius,
|
||||||
|
double radius_noise_percentage = 0.)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
Point p = *generator++;
|
||||||
|
if (radius_noise_percentage > 0.)
|
||||||
|
{
|
||||||
|
double radius_noise_ratio = rng.get_double(
|
||||||
|
(100. - radius_noise_percentage)/100.,
|
||||||
|
(100. + radius_noise_percentage)/100.);
|
||||||
|
|
||||||
|
typename Kernel::Point_to_vector_d k_pt_to_vec =
|
||||||
|
k.point_to_vector_d_object();
|
||||||
|
typename Kernel::Vector_to_point_d k_vec_to_pt =
|
||||||
|
k.vector_to_point_d_object();
|
||||||
|
typename Kernel::Scaled_vector_d k_scaled_vec =
|
||||||
|
k.scaled_vector_d_object();
|
||||||
|
p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
|
||||||
|
}
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_two_spheres_d(
|
||||||
|
std::size_t num_points, int dim, double radius,
|
||||||
|
double distance_between_centers, double radius_noise_percentage = 0.)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::Vector_d Vector;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
CGAL::Random_points_on_sphere_d<Point> generator(dim, radius);
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
|
||||||
|
std::vector<FT> t(dim, FT(0));
|
||||||
|
t[0] = distance_between_centers;
|
||||||
|
Vector c1_to_c2(t.begin(), t.end());
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
Point p = *generator++;
|
||||||
|
if (radius_noise_percentage > 0.)
|
||||||
|
{
|
||||||
|
double radius_noise_ratio = rng.get_double(
|
||||||
|
(100. - radius_noise_percentage)/100.,
|
||||||
|
(100. + radius_noise_percentage)/100.);
|
||||||
|
|
||||||
|
typename Kernel::Point_to_vector_d k_pt_to_vec =
|
||||||
|
k.point_to_vector_d_object();
|
||||||
|
typename Kernel::Vector_to_point_d k_vec_to_pt =
|
||||||
|
k.vector_to_point_d_object();
|
||||||
|
typename Kernel::Scaled_vector_d k_scaled_vec =
|
||||||
|
k.scaled_vector_d_object();
|
||||||
|
p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio));
|
||||||
|
}
|
||||||
|
|
||||||
|
typename Kernel::Translated_point_d k_transl =
|
||||||
|
k.translated_point_d_object();
|
||||||
|
Point p2 = k_transl(p, c1_to_c2);
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
if (sparsifier.try_to_insert_point(p2))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
points.push_back(p2);
|
||||||
|
i += 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Product of a 3-sphere and a circle => d = 3 / D = 5
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_3sphere_and_circle(
|
||||||
|
std::size_t num_points, double sphere_radius)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::Vector_d Vector;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
CGAL::Random_points_on_sphere_d<Point> generator(3, sphere_radius);
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
|
||||||
|
typename Kernel::Translated_point_d k_transl =
|
||||||
|
k.translated_point_d_object();
|
||||||
|
typename Kernel::Compute_coordinate_d k_coord =
|
||||||
|
k.compute_coordinate_d_object();
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
Point p_sphere = *generator++; // First 3 coords
|
||||||
|
|
||||||
|
FT alpha = rng.get_double(0, 6.2832);
|
||||||
|
std::vector<FT> pt(5);
|
||||||
|
pt[0] = k_coord(p_sphere, 0);
|
||||||
|
pt[1] = k_coord(p_sphere, 1);
|
||||||
|
pt[2] = k_coord(p_sphere, 2);
|
||||||
|
pt[3] = std::cos(alpha);
|
||||||
|
pt[4] = std::sin(alpha);
|
||||||
|
Point p(pt.begin(), pt.end());
|
||||||
|
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
if (sparsifier.try_to_insert_point(p2))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a = big radius, b = small radius
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(
|
||||||
|
std::size_t num_points, double a, double b, bool uniform = false)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
|
||||||
|
// if uniform
|
||||||
|
std::size_t num_lines = (std::size_t)sqrt(num_points);
|
||||||
|
std::size_t num_cols = num_points/num_lines + 1;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
FT u, v;
|
||||||
|
if (uniform)
|
||||||
|
{
|
||||||
|
std::size_t k1 = i / num_lines;
|
||||||
|
std::size_t k2 = i % num_lines;
|
||||||
|
u = 6.2832 * k1 / num_lines;
|
||||||
|
v = 6.2832 * k2 / num_lines;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = rng.get_double(0, 6.2832);
|
||||||
|
v = rng.get_double(0, 6.2832);
|
||||||
|
}
|
||||||
|
double tmp = cos(u/2)*sin(v) - sin(u/2)*sin(2.*v);
|
||||||
|
Point p = construct_point(k,
|
||||||
|
(a + b*tmp)*cos(u),
|
||||||
|
(a + b*tmp)*sin(u),
|
||||||
|
b*(sin(u/2)*sin(v) + cos(u/2)*sin(2.*v)));
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a = big radius, b = small radius
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(
|
||||||
|
std::size_t num_points, double a, double b, double noise = 0., bool uniform = false)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
|
||||||
|
// if uniform
|
||||||
|
std::size_t num_lines = (std::size_t)sqrt(num_points);
|
||||||
|
std::size_t num_cols = num_points/num_lines + 1;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
FT u, v;
|
||||||
|
if (uniform)
|
||||||
|
{
|
||||||
|
std::size_t k1 = i / num_lines;
|
||||||
|
std::size_t k2 = i % num_lines;
|
||||||
|
u = 6.2832 * k1 / num_lines;
|
||||||
|
v = 6.2832 * k2 / num_lines;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = rng.get_double(0, 6.2832);
|
||||||
|
v = rng.get_double(0, 6.2832);
|
||||||
|
}
|
||||||
|
Point p = construct_point(k,
|
||||||
|
(a + b*cos(v))*cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
|
||||||
|
(a + b*cos(v))*sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)),
|
||||||
|
b*sin(v)*cos(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)),
|
||||||
|
b*sin(v)*sin(u/2) + (noise == 0. ? 0. : rng.get_double(0, noise)));
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// a = big radius, b = small radius
|
||||||
|
template <typename Kernel>
|
||||||
|
std::vector<typename Kernel::Point_d>
|
||||||
|
generate_points_on_klein_bottle_variant_5D(
|
||||||
|
std::size_t num_points, double a, double b, bool uniform = false)
|
||||||
|
{
|
||||||
|
typedef typename Kernel::Point_d Point;
|
||||||
|
typedef typename Kernel::FT FT;
|
||||||
|
Kernel k;
|
||||||
|
CGAL::Random rng;
|
||||||
|
|
||||||
|
// if uniform
|
||||||
|
std::size_t num_lines = (std::size_t)sqrt(num_points);
|
||||||
|
std::size_t num_cols = num_points/num_lines + 1;
|
||||||
|
|
||||||
|
std::vector<Point> points;
|
||||||
|
points.reserve(num_points);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
Point_sparsifier<Kernel, std::vector<Point> > sparsifier(points);
|
||||||
|
#endif
|
||||||
|
for (std::size_t i = 0 ; i < num_points ; )
|
||||||
|
{
|
||||||
|
FT u, v;
|
||||||
|
if (uniform)
|
||||||
|
{
|
||||||
|
std::size_t k1 = i / num_lines;
|
||||||
|
std::size_t k2 = i % num_lines;
|
||||||
|
u = 6.2832 * k1 / num_lines;
|
||||||
|
v = 6.2832 * k2 / num_lines;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u = rng.get_double(0, 6.2832);
|
||||||
|
v = rng.get_double(0, 6.2832);
|
||||||
|
}
|
||||||
|
FT x1 = (a + b*cos(v))*cos(u);
|
||||||
|
FT x2 = (a + b*cos(v))*sin(u);
|
||||||
|
FT x3 = b*sin(v)*cos(u/2);
|
||||||
|
FT x4 = b*sin(v)*sin(u/2);
|
||||||
|
FT x5 = x1 + x2 + x3 + x4;
|
||||||
|
|
||||||
|
Point p = construct_point(k, x1, x2, x3, x4, x5);
|
||||||
|
#ifdef CGAL_TC_USE_SLOW_BUT_ACCURATE_SPARSIFIER
|
||||||
|
if (sparsifier.try_to_insert_point(p))
|
||||||
|
++i;
|
||||||
|
#else
|
||||||
|
points.push_back(p);
|
||||||
|
++i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Kernel>
|
||||||
|
void benchmark_spatial_search(
|
||||||
|
const std::vector<typename Kernel::Point_d> &points, const Kernel &k,
|
||||||
|
std::ostream & csv_file)
|
||||||
|
{
|
||||||
|
std::cout <<
|
||||||
|
"****************************************\n"
|
||||||
|
"***** Benchmarking spatial search ******\n"
|
||||||
|
"****************************************\n\n";
|
||||||
|
|
||||||
|
const std::size_t NUM_QUERIES = 100000;
|
||||||
|
const std::size_t NUM_NEIGHBORS = 50;
|
||||||
|
|
||||||
|
typedef Kernel::FT FT;
|
||||||
|
typedef Kernel::Point_d Point;
|
||||||
|
typedef std::vector<Point> Points;
|
||||||
|
|
||||||
|
CGAL::Random random_generator;
|
||||||
|
Wall_clock_timer t;
|
||||||
|
|
||||||
|
//****************************** CGAL ***************************************
|
||||||
|
{
|
||||||
|
std::cout << "\n=== CGAL ===\n";
|
||||||
|
|
||||||
|
typedef CGAL::Tangential_complex_::Point_cloud_data_structure<Kernel, Points>
|
||||||
|
Points_ds;
|
||||||
|
typedef Points_ds::KNS_range KNS_range;
|
||||||
|
typedef Points_ds::KNS_iterator KNS_iterator;
|
||||||
|
typedef Points_ds::INS_range INS_range;
|
||||||
|
typedef Points_ds::INS_iterator INS_iterator;
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
Points_ds points_ds(points);
|
||||||
|
double init_time = t.elapsed();
|
||||||
|
std::cout << "Init: " << init_time << std::endl;
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i)
|
||||||
|
{
|
||||||
|
std::size_t pt_idx = random_generator.get_int(0, points.size() - 1);
|
||||||
|
KNS_range kns_range = points_ds.query_ANN(
|
||||||
|
points[pt_idx], NUM_NEIGHBORS, true);
|
||||||
|
}
|
||||||
|
double queries_time = t.elapsed();
|
||||||
|
std::cout << NUM_QUERIES << " queries among "
|
||||||
|
<< points.size() << " points: " << queries_time << std::endl;
|
||||||
|
csv_file << queries_time << ";";
|
||||||
|
}
|
||||||
|
//**************************** nanoflann ************************************
|
||||||
|
{
|
||||||
|
std::cout << "\n=== nanoflann ===\n";
|
||||||
|
|
||||||
|
typedef CGAL::Tangential_complex_::
|
||||||
|
Point_cloud_data_structure__nanoflann<Kernel, Points>
|
||||||
|
Points_ds;
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
Points_ds points_ds(points, k);
|
||||||
|
double init_time = t.elapsed();
|
||||||
|
std::cout << "Init: " << init_time << std::endl;
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i)
|
||||||
|
{
|
||||||
|
std::size_t pt_idx = random_generator.get_int(0, points.size() - 1);
|
||||||
|
std::size_t neighbors_indices[NUM_NEIGHBORS];
|
||||||
|
FT neighbors_sq_distances[NUM_NEIGHBORS];
|
||||||
|
points_ds.query_ANN(
|
||||||
|
points[pt_idx], NUM_NEIGHBORS, neighbors_indices, neighbors_sq_distances);
|
||||||
|
}
|
||||||
|
double queries_time = t.elapsed();
|
||||||
|
std::cout << NUM_QUERIES << " queries among "
|
||||||
|
<< points.size() << " points: " << queries_time << std::endl;
|
||||||
|
csv_file << queries_time << ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************* ANN ***************************************
|
||||||
|
{
|
||||||
|
std::cout << "\n=== ANN ===\n";
|
||||||
|
|
||||||
|
typedef CGAL::Tangential_complex_::
|
||||||
|
Point_cloud_data_structure__ANN<Kernel, Points>
|
||||||
|
Points_ds;
|
||||||
|
|
||||||
|
t.reset();
|
||||||
|
Points_ds points_ds(points, k);
|
||||||
|
double init_time = t.elapsed();
|
||||||
|
std::cout << "Init: " << init_time << std::endl;
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
for (std::size_t i = 0 ; i < NUM_QUERIES ; ++i)
|
||||||
|
{
|
||||||
|
std::size_t pt_idx = random_generator.get_int(0, points.size() - 1);
|
||||||
|
int neighbors_indices[NUM_NEIGHBORS];
|
||||||
|
double neighbors_sq_distances[NUM_NEIGHBORS];
|
||||||
|
points_ds.query_ANN(
|
||||||
|
points[pt_idx], NUM_NEIGHBORS, neighbors_indices, neighbors_sq_distances);
|
||||||
|
}
|
||||||
|
double queries_time = t.elapsed();
|
||||||
|
std::cout << NUM_QUERIES << " queries among "
|
||||||
|
<< points.size() << " points: " << queries_time << std::endl;
|
||||||
|
csv_file << queries_time << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H
|
||||||
|
|
@ -124,7 +124,7 @@ public:
|
||||||
using Base::vertices_begin;
|
using Base::vertices_begin;
|
||||||
using Base::vertices_end;
|
using Base::vertices_end;
|
||||||
// using Base::
|
// using Base::
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//*** Side_of_oriented_subsphere_d ***
|
//*** Side_of_oriented_subsphere_d ***
|
||||||
typedef typename Base::Flat_orientation_d Flat_orientation_d;
|
typedef typename Base::Flat_orientation_d Flat_orientation_d;
|
||||||
|
|
@ -161,12 +161,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// With this constructor,
|
// With this constructor,
|
||||||
// the user can specify a Flat_orientation_d object to be used for
|
// the user can specify a Flat_orientation_d object to be used for
|
||||||
// orienting simplices of a specific dimension
|
// orienting simplices of a specific dimension
|
||||||
// (= preset_flat_orientation_.first)
|
// (= preset_flat_orientation_.first)
|
||||||
// It it used by the dark triangulations created by DT::remove
|
// It it used by the dark triangulations created by DT::remove
|
||||||
Delaunay_triangulation(
|
Delaunay_triangulation(
|
||||||
int dim,
|
int dim,
|
||||||
const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
|
const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
|
||||||
const Geom_traits &k = Geom_traits())
|
const Geom_traits &k = Geom_traits())
|
||||||
: Base(dim, preset_flat_orientation, k)
|
: Base(dim, preset_flat_orientation, k)
|
||||||
|
|
@ -181,8 +181,8 @@ public:
|
||||||
Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const
|
Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const
|
||||||
{
|
{
|
||||||
return Side_of_oriented_subsphere_d (
|
return Side_of_oriented_subsphere_d (
|
||||||
flat_orientation_,
|
flat_orientation_,
|
||||||
geom_traits().construct_flat_orientation_d_object(),
|
geom_traits().construct_flat_orientation_d_object(),
|
||||||
geom_traits().in_flat_side_of_oriented_sphere_d_object()
|
geom_traits().in_flat_side_of_oriented_sphere_d_object()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +294,7 @@ public:
|
||||||
|
|
||||||
Orientation o = ori_(
|
Orientation o = ori_(
|
||||||
boost::make_transform_iterator(s->vertices_begin(), spivi),
|
boost::make_transform_iterator(s->vertices_begin(), spivi),
|
||||||
boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
|
boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
|
||||||
spivi));
|
spivi));
|
||||||
|
|
||||||
if( POSITIVE == o )
|
if( POSITIVE == o )
|
||||||
|
|
@ -323,9 +323,9 @@ public:
|
||||||
return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f)));
|
return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
|
||||||
|
|
||||||
bool is_valid(bool verbose = false, int level = 0) const;
|
bool is_valid(bool verbose = false, int level = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -342,7 +342,7 @@ private:
|
||||||
Conflict_traversal_pred_in_fullspace;
|
Conflict_traversal_pred_in_fullspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
// FUNCTIONS THAT ARE MEMBER METHODS:
|
// FUNCTIONS THAT ARE MEMBER METHODS:
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
|
||||||
|
|
@ -515,7 +515,7 @@ Delaunay_triangulation<DCTraits, TDS>
|
||||||
typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
|
typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
|
||||||
Dark_full_cells conflict_zone;
|
Dark_full_cells conflict_zone;
|
||||||
std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
|
std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
|
||||||
|
|
||||||
dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
|
dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
|
||||||
// Make the dark simplices in the conflict zone searchable
|
// Make the dark simplices in the conflict zone searchable
|
||||||
conflict_zone.make_searchable();
|
conflict_zone.make_searchable();
|
||||||
|
|
@ -613,7 +613,7 @@ Delaunay_triangulation<DCTraits, TDS>
|
||||||
int li = light_s->index(dark_s->vertex(di)->data());
|
int li = light_s->index(dark_s->vertex(di)->data());
|
||||||
Rotor light_r(light_s, li, light_i);
|
Rotor light_r(light_s, li, light_i);
|
||||||
typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
|
typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
|
||||||
|
|
||||||
while (simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))))
|
while (simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))))
|
||||||
light_r = rotate_rotor(light_r);
|
light_r = rotate_rotor(light_r);
|
||||||
|
|
||||||
|
|
@ -874,27 +874,27 @@ template< typename DCTraits, typename TDS >
|
||||||
bool
|
bool
|
||||||
Delaunay_triangulation<DCTraits, TDS>
|
Delaunay_triangulation<DCTraits, TDS>
|
||||||
::is_valid(bool verbose, int level) const
|
::is_valid(bool verbose, int level) const
|
||||||
{
|
{
|
||||||
if (!Base::is_valid(verbose, level))
|
if (!Base::is_valid(verbose, level))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int dim = current_dimension();
|
int dim = current_dimension();
|
||||||
if (dim == maximal_dimension())
|
if (dim == maximal_dimension())
|
||||||
{
|
{
|
||||||
for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ;
|
for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ;
|
||||||
cit != finite_full_cells_end() ; ++cit )
|
cit != this->finite_full_cells_end() ; ++cit )
|
||||||
{
|
{
|
||||||
Full_cell_const_handle ch = cit.base();
|
Full_cell_const_handle ch = cit.base();
|
||||||
for(int i = 0; i < dim+1 ; ++i )
|
for(int i = 0; i < dim+1 ; ++i )
|
||||||
{
|
{
|
||||||
// If the i-th neighbor is not an infinite cell
|
// If the i-th neighbor is not an infinite cell
|
||||||
Vertex_handle opposite_vh =
|
Vertex_handle opposite_vh =
|
||||||
ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
|
ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
|
||||||
if (!is_infinite(opposite_vh))
|
if (!is_infinite(opposite_vh))
|
||||||
{
|
{
|
||||||
Side_of_oriented_sphere_d side =
|
Side_of_oriented_sphere_d side =
|
||||||
geom_traits().side_of_oriented_sphere_d_object();
|
geom_traits().side_of_oriented_sphere_d_object();
|
||||||
if (side(Point_const_iterator(ch->vertices_begin()),
|
if (side(Point_const_iterator(ch->vertices_begin()),
|
||||||
Point_const_iterator(ch->vertices_end()),
|
Point_const_iterator(ch->vertices_end()),
|
||||||
opposite_vh->point()) == ON_BOUNDED_SIDE)
|
opposite_vh->point()) == ON_BOUNDED_SIDE)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ input_point(std::istream & is, const Traits &traits, P & p)
|
||||||
{
|
{
|
||||||
typedef typename Traits::FT FT;
|
typedef typename Traits::FT FT;
|
||||||
std::vector<FT> coords;
|
std::vector<FT> coords;
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
|
@ -125,7 +125,7 @@ operator>>(std::istream &is, typename Wrap::Point_d<K> & p)
|
||||||
typedef typename Wrap::Point_d<K> P;
|
typedef typename Wrap::Point_d<K> P;
|
||||||
typedef typename K::FT FT;
|
typedef typename K::FT FT;
|
||||||
std::vector<FT> coords;
|
std::vector<FT> coords;
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
|
@ -165,7 +165,7 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d<K> & wp)
|
||||||
std::vector<FT> coords;
|
std::vector<FT> coords;
|
||||||
while (line_sstr >> temp)
|
while (line_sstr >> temp)
|
||||||
coords.push_back(temp);
|
coords.push_back(temp);
|
||||||
|
|
||||||
typename std::vector<FT>::iterator last = coords.end() - 1;
|
typename std::vector<FT>::iterator last = coords.end() - 1;
|
||||||
P p = P(coords.begin(), last);
|
P p = P(coords.begin(), last);
|
||||||
wp = WP(p, *last);
|
wp = WP(p, *last);
|
||||||
|
|
@ -173,9 +173,35 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d<K> & wp)
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: test if the stream is binary or text?
|
||||||
|
template<typename K>
|
||||||
|
std::istream &
|
||||||
|
operator>>(std::istream &is, typename Wrap::Vector_d<K> & v)
|
||||||
|
{
|
||||||
|
typedef typename Wrap::Vector_d<K> V;
|
||||||
|
typedef typename K::FT FT;
|
||||||
|
std::vector<FT> coords;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!std::getline(is, line))
|
||||||
|
return is;
|
||||||
|
if (line != "")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::stringstream line_sstr(line);
|
||||||
|
FT temp;
|
||||||
|
while (line_sstr >> temp)
|
||||||
|
coords.push_back(temp);
|
||||||
|
|
||||||
|
v = V(coords.begin(), coords.end());
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
template < class GT, class TDS >
|
template < class GT, class TDS >
|
||||||
std::ostream &
|
std::ostream &
|
||||||
export_triangulation_to_off(std::ostream & os,
|
export_triangulation_to_off(std::ostream & os,
|
||||||
const Triangulation<GT,TDS> & tr,
|
const Triangulation<GT,TDS> & tr,
|
||||||
bool in_3D_export_surface_only = false)
|
bool in_3D_export_surface_only = false)
|
||||||
{
|
{
|
||||||
|
|
@ -188,7 +214,7 @@ export_triangulation_to_off(std::ostream & os,
|
||||||
typedef typename Tr::Full_cell_const_iterator Full_cell_iterator;
|
typedef typename Tr::Full_cell_const_iterator Full_cell_iterator;
|
||||||
typedef typename Tr::Full_cell Full_cell;
|
typedef typename Tr::Full_cell Full_cell;
|
||||||
typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator;
|
typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator;
|
||||||
|
|
||||||
if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3)
|
if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3.";
|
std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3.";
|
||||||
|
|
@ -199,11 +225,11 @@ export_triangulation_to_off(std::ostream & os,
|
||||||
size_t n = tr.number_of_vertices();
|
size_t n = tr.number_of_vertices();
|
||||||
|
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
|
|
||||||
// write the vertices
|
// write the vertices
|
||||||
std::map<Vertex_handle, int> index_of_vertex;
|
std::map<Vertex_handle, int> index_of_vertex;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(Finite_vertex_iterator it = tr.finite_vertices_begin();
|
for(Finite_vertex_iterator it = tr.finite_vertices_begin();
|
||||||
it != tr.finite_vertices_end(); ++it, ++i)
|
it != tr.finite_vertices_end(); ++it, ++i)
|
||||||
{
|
{
|
||||||
Triangulation_IO::output_point(output, tr.geom_traits(), it->point());
|
Triangulation_IO::output_point(output, tr.geom_traits(), it->point());
|
||||||
|
|
@ -213,7 +239,7 @@ export_triangulation_to_off(std::ostream & os,
|
||||||
index_of_vertex[it.base()] = i;
|
index_of_vertex[it.base()] = i;
|
||||||
}
|
}
|
||||||
CGAL_assertion( i == n );
|
CGAL_assertion( i == n );
|
||||||
|
|
||||||
size_t number_of_triangles = 0;
|
size_t number_of_triangles = 0;
|
||||||
if (tr.maximal_dimension() == 2)
|
if (tr.maximal_dimension() == 2)
|
||||||
{
|
{
|
||||||
|
|
@ -248,7 +274,7 @@ export_triangulation_to_off(std::ostream & os,
|
||||||
output << index_of_vertex[*vit] << " ";
|
output << index_of_vertex[*vit] << " ";
|
||||||
}
|
}
|
||||||
output << std::endl;
|
output << std::endl;
|
||||||
++number_of_triangles;
|
++number_of_triangles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +310,7 @@ export_triangulation_to_off(std::ostream & os,
|
||||||
}
|
}
|
||||||
|
|
||||||
os << "OFF \n"
|
os << "OFF \n"
|
||||||
<< n << " "
|
<< n << " "
|
||||||
<< number_of_triangles << " 0\n"
|
<< number_of_triangles << " 0\n"
|
||||||
<< output.str();
|
<< output.str();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class Regular_triangulation
|
||||||
typedef Regular_triangulation_euclidean_traits<Traits_> RTTraits;
|
typedef Regular_triangulation_euclidean_traits<Traits_> RTTraits;
|
||||||
typedef typename RTTraits::Dimension Maximal_dimension_;
|
typedef typename RTTraits::Dimension Maximal_dimension_;
|
||||||
typedef typename Default::Get<
|
typedef typename Default::Get<
|
||||||
TDS_,
|
TDS_,
|
||||||
Triangulation_data_structure<
|
Triangulation_data_structure<
|
||||||
Maximal_dimension_,
|
Maximal_dimension_,
|
||||||
Triangulation_vertex<RTTraits>,
|
Triangulation_vertex<RTTraits>,
|
||||||
|
|
@ -71,7 +71,7 @@ public: // PUBLIC NESTED TYPES
|
||||||
typedef typename Base::Full_cell Full_cell;
|
typedef typename Base::Full_cell Full_cell;
|
||||||
typedef typename Base::Facet Facet;
|
typedef typename Base::Facet Facet;
|
||||||
typedef typename Base::Face Face;
|
typedef typename Base::Face Face;
|
||||||
|
|
||||||
typedef Maximal_dimension_ Maximal_dimension;
|
typedef Maximal_dimension_ Maximal_dimension;
|
||||||
typedef typename RTTraits::Bare_point_d Bare_point;
|
typedef typename RTTraits::Bare_point_d Bare_point;
|
||||||
typedef typename RTTraits::Weighted_point_d Weighted_point;
|
typedef typename RTTraits::Weighted_point_d Weighted_point;
|
||||||
|
|
@ -156,7 +156,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS
|
||||||
|
|
||||||
Regular_triangulation(int dim, const Geom_traits &k = Geom_traits())
|
Regular_triangulation(int dim, const Geom_traits &k = Geom_traits())
|
||||||
|
|
@ -165,12 +165,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// With this constructor,
|
// With this constructor,
|
||||||
// the user can specify a Flat_orientation_d object to be used for
|
// the user can specify a Flat_orientation_d object to be used for
|
||||||
// orienting simplices of a specific dimension
|
// orienting simplices of a specific dimension
|
||||||
// (= preset_flat_orientation_.first)
|
// (= preset_flat_orientation_.first)
|
||||||
// It it used by the dark triangulations created by DT::remove
|
// It it used by the dark triangulations created by DT::remove
|
||||||
Regular_triangulation(
|
Regular_triangulation(
|
||||||
int dim,
|
int dim,
|
||||||
const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
|
const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation,
|
||||||
const Geom_traits &k = Geom_traits())
|
const Geom_traits &k = Geom_traits())
|
||||||
: Base(dim, preset_flat_orientation, k)
|
: Base(dim, preset_flat_orientation, k)
|
||||||
|
|
@ -185,8 +185,8 @@ public:
|
||||||
Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const
|
Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const
|
||||||
{
|
{
|
||||||
return Power_side_of_power_sphere_for_non_maximal_dim_d (
|
return Power_side_of_power_sphere_for_non_maximal_dim_d (
|
||||||
flat_orientation_,
|
flat_orientation_,
|
||||||
geom_traits().construct_flat_orientation_d_object(),
|
geom_traits().construct_flat_orientation_d_object(),
|
||||||
geom_traits().in_flat_power_side_of_power_sphere_d_object()
|
geom_traits().in_flat_power_side_of_power_sphere_d_object()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -246,13 +246,13 @@ public:
|
||||||
return number_of_vertices() - n;
|
return number_of_vertices() - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex_handle insert(const Weighted_point &,
|
Vertex_handle insert(const Weighted_point &,
|
||||||
const Locate_type,
|
const Locate_type,
|
||||||
const Face &,
|
const Face &,
|
||||||
const Facet &,
|
const Facet &,
|
||||||
const Full_cell_handle);
|
const Full_cell_handle);
|
||||||
|
|
||||||
Vertex_handle insert(const Weighted_point & p,
|
Vertex_handle insert(const Weighted_point & p,
|
||||||
const Full_cell_handle start = Full_cell_handle())
|
const Full_cell_handle start = Full_cell_handle())
|
||||||
{
|
{
|
||||||
Locate_type lt;
|
Locate_type lt;
|
||||||
|
|
@ -272,14 +272,14 @@ public:
|
||||||
Vertex_handle insert_in_conflicting_cell(
|
Vertex_handle insert_in_conflicting_cell(
|
||||||
const Weighted_point &, const Full_cell_handle,
|
const Weighted_point &, const Full_cell_handle,
|
||||||
const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle());
|
const Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle());
|
||||||
|
|
||||||
Vertex_handle insert_if_in_star(const Weighted_point &,
|
Vertex_handle insert_if_in_star(const Weighted_point &,
|
||||||
const Vertex_handle,
|
const Vertex_handle,
|
||||||
const Locate_type,
|
const Locate_type,
|
||||||
const Face &,
|
const Face &,
|
||||||
const Facet &,
|
const Facet &,
|
||||||
const Full_cell_handle);
|
const Full_cell_handle);
|
||||||
|
|
||||||
Vertex_handle insert_if_in_star(
|
Vertex_handle insert_if_in_star(
|
||||||
const Weighted_point & p, const Vertex_handle star_center,
|
const Weighted_point & p, const Vertex_handle star_center,
|
||||||
const Full_cell_handle start = Full_cell_handle())
|
const Full_cell_handle start = Full_cell_handle())
|
||||||
|
|
@ -292,7 +292,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex_handle insert_if_in_star(
|
Vertex_handle insert_if_in_star(
|
||||||
const Weighted_point & p, const Vertex_handle star_center,
|
const Weighted_point & p, const Vertex_handle star_center,
|
||||||
const Vertex_handle hint)
|
const Vertex_handle hint)
|
||||||
{
|
{
|
||||||
CGAL_assertion( Vertex_handle() != hint );
|
CGAL_assertion( Vertex_handle() != hint );
|
||||||
|
|
@ -348,7 +348,7 @@ public:
|
||||||
|
|
||||||
Orientation o = ori_(
|
Orientation o = ori_(
|
||||||
boost::make_transform_iterator(s->vertices_begin(), spivi),
|
boost::make_transform_iterator(s->vertices_begin(), spivi),
|
||||||
boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
|
boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1,
|
||||||
spivi));
|
spivi));
|
||||||
|
|
||||||
if( POSITIVE == o )
|
if( POSITIVE == o )
|
||||||
|
|
@ -377,9 +377,9 @@ public:
|
||||||
return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f)));
|
return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY
|
||||||
|
|
||||||
bool is_valid(bool verbose = false, int level = 0) const;
|
bool is_valid(bool verbose = false, int level = 0) const;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC
|
||||||
|
|
@ -390,10 +390,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
bool
|
bool
|
||||||
does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end,
|
does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end,
|
||||||
Vertex_handle vh) const
|
Vertex_handle vh) const
|
||||||
{
|
{
|
||||||
// Check all vertices
|
// Check all vertices
|
||||||
|
|
@ -412,7 +412,7 @@ private:
|
||||||
|
|
||||||
template<typename InputIterator, typename OutputIterator>
|
template<typename InputIterator, typename OutputIterator>
|
||||||
void
|
void
|
||||||
process_conflict_zone(InputIterator cz_begin, InputIterator cz_end,
|
process_conflict_zone(InputIterator cz_begin, InputIterator cz_end,
|
||||||
OutputIterator vertices_out) const
|
OutputIterator vertices_out) const
|
||||||
{
|
{
|
||||||
// Get all vertices
|
// Get all vertices
|
||||||
|
|
@ -432,10 +432,10 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
void
|
void
|
||||||
process_cz_vertices_after_insertion(InputIterator vertices_begin,
|
process_cz_vertices_after_insertion(InputIterator vertices_begin,
|
||||||
InputIterator vertices_end)
|
InputIterator vertices_end)
|
||||||
{
|
{
|
||||||
// Get all vertices
|
// Get all vertices
|
||||||
|
|
@ -463,14 +463,14 @@ private:
|
||||||
Conflict_traversal_pred_in_subspace;
|
Conflict_traversal_pred_in_subspace;
|
||||||
typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace>
|
typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace>
|
||||||
Conflict_traversal_pred_in_fullspace;
|
Conflict_traversal_pred_in_fullspace;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES
|
||||||
std::vector<Weighted_point> m_hidden_points;
|
std::vector<Weighted_point> m_hidden_points;
|
||||||
|
|
||||||
}; // class Regular_triangulation
|
}; // class Regular_triangulation
|
||||||
|
|
||||||
|
|
||||||
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||||
// FUNCTIONS THAT ARE MEMBER METHODS:
|
// FUNCTIONS THAT ARE MEMBER METHODS:
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS
|
||||||
|
|
@ -536,8 +536,8 @@ Regular_triangulation<Traits, TDS>
|
||||||
typedef Triangulation_full_cell<
|
typedef Triangulation_full_cell<
|
||||||
Geom_traits,
|
Geom_traits,
|
||||||
internal::Triangulation::Dark_full_cell_data<TDS> > Dark_full_cell_base;
|
internal::Triangulation::Dark_full_cell_data<TDS> > Dark_full_cell_base;
|
||||||
typedef Triangulation_data_structure<Maximal_dimension,
|
typedef Triangulation_data_structure<Maximal_dimension,
|
||||||
Dark_vertex_base,
|
Dark_vertex_base,
|
||||||
Dark_full_cell_base
|
Dark_full_cell_base
|
||||||
> Dark_tds;
|
> Dark_tds;
|
||||||
typedef Regular_triangulation<Traits, Dark_tds> Dark_triangulation;
|
typedef Regular_triangulation<Traits, Dark_tds> Dark_triangulation;
|
||||||
|
|
@ -648,7 +648,7 @@ Regular_triangulation<Traits, TDS>
|
||||||
typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
|
typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells;
|
||||||
Dark_full_cells conflict_zone;
|
Dark_full_cells conflict_zone;
|
||||||
std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
|
std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone);
|
||||||
|
|
||||||
dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
|
dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out);
|
||||||
// Make the dark simplices in the conflict zone searchable
|
// Make the dark simplices in the conflict zone searchable
|
||||||
conflict_zone.make_searchable();
|
conflict_zone.make_searchable();
|
||||||
|
|
@ -673,8 +673,8 @@ Regular_triangulation<Traits, TDS>
|
||||||
dark_incident_s.clear();
|
dark_incident_s.clear();
|
||||||
dark_out = std::back_inserter(dark_incident_s);
|
dark_out = std::back_inserter(dark_incident_s);
|
||||||
dark_side.tds().incident_full_cells(dark_v, dark_out);
|
dark_side.tds().incident_full_cells(dark_v, dark_out);
|
||||||
for(typename Dark_full_cells::iterator it = dark_incident_s.begin();
|
for(typename Dark_full_cells::iterator it = dark_incident_s.begin();
|
||||||
it != dark_incident_s.end();
|
it != dark_incident_s.end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
(*it)->data().count_ += 1;
|
(*it)->data().count_ += 1;
|
||||||
|
|
@ -748,7 +748,7 @@ Regular_triangulation<Traits, TDS>
|
||||||
int li = light_s->index(dark_s->vertex(di)->data());
|
int li = light_s->index(dark_s->vertex(di)->data());
|
||||||
Rotor light_r(light_s, li, light_i);
|
Rotor light_r(light_s, li, light_i);
|
||||||
typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
|
typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i);
|
||||||
|
|
||||||
while( simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))) )
|
while( simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))) )
|
||||||
light_r = rotate_rotor(light_r);
|
light_r = rotate_rotor(light_r);
|
||||||
|
|
||||||
|
|
@ -894,9 +894,9 @@ Regular_triangulation<Traits, TDS>
|
||||||
template< typename Traits, typename TDS >
|
template< typename Traits, typename TDS >
|
||||||
typename Regular_triangulation<Traits, TDS>::Vertex_handle
|
typename Regular_triangulation<Traits, TDS>::Vertex_handle
|
||||||
Regular_triangulation<Traits, TDS>
|
Regular_triangulation<Traits, TDS>
|
||||||
::insert_if_in_star(const Weighted_point & p,
|
::insert_if_in_star(const Weighted_point & p,
|
||||||
const Vertex_handle star_center,
|
const Vertex_handle star_center,
|
||||||
const Locate_type lt, const Face & f, const Facet & ft,
|
const Locate_type lt, const Face & f, const Facet & ft,
|
||||||
const Full_cell_handle s)
|
const Full_cell_handle s)
|
||||||
{
|
{
|
||||||
switch( lt )
|
switch( lt )
|
||||||
|
|
@ -934,7 +934,7 @@ Regular_triangulation<Traits, TDS>
|
||||||
template< typename Traits, typename TDS >
|
template< typename Traits, typename TDS >
|
||||||
typename Regular_triangulation<Traits, TDS>::Vertex_handle
|
typename Regular_triangulation<Traits, TDS>::Vertex_handle
|
||||||
Regular_triangulation<Traits, TDS>
|
Regular_triangulation<Traits, TDS>
|
||||||
::insert_in_conflicting_cell(const Weighted_point & p,
|
::insert_in_conflicting_cell(const Weighted_point & p,
|
||||||
const Full_cell_handle s,
|
const Full_cell_handle s,
|
||||||
const Vertex_handle only_if_this_vertex_is_in_the_cz)
|
const Vertex_handle only_if_this_vertex_is_in_the_cz)
|
||||||
{
|
{
|
||||||
|
|
@ -955,10 +955,10 @@ Regular_triangulation<Traits, TDS>
|
||||||
cs.reserve(64);
|
cs.reserve(64);
|
||||||
std::back_insert_iterator<Full_cell_h_vector> out(cs);
|
std::back_insert_iterator<Full_cell_h_vector> out(cs);
|
||||||
Facet ft = compute_conflict_zone(p, s, out);
|
Facet ft = compute_conflict_zone(p, s, out);
|
||||||
|
|
||||||
// Check if the CZ contains "only_if_this_vertex_is_in_the_cz"
|
// Check if the CZ contains "only_if_this_vertex_is_in_the_cz"
|
||||||
if (only_if_this_vertex_is_in_the_cz != Vertex_handle()
|
if (only_if_this_vertex_is_in_the_cz != Vertex_handle()
|
||||||
&& !does_cell_range_contain_vertex(cs.begin(), cs.end(),
|
&& !does_cell_range_contain_vertex(cs.begin(), cs.end(),
|
||||||
only_if_this_vertex_is_in_the_cz))
|
only_if_this_vertex_is_in_the_cz))
|
||||||
{
|
{
|
||||||
return Vertex_handle();
|
return Vertex_handle();
|
||||||
|
|
@ -967,7 +967,7 @@ Regular_triangulation<Traits, TDS>
|
||||||
// Otherwise, proceed with the insertion
|
// Otherwise, proceed with the insertion
|
||||||
std::vector<Vertex_handle> cz_vertices;
|
std::vector<Vertex_handle> cz_vertices;
|
||||||
cz_vertices.reserve(64);
|
cz_vertices.reserve(64);
|
||||||
process_conflict_zone(cs.begin(), cs.end(),
|
process_conflict_zone(cs.begin(), cs.end(),
|
||||||
std::back_inserter(cz_vertices));
|
std::back_inserter(cz_vertices));
|
||||||
|
|
||||||
Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft);
|
Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft);
|
||||||
|
|
@ -1048,8 +1048,8 @@ Regular_triangulation<Traits, TDS>
|
||||||
if( current_dimension() < maximal_dimension() )
|
if( current_dimension() < maximal_dimension() )
|
||||||
{
|
{
|
||||||
Conflict_pred_in_subspace c(
|
Conflict_pred_in_subspace c(
|
||||||
*this, p,
|
*this, p,
|
||||||
coaffine_orientation_predicate(),
|
coaffine_orientation_predicate(),
|
||||||
power_side_of_power_sphere_for_non_maximal_dim_predicate());
|
power_side_of_power_sphere_for_non_maximal_dim_predicate());
|
||||||
return c(s);
|
return c(s);
|
||||||
}
|
}
|
||||||
|
|
@ -1072,8 +1072,8 @@ Regular_triangulation<Traits, TDS>
|
||||||
if( current_dimension() < maximal_dimension() )
|
if( current_dimension() < maximal_dimension() )
|
||||||
{
|
{
|
||||||
Conflict_pred_in_subspace c(
|
Conflict_pred_in_subspace c(
|
||||||
*this, p,
|
*this, p,
|
||||||
coaffine_orientation_predicate(),
|
coaffine_orientation_predicate(),
|
||||||
power_side_of_power_sphere_for_non_maximal_dim_predicate());
|
power_side_of_power_sphere_for_non_maximal_dim_predicate());
|
||||||
Conflict_traversal_pred_in_subspace tp(*this, c);
|
Conflict_traversal_pred_in_subspace tp(*this, c);
|
||||||
return tds().gather_full_cells(s, tp, out);
|
return tds().gather_full_cells(s, tp, out);
|
||||||
|
|
@ -1094,7 +1094,7 @@ template< typename Traits, typename TDS >
|
||||||
bool
|
bool
|
||||||
Regular_triangulation<Traits, TDS>
|
Regular_triangulation<Traits, TDS>
|
||||||
::is_valid(bool verbose, int level) const
|
::is_valid(bool verbose, int level) const
|
||||||
{
|
{
|
||||||
if (!Base::is_valid(verbose, level))
|
if (!Base::is_valid(verbose, level))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -1105,16 +1105,16 @@ Regular_triangulation<Traits, TDS>
|
||||||
cit != finite_full_cells_end() ; ++cit )
|
cit != finite_full_cells_end() ; ++cit )
|
||||||
{
|
{
|
||||||
Full_cell_const_handle ch = cit.base();
|
Full_cell_const_handle ch = cit.base();
|
||||||
for(int i = 0; i < dim+1 ; ++i )
|
for(int i = 0; i < dim+1 ; ++i )
|
||||||
{
|
{
|
||||||
// If the i-th neighbor is not an infinite cell
|
// If the i-th neighbor is not an infinite cell
|
||||||
Vertex_handle opposite_vh =
|
Vertex_handle opposite_vh =
|
||||||
ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
|
ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch));
|
||||||
if (!is_infinite(opposite_vh))
|
if (!is_infinite(opposite_vh))
|
||||||
{
|
{
|
||||||
Power_side_of_power_sphere_d side =
|
Power_side_of_power_sphere_d side =
|
||||||
geom_traits().power_side_of_power_sphere_d_object();
|
geom_traits().power_side_of_power_sphere_d_object();
|
||||||
if (side(Point_const_iterator(ch->vertices_begin()),
|
if (side(Point_const_iterator(ch->vertices_begin()),
|
||||||
Point_const_iterator(ch->vertices_end()),
|
Point_const_iterator(ch->vertices_end()),
|
||||||
opposite_vh->point()) == ON_POSITIVE_SIDE)
|
opposite_vh->point()) == ON_POSITIVE_SIDE)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -611,7 +611,8 @@ public:
|
||||||
return incident_faces(v, dim, out, cmp, true);
|
return incident_faces(v, dim, out, cmp, true);
|
||||||
}
|
}
|
||||||
template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> >
|
template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> >
|
||||||
OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator, Comparator = Comparator(), bool = false) const;
|
OutputIterator incident_faces(Vertex_const_handle, const int, OutputIterator,
|
||||||
|
Comparator = Comparator(), bool = false) const;
|
||||||
#else
|
#else
|
||||||
template< typename OutputIterator, typename Comparator >
|
template< typename OutputIterator, typename Comparator >
|
||||||
OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator())
|
OutputIterator incident_upper_faces(Vertex_const_handle v, const int dim, OutputIterator out, Comparator cmp = Comparator())
|
||||||
|
|
@ -664,6 +665,9 @@ Triangulation_data_structure<Dim, Vb, Fcb>
|
||||||
{
|
{
|
||||||
// CGAL_expensive_precondition(is_vertex(v));
|
// CGAL_expensive_precondition(is_vertex(v));
|
||||||
CGAL_precondition(Vertex_handle() != v);
|
CGAL_precondition(Vertex_handle() != v);
|
||||||
|
CGAL_precondition(v->full_cell()->has_vertex(v));
|
||||||
|
if (!v->full_cell()->has_vertex(v)) // CJTODO TEMP
|
||||||
|
std::cout << "ERROR: incident_full_cells !v->full_cell()->has_vertex(v). Is the point cloud sparse enough?";
|
||||||
Face f(v->full_cell());
|
Face f(v->full_cell());
|
||||||
f.set_index(0, v->full_cell()->index(v));
|
f.set_index(0, v->full_cell()->index(v));
|
||||||
return incident_full_cells(f, out);
|
return incident_full_cells(f, out);
|
||||||
|
|
@ -713,7 +717,9 @@ Triangulation_data_structure<Dim, Vb, Fcb>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear_visited_marks(start);
|
clear_visited_marks(start); // CJTODO: couldn't we use what is in "out"
|
||||||
|
// to make ot faster? (would require to
|
||||||
|
// replace the output iterator by a container)
|
||||||
return ft;
|
return ft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ public:
|
||||||
#endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
|
#endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
|
||||||
{
|
{
|
||||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_type n = number_of_vertices();
|
size_type n = number_of_vertices();
|
||||||
|
|
@ -691,7 +691,7 @@ public:
|
||||||
size_type n = number_of_vertices();
|
size_type n = number_of_vertices();
|
||||||
|
|
||||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Parallel
|
// Parallel
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ namespace CGAL {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_type n = number_of_vertices();
|
size_type n = number_of_vertices();
|
||||||
|
|
@ -695,7 +695,7 @@ namespace CGAL {
|
||||||
size_type n = number_of_vertices();
|
size_type n = number_of_vertices();
|
||||||
|
|
||||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||||
WallClockTimer t;
|
Wall_clock_timer t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Parallel
|
// Parallel
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue