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
|
||||
std::cerr << std::endl << " Updating cells...";
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
size_t num_cells = c3t3_.number_of_cells_in_complex();
|
||||
# endif
|
||||
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ private:
|
|||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
std::cerr << "Computing moves...";
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -688,7 +688,7 @@ operator()(int nb_iterations, Visitor visitor)
|
|||
running_time_.start();
|
||||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
// Fill set containing moving vertices
|
||||
|
|
@ -899,7 +899,7 @@ update_mesh(const Moves_vector& moves,
|
|||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
std::cerr << "Moving vertices...";
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
#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
|
||||
std::cerr << "Refining facets..." << std::endl;
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
facets_mesher_.refine(facets_visitor_);
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
|
|
@ -481,7 +481,7 @@ initialize()
|
|||
{
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
std::cerr << "Initializing... ";
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
//=====================================
|
||||
// Bounding box estimation
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ protected:
|
|||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
protected:
|
||||
WallClockTimer m_timer;
|
||||
Wall_clock_timer m_timer;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
// TBB timers
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
#include <tbb/tick_count.h>
|
||||
struct WallClockTimer
|
||||
struct Wall_clock_timer
|
||||
{
|
||||
tbb::tick_count t;
|
||||
WallClockTimer()
|
||||
Wall_clock_timer()
|
||||
{
|
||||
t = tbb::tick_count::now();
|
||||
}
|
||||
|
|
@ -48,10 +48,10 @@
|
|||
#else
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
struct WallClockTimer
|
||||
struct Wall_clock_timer
|
||||
{
|
||||
CGAL::Real_timer t;
|
||||
WallClockTimer()
|
||||
Wall_clock_timer()
|
||||
{
|
||||
t.start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -632,7 +632,7 @@ scan_triangulation_impl()
|
|||
typedef typename Tr::Finite_cells_iterator Finite_cell_iterator;
|
||||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -930,7 +930,7 @@ scan_triangulation_impl()
|
|||
typedef typename Tr::Finite_facets_iterator Finite_facet_iterator;
|
||||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_VERY_VERBOSE
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ operator()(Visitor visitor)
|
|||
running_time_.start();
|
||||
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
// Build priority queue (we use one queue for all steps)
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ public: // methods
|
|||
operator()(Visitor visitor = Visitor())
|
||||
{
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
Mesh_optimization_return_code ret =
|
||||
|
|
@ -964,7 +964,7 @@ pump_vertices(double sliver_criterion_limit,
|
|||
Visitor& visitor)
|
||||
{
|
||||
#ifdef CGAL_MESH_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
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_ >
|
||||
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(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,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> {
|
||||
typedef typename Get_functor<AK, T>::type AP;
|
||||
typedef typename Get_functor<EK, T>::type EP;
|
||||
typedef Filtered_predicate2<EP,AP,C2E,C2A> type;
|
||||
typedef typename Get_functor<AK, T>::type AP;
|
||||
typedef typename Get_functor<EK, T>::type EP;
|
||||
typedef Filtered_predicate2<EP,AP,C2E,C2A> type;
|
||||
};
|
||||
// TODO:
|
||||
// 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, 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_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, Construct_flat_orientation_tag>::type Construct_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, 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, Translated_point_tag>::type Translated_point_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_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); }
|
||||
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_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); }
|
||||
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); }
|
||||
|
|
@ -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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ template <class R_> struct Construct_sphere : Store_kernel<R_> {
|
|||
}
|
||||
template <class Iter>
|
||||
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_, 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_> {
|
||||
CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere)
|
||||
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_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(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(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
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -216,6 +216,8 @@ namespace CGAL {
|
|||
CGAL_DECL_COMPUTE(Hyperplane_translation);
|
||||
CGAL_DECL_COMPUTE(Value_at);
|
||||
CGAL_DECL_COMPUTE(Point_weight);
|
||||
CGAL_DECL_COMPUTE(Power_distance);
|
||||
CGAL_DECL_COMPUTE(Power_distance_to_point);
|
||||
#undef CGAL_DECL_COMPUTE
|
||||
|
||||
#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_circumcenter,Point);
|
||||
CGAL_DECL_CONSTRUCT(Point_drop_weight,Point);
|
||||
CGAL_DECL_CONSTRUCT(Power_center,Weighted_point);
|
||||
#undef CGAL_DECL_CONSTRUCT
|
||||
#if 0
|
||||
#define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ int main()
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#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<CGAL::Interval_nt_advanced,CGAL::Dimension_tag<2> > KA;
|
||||
|
|
@ -84,6 +85,7 @@ void test2(){
|
|||
typedef typename K1::Ray_d R;
|
||||
typedef typename K1::Iso_box_d IB;
|
||||
typedef typename K1::Flat_orientation_d FO;
|
||||
typedef typename K1::Weighted_point_d WP;
|
||||
|
||||
//typedef K1::Construct_point 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_max_vertex_d CMV;
|
||||
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(D);
|
||||
|
|
@ -196,6 +205,12 @@ void test2(){
|
|||
CmV cmv Kinit(construct_min_vertex_d_object);
|
||||
CMV cMv Kinit(construct_max_vertex_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(pol);
|
||||
|
|
@ -203,11 +218,12 @@ void test2(){
|
|||
CGAL_USE(cd);
|
||||
CGAL_USE(cli);
|
||||
CGAL_USE(cr);
|
||||
using std::abs;
|
||||
P a=cp(3,4);
|
||||
assert(pd(a)==2);
|
||||
assert(pv(a)[1]==4);
|
||||
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(a,b,0));
|
||||
int rr[]={3,5,2};
|
||||
|
|
@ -221,8 +237,8 @@ void test2(){
|
|||
assert(cl(a,c)==CGAL::SMALLER);
|
||||
assert(ll(b,c));
|
||||
assert(cl(c,b)==CGAL::LARGER);
|
||||
assert(fabs(m(a,c)[0]-3)<.0001);
|
||||
assert(fabs(m(a,c)[1]-4.5)<.0001);
|
||||
assert(abs(m(a,c)[0]-3)<.0001);
|
||||
assert(abs(m(a,c)[1]-4.5)<.0001);
|
||||
P d=cp(r,r+3,CGAL::Homogeneous_tag());
|
||||
S s=cs(c,d);
|
||||
std::cout << cc(a,1) << std::endl;
|
||||
|
|
@ -277,9 +293,9 @@ void test2(){
|
|||
assert(v.size()==1);
|
||||
assert(lr(tab3+0,tab3+2)==1);
|
||||
H h=ch(tab2+1,tab2+3,tab2[0]);
|
||||
assert(fabs(va(h,x2)-1)<.0001);
|
||||
assert(fabs(va(h,x3)-1)<.0001);
|
||||
assert(fabs(va(h,x1)+1)<.0001);
|
||||
assert(abs(va(h,x2)-1)<.0001);
|
||||
assert(abs(va(h,x3)-1)<.0001);
|
||||
assert(abs(va(h,x1)+1)<.0001);
|
||||
H h2=ch(tab2+1,tab2+3,x1,CGAL::ON_POSITIVE_SIDE);
|
||||
assert(hops(h2,x1));
|
||||
assert(os(h2,x1)==CGAL::ON_POSITIVE_SIDE);
|
||||
|
|
@ -340,20 +356,35 @@ void test2(){
|
|||
Sp sp = csp(tabz+0,tabz+3);
|
||||
P cent0=cos(sp);
|
||||
P cent1=cos(tabz+0,tabz+3);
|
||||
assert(fabs(cent0[0]-2)<.0001);
|
||||
assert(fabs(cent0[1]+3)<.0001);
|
||||
assert(fabs(cent1[0]-2)<.0001);
|
||||
assert(fabs(cent1[1]+3)<.0001);
|
||||
assert(fabs(sp.squared_radius()-25)<.0001);
|
||||
assert(abs(cent0[0]-2)<.0001);
|
||||
assert(abs(cent0[1]+3)<.0001);
|
||||
assert(abs(cent1[0]-2)<.0001);
|
||||
assert(abs(cent1[1]+3)<.0001);
|
||||
assert(abs(sp.squared_radius()-25)<.0001);
|
||||
#if 1
|
||||
// Fails for an exact kernel
|
||||
P psp0=ps(sp,0);
|
||||
P psp1=ps(sp,1);
|
||||
P psp2=ps(sp,2);
|
||||
assert(!ed(psp0,psp1));
|
||||
assert(!ed(psp0,psp2));
|
||||
assert(!ed(psp2,psp1));
|
||||
assert(fabs(sd(cent0,psp0)-25)<.0001);
|
||||
assert(fabs(sd(cent0,psp1)-25)<.0001);
|
||||
assert(fabs(sd(cent0,psp2)-25)<.0001);
|
||||
assert(abs(sd(cent0,psp0)-25)<.0001);
|
||||
assert(abs(sd(cent0,psp1)-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 br=cp(4,-1);
|
||||
|
|
@ -459,6 +490,7 @@ void test3(){
|
|||
PD pd Kinit(point_dimension_d_object);
|
||||
AI ai Kinit(affinely_independent_d_object);
|
||||
SBDS sbds Kinit(side_of_bounded_sphere_d_object);
|
||||
using std::abs;
|
||||
P a; // Triangulation needs this :-(
|
||||
a=cp(2,3,4);
|
||||
assert(pd(a)==3);
|
||||
|
|
@ -482,7 +514,7 @@ void test3(){
|
|||
std::cout << *i << ' ';
|
||||
std::cout << '\n';
|
||||
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};
|
||||
std::cout << po (&tab[0],tab+4) << ' ';
|
||||
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{
|
||||
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_)
|
||||
:Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){}
|
||||
|
||||
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
|
||||
{ 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{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -881,8 +881,8 @@ Delaunay_triangulation<DCTraits, TDS>
|
|||
int dim = current_dimension();
|
||||
if (dim == maximal_dimension())
|
||||
{
|
||||
for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ;
|
||||
cit != finite_full_cells_end() ; ++cit )
|
||||
for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ;
|
||||
cit != this->finite_full_cells_end() ; ++cit )
|
||||
{
|
||||
Full_cell_const_handle ch = cit.base();
|
||||
for(int i = 0; i < dim+1 ; ++i )
|
||||
|
|
|
|||
|
|
@ -173,6 +173,32 @@ operator>>(std::istream &is, typename Wrap::Weighted_point_d<K> & wp)
|
|||
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 >
|
||||
std::ostream &
|
||||
export_triangulation_to_off(std::ostream & os,
|
||||
|
|
|
|||
|
|
@ -611,7 +611,8 @@ public:
|
|||
return incident_faces(v, dim, out, cmp, true);
|
||||
}
|
||||
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
|
||||
template< typename OutputIterator, typename 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_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());
|
||||
f.set_index(0, v->full_cell()->index(v));
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ public:
|
|||
#endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
|
||||
{
|
||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
size_type n = number_of_vertices();
|
||||
|
|
@ -691,7 +691,7 @@ public:
|
|||
size_type n = number_of_vertices();
|
||||
|
||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
// Parallel
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ namespace CGAL {
|
|||
#endif
|
||||
|
||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
size_type n = number_of_vertices();
|
||||
|
|
@ -695,7 +695,7 @@ namespace CGAL {
|
|||
size_type n = number_of_vertices();
|
||||
|
||||
#ifdef CGAL_TRIANGULATION_3_PROFILING
|
||||
WallClockTimer t;
|
||||
Wall_clock_timer t;
|
||||
#endif
|
||||
|
||||
// Parallel
|
||||
|
|
|
|||
Loading…
Reference in New Issue