12 #ifndef TANGENTIAL_COMPLEX_H_    13 #define TANGENTIAL_COMPLEX_H_    15 #include <gudhi/Tangential_complex/config.h>    16 #include <gudhi/Tangential_complex/Simplicial_complex.h>    17 #include <gudhi/Tangential_complex/utilities.h>    18 #include <gudhi/Kd_tree_search.h>    19 #include <gudhi/console_color.h>    20 #include <gudhi/Clock.h>    21 #include <gudhi/Simplex_tree.h>    22 #include <gudhi/Debug_utils.h>    24 #include <CGAL/Default.h>    25 #include <CGAL/Dimension.h>    26 #include <CGAL/function_objects.h>      27 #include <CGAL/Epick_d.h>    28 #include <CGAL/Regular_triangulation_traits_adapter.h>    29 #include <CGAL/Regular_triangulation.h>    30 #include <CGAL/Delaunay_triangulation.h>    31 #include <CGAL/Combination_enumerator.h>    32 #include <CGAL/point_generators_d.h>    33 #include <CGAL/version.h>      36 #include <Eigen/Eigen>    37 #include <Eigen/src/Core/util/Macros.h>      39 #include <boost/optional.hpp>    40 #include <boost/iterator/transform_iterator.hpp>    41 #include <boost/range/adaptor/transformed.hpp>    42 #include <boost/range/counting_range.hpp>    43 #include <boost/math/special_functions/factorials.hpp>    44 #include <boost/container/flat_set.hpp>    61 #include <tbb/parallel_for.h>    62 #include <tbb/combinable.h>    69 #if CGAL_VERSION_NR < 1041101000    70 # error Tangential_complex is only available for CGAL >= 4.11    73 #if !EIGEN_VERSION_AT_LEAST(3,1,0)    74 # error Tangential_complex is only available for Eigen3 >= 3.1.0 installed with CGAL    81 namespace tangential_complex {
    83 using namespace internal;
    87   Vertex_data(std::size_t data = (std::numeric_limits<std::size_t>::max)()) : m_data(data) {}
    89   operator std::size_t() { 
return m_data; }
    91   operator std::size_t()
 const { 
return m_data; }
   122 template <
typename Kernel_,       
   123           typename DimensionTag,  
   124           typename Concurrency_tag = CGAL::Parallel_tag, 
typename Triangulation_ = CGAL::Default>
   127   typedef typename K::FT FT;
   128   typedef typename K::Point_d Point;
   129   typedef typename K::Weighted_point_d Weighted_point;
   130   typedef typename K::Vector_d Vector;
   132   typedef typename CGAL::Default::Get<
   134       CGAL::Regular_triangulation<
   135           CGAL::Epick_d<DimensionTag>,
   136           CGAL::Triangulation_data_structure<
   137               typename CGAL::Epick_d<DimensionTag>::Dimension,
   138               CGAL::Triangulation_vertex<CGAL::Regular_triangulation_traits_adapter<CGAL::Epick_d<DimensionTag> >,
   140               CGAL::Triangulation_full_cell<
   141                   CGAL::Regular_triangulation_traits_adapter<CGAL::Epick_d<DimensionTag> > > > > >::type Triangulation;
   142   typedef typename Triangulation::Geom_traits Tr_traits;
   143   typedef typename Triangulation::Weighted_point Tr_point;
   144   typedef typename Tr_traits::Base::Point_d Tr_bare_point;
   145   typedef typename Triangulation::Vertex_handle Tr_vertex_handle;
   146   typedef typename Triangulation::Full_cell_handle Tr_full_cell_handle;
   147   typedef typename Tr_traits::Vector_d Tr_vector;
   149 #if defined(GUDHI_USE_TBB)   150   typedef std::mutex Mutex_for_perturb;
   151   typedef Vector Translation_for_perturb;
   152   typedef std::vector<Atomic_wrapper<FT> > Weights;
   154   typedef Vector Translation_for_perturb;
   155   typedef std::vector<FT> Weights;
   157   typedef std::vector<Translation_for_perturb> Translations_for_perturb;
   163     Tr_and_VH() : m_tr(NULL) {}
   165     Tr_and_VH(
int dim) : m_tr(
new Triangulation(dim)) {}
   167     ~Tr_and_VH() { destroy_triangulation(); }
   169     Triangulation &construct_triangulation(
int dim) {
   171       m_tr = 
new Triangulation(dim);
   175     void destroy_triangulation() {
   180     Triangulation &tr() { 
return *m_tr; }
   182     Triangulation 
const &tr()
 const { 
return *m_tr; }
   184     Tr_vertex_handle 
const ¢er_vertex()
 const { 
return m_center_vertex; }
   186     Tr_vertex_handle ¢er_vertex() { 
return m_center_vertex; }
   190     Tr_vertex_handle m_center_vertex;
   194   typedef Basis<K> Tangent_space_basis;
   195   typedef Basis<K> Orthogonal_space_basis;
   196   typedef std::vector<Tangent_space_basis> TS_container;
   197   typedef std::vector<Orthogonal_space_basis> OS_container;
   199   typedef std::vector<Point> Points;
   201   typedef boost::container::flat_set<std::size_t> Simplex;
   202   typedef std::set<Simplex> Simplex_set;
   209   typedef std::vector<Tr_and_VH> Tr_container;
   210   typedef std::vector<Vector> Vectors;
   214   typedef boost::container::flat_set<std::size_t> Incident_simplex;
   215   typedef std::vector<Incident_simplex> Star;
   216   typedef std::vector<Star> Stars_container;
   220   static const Tr_point &vertex_handle_to_point(Tr_vertex_handle vh) { 
return vh->point(); }
   222   template <
typename P, 
typename VH>
   223   static const P &vertex_handle_to_point(VH vh) {
   228   typedef internal::Simplicial_complex Simplicial_complex;
   239   template <
typename Po
int_range>
   241 #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
   242                      InputIterator first_for_tse, InputIterator last_for_tse,
   246         m_intrinsic_dim(intrinsic_dimension),
   247         m_ambient_dim(points.empty() ? 0 : k.point_dimension_d_object()(*points.begin())),
   248         m_points(points.begin(), points.end()),
   249         m_weights(m_points.size(), FT(0))
   250 #if defined(GUDHI_USE_TBB) && defined(GUDHI_TC_PERTURB_POSITION)
   252         m_p_perturb_mutexes(NULL)
   255         m_points_ds(m_points),
   256         m_last_max_perturb(0.),
   257         m_are_tangent_spaces_computed(m_points.size(), false),
   258         m_tangent_spaces(m_points.size(), Tangent_space_basis())
   259 #ifdef GUDHI_TC_EXPORT_NORMALS
   261         m_orth_spaces(m_points.size(), Orthogonal_space_basis())
   263 #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
   265         m_points_for_tse(first_for_tse, last_for_tse),
   266         m_points_ds_for_tse(m_points_for_tse)
   273 #if defined(GUDHI_USE_TBB) && defined(GUDHI_TC_PERTURB_POSITION)   274     delete[] m_p_perturb_mutexes;
   284   Points 
const &points()
 const { 
return m_points; }
   291   Point 
get_point(std::size_t vertex)
 const { 
return m_points[vertex]; }
   304   void set_weights(
const Weights &weights) { m_weights = weights; }
   306   void set_tangent_planes(
const TS_container &tangent_spaces
   307 #ifdef GUDHI_TC_EXPORT_NORMALS
   309                           const OS_container &orthogonal_spaces
   312 #ifdef GUDHI_TC_EXPORT_NORMALS   313     GUDHI_CHECK(m_points.size() == tangent_spaces.size() && m_points.size() == orthogonal_spaces.size(),
   314                 std::logic_error(
"Wrong sizes"));
   316     GUDHI_CHECK(m_points.size() == tangent_spaces.size(), std::logic_error(
"Wrong sizes"));
   318     m_tangent_spaces = tangent_spaces;
   319 #ifdef GUDHI_TC_EXPORT_NORMALS   320     m_orth_spaces = orthogonal_spaces;
   322     for (std::size_t i = 0; i < m_points.size(); ++i) m_are_tangent_spaces_computed[i] = 
true;
   331 #ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS   332     std::cerr << red << 
"WARNING: GUDHI_TC_PERFORM_EXTRA_CHECKS is defined. "   333               << 
"Computation might be slower than usual.\n"   337 #if defined(GUDHI_TC_PROFILING) && defined(GUDHI_USE_TBB)   344     m_triangulations.resize(m_points.size());
   345     m_stars.resize(m_points.size());
   346     m_squared_star_spheres_radii_incl_margin.resize(m_points.size(), FT(-1));
   347 #ifdef GUDHI_TC_PERTURB_POSITION   348     if (m_points.empty())
   349       m_translations.clear();
   351       m_translations.resize(m_points.size(), m_k.construct_vector_d_object()(m_ambient_dim));
   352 #if defined(GUDHI_USE_TBB)   353     delete[] m_p_perturb_mutexes;
   354     m_p_perturb_mutexes = 
new Mutex_for_perturb[m_points.size()];
   360     if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
   361       tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()), Compute_tangent_triangulation(*
this));
   363 #endif  // GUDHI_USE_TBB   365       for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i);
   368 #endif  // GUDHI_USE_TBB   370 #if defined(GUDHI_TC_PROFILING) && defined(GUDHI_USE_TBB)   372     std::cerr << 
"Tangential complex computed in " << t.num_seconds() << 
" seconds.\n";
   379     bool success = 
false;
   381     unsigned int num_steps = 0;
   383     std::size_t initial_num_inconsistent_stars = 0;
   385     std::size_t best_num_inconsistent_stars = 0;
   387     std::size_t final_num_inconsistent_stars = 0;
   398     if (time_limit == 0.) 
return info;
   402 #ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES   403     std::tuple<std::size_t, std::size_t, std::size_t> stats_before = number_of_inconsistent_simplices(
false);
   405     if (std::get<1>(stats_before) == 0) {
   407       std::cerr << 
"Nothing to fix.\n";
   412 #endif  // GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES   414     m_last_max_perturb = max_perturb;
   420 #ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES   421       std::cerr << 
"\nBefore fix step:\n"   422                 << 
"  * Total number of simplices in stars (incl. duplicates): " << std::get<0>(stats_before) << 
"\n"   423                 << 
"  * Num inconsistent simplices in stars (incl. duplicates): " << red << std::get<1>(stats_before)
   424                 << white << 
" (" << 100. * std::get<1>(stats_before) / std::get<0>(stats_before) << 
"%)\n"   425                 << 
"  * Number of stars containing inconsistent simplices: " << red << std::get<2>(stats_before)
   426                 << white << 
" (" << 100. * std::get<2>(stats_before) / m_points.size() << 
"%)\n";
   429 #if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)   430       std::cerr << yellow << 
"\nAttempt to fix inconsistencies using perturbations - step #" << info.
num_steps + 1
   434       std::size_t num_inconsistent_stars = 0;
   435       std::vector<std::size_t> updated_points;
   437 #ifdef GUDHI_TC_PROFILING   438       Gudhi::Clock t_fix_step;
   442 #if defined(GUDHI_USE_TBB)   443       if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
   444         tbb::combinable<std::size_t> num_inconsistencies;
   445         tbb::combinable<std::vector<std::size_t> > tls_updated_points;
   446         tbb::parallel_for(tbb::blocked_range<size_t>(0, m_triangulations.size()),
   447                           Try_to_solve_inconsistencies_in_a_local_triangulation(*
this, max_perturb, num_inconsistencies,
   448                                                                                 tls_updated_points));
   449         num_inconsistent_stars = num_inconsistencies.combine(std::plus<std::size_t>());
   451             tls_updated_points.combine([](std::vector<std::size_t> 
const &x, std::vector<std::size_t> 
const &y) {
   452               std::vector<std::size_t> res;
   453               res.reserve(x.size() + y.size());
   454               res.insert(res.end(), x.begin(), x.end());
   455               res.insert(res.end(), y.begin(), y.end());
   459 #endif  // GUDHI_USE_TBB   461         for (std::size_t i = 0; i < m_triangulations.size(); ++i) {
   462           num_inconsistent_stars +=
   463               try_to_solve_inconsistencies_in_a_local_triangulation(i, max_perturb, std::back_inserter(updated_points));
   465 #if defined(GUDHI_USE_TBB)   467 #endif  // GUDHI_USE_TBB   469 #ifdef GUDHI_TC_PROFILING   473 #if defined(GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES) || defined(DEBUG_TRACES)   474       std::cerr << 
"\nEncountered during fix:\n"   475                 << 
"  * Num stars containing inconsistent simplices: " << red << num_inconsistent_stars << white << 
" ("   476                 << 100. * num_inconsistent_stars / m_points.size() << 
"%)\n";
   479 #ifdef GUDHI_TC_PROFILING   480       std::cerr << yellow << 
"done in " << t_fix_step.num_seconds() << 
" seconds.\n" << white;
   481 #elif defined(DEBUG_TRACES)   482       std::cerr << yellow << 
"done.\n" << white;
   485       if (num_inconsistent_stars > 0) refresh_tangential_complex(updated_points);
   487 #ifdef GUDHI_TC_PERFORM_EXTRA_CHECKS   489       std::size_t num_inc_1 = std::get<1>(number_of_inconsistent_simplices(
false));
   490       refresh_tangential_complex();
   491       std::size_t num_inc_2 = std::get<1>(number_of_inconsistent_simplices(
false));
   492       if (num_inc_1 != num_inc_2)
   493         std::cerr << red << 
"REFRESHMENT CHECK: FAILED. (" << num_inc_1 << 
" vs " << num_inc_2 << 
")\n" << white;
   495         std::cerr << green << 
"REFRESHMENT CHECK: PASSED.\n" << white;
   498 #ifdef GUDHI_TC_SHOW_DETAILED_STATS_FOR_INCONSISTENCIES   499       std::tuple<std::size_t, std::size_t, std::size_t> stats_after = number_of_inconsistent_simplices(
false);
   501       std::cerr << 
"\nAfter fix:\n"   502                 << 
"  * Total number of simplices in stars (incl. duplicates): " << std::get<0>(stats_after) << 
"\n"   503                 << 
"  * Num inconsistent simplices in stars (incl. duplicates): " << red << std::get<1>(stats_after)
   504                 << white << 
" (" << 100. * std::get<1>(stats_after) / std::get<0>(stats_after) << 
"%)\n"   505                 << 
"  * Number of stars containing inconsistent simplices: " << red << std::get<2>(stats_after) << white
   506                 << 
" (" << 100. * std::get<2>(stats_after) / m_points.size() << 
"%)\n";
   508       stats_before = stats_after;
   518       done = (num_inconsistent_stars == 0);
   521         if (time_limit > 0. && t.num_seconds() > time_limit) {
   523           std::cerr << red << 
"Time limit reached.\n" << white;
   532     std::cerr << green << 
"Fixed!\n" << white;
   541     std::size_t num_simplices = 0;
   543     std::size_t num_inconsistent_simplices = 0;
   545     std::size_t num_inconsistent_stars = 0;
   561     for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
   562       bool is_star_inconsistent = 
false;
   565       Star::const_iterator it_inc_simplex = m_stars[idx].begin();
   566       Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
   567       for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
   569         if (is_infinite(*it_inc_simplex)) 
continue;
   571         Simplex c = *it_inc_simplex;
   574         if (!is_simplex_consistent(c)) {
   576           is_star_inconsistent = 
true;
   585       std::cerr << 
"\n==========================================================\n"   586                 << 
"Inconsistencies:\n"   587                 << 
"  * Total number of simplices in stars (incl. duplicates): " << stats.
num_simplices << 
"\n"   588                 << 
"  * Number of inconsistent simplices in stars (incl. duplicates): "   593                 << 
"==========================================================\n";
   609   template <
typename Simplex_tree_>
   611                      bool export_inconsistent_simplices = 
true   614                      bool export_infinite_simplices = 
false, Simplex_set *p_inconsistent_simplices = NULL
   617 #if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)   618     std::cerr << yellow << 
"\nExporting the TC as a Simplex_tree... " << white;
   620 #ifdef GUDHI_TC_PROFILING   627     for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
   629       Star::const_iterator it_inc_simplex = m_stars[idx].begin();
   630       Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
   631       for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
   632         Simplex c = *it_inc_simplex;
   635         if (!export_infinite_simplices && is_infinite(c)) 
continue;
   637         if (static_cast<int>(c.size()) > max_dim) max_dim = 
static_cast<int>(c.size());
   641         if (!export_inconsistent_simplices && !is_simplex_consistent(c)) 
continue;
   644         bool inserted = tree.insert_simplex_and_subfaces(c).second;
   647         if (p_inconsistent_simplices && inserted && !is_simplex_consistent(c)) {
   648           p_inconsistent_simplices->insert(c);
   653 #ifdef GUDHI_TC_PROFILING   655     std::cerr << yellow << 
"done in " << t.num_seconds() << 
" seconds.\n" << white;
   656 #elif defined(DEBUG_TRACES)   657     std::cerr << yellow << 
"done.\n" << white;
   673   int create_complex(Simplicial_complex &complex, 
bool export_inconsistent_simplices = 
true,
   674                      bool export_infinite_simplices = 
false, 
int check_lower_and_higher_dim_simplices = 2,
   675                      Simplex_set *p_inconsistent_simplices = NULL)
 const {
   676 #if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)   677     std::cerr << yellow << 
"\nExporting the TC as a Simplicial_complex... " << white;
   679 #ifdef GUDHI_TC_PROFILING   687     for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
   689       Star::const_iterator it_inc_simplex = m_stars[idx].begin();
   690       Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
   691       for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
   692         Simplex c = *it_inc_simplex;
   695         if (!export_infinite_simplices && is_infinite(c)) 
continue;
   697         if (static_cast<int>(c.size()) > max_dim) max_dim = 
static_cast<int>(c.size());
   701         if (!export_inconsistent_simplices && !is_simplex_consistent(c)) 
continue;
   704         if (check_lower_and_higher_dim_simplices == 2 && max_dim != -1 && static_cast<int>(c.size()) != max_dim) {
   707                     << 
"Info: check_lower_and_higher_dim_simplices ACTIVATED. "   708                        "Export might be take some time...\n"   710           check_lower_and_higher_dim_simplices = 1;
   714         bool added = complex.add_simplex(c, check_lower_and_higher_dim_simplices == 1);
   717         if (p_inconsistent_simplices && added && !is_simplex_consistent(c)) {
   718           p_inconsistent_simplices->insert(c);
   723 #ifdef GUDHI_TC_PROFILING   725     std::cerr << yellow << 
"done in " << t.num_seconds() << 
" seconds.\n" << white;
   726 #elif defined(DEBUG_TRACES)   727     std::cerr << yellow << 
"done.\n" << white;
   733   template <
typename ProjectionFunctor = CGAL::Identity<Po
int> >
   734   std::ostream &export_to_off(
const Simplicial_complex &complex, std::ostream &os,
   735                               Simplex_set 
const *p_simpl_to_color_in_red = NULL,
   736                               Simplex_set 
const *p_simpl_to_color_in_green = NULL,
   737                               Simplex_set 
const *p_simpl_to_color_in_blue = NULL,
   738                               ProjectionFunctor 
const &point_projection = ProjectionFunctor())
 const {
   739     return export_to_off(os, 
false, p_simpl_to_color_in_red, p_simpl_to_color_in_green, p_simpl_to_color_in_blue,
   740                          &complex, point_projection);
   743   template <
typename ProjectionFunctor = CGAL::Identity<Po
int> >
   744   std::ostream &export_to_off(std::ostream &os, 
bool color_inconsistencies = 
false,
   745                               Simplex_set 
const *p_simpl_to_color_in_red = NULL,
   746                               Simplex_set 
const *p_simpl_to_color_in_green = NULL,
   747                               Simplex_set 
const *p_simpl_to_color_in_blue = NULL,
   748                               const Simplicial_complex *p_complex = NULL,
   749                               ProjectionFunctor 
const &point_projection = ProjectionFunctor())
 const {
   750     if (m_points.empty()) 
return os;
   752     if (m_ambient_dim < 2) {
   753       std::cerr << 
"Error: export_to_off => ambient dimension should be >= 2.\n";
   754       os << 
"Error: export_to_off => ambient dimension should be >= 2.\n";
   757     if (m_ambient_dim > 3) {
   758       std::cerr << 
"Warning: export_to_off => ambient dimension should be "   759                    "<= 3. Only the first 3 coordinates will be exported.\n";
   762     if (m_intrinsic_dim < 1 || m_intrinsic_dim > 3) {
   763       std::cerr << 
"Error: export_to_off => intrinsic dimension should be "   764                    "between 1 and 3.\n";
   765       os << 
"Error: export_to_off => intrinsic dimension should be "   766             "between 1 and 3.\n";
   770     std::stringstream output;
   771     std::size_t num_simplices, num_vertices;
   772     export_vertices_to_off(output, num_vertices, 
false, point_projection);
   774       export_simplices_to_off(*p_complex, output, num_simplices, p_simpl_to_color_in_red, p_simpl_to_color_in_green,
   775                               p_simpl_to_color_in_blue);
   777       export_simplices_to_off(output, num_simplices, color_inconsistencies, p_simpl_to_color_in_red,
   778                               p_simpl_to_color_in_green, p_simpl_to_color_in_blue);
   781 #ifdef GUDHI_TC_EXPORT_NORMALS   786        << num_vertices << 
" " << num_simplices << 
" "   794   void refresh_tangential_complex() {
   795 #if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)   796     std::cerr << yellow << 
"\nRefreshing TC... " << white;
   799 #ifdef GUDHI_TC_PROFILING   804     if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
   805       tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()), Compute_tangent_triangulation(*
this));
   807 #endif  // GUDHI_USE_TBB   809       for (std::size_t i = 0; i < m_points.size(); ++i) compute_tangent_triangulation(i);
   812 #endif  // GUDHI_USE_TBB   814 #ifdef GUDHI_TC_PROFILING   816     std::cerr << yellow << 
"done in " << t.num_seconds() << 
" seconds.\n" << white;
   817 #elif defined(DEBUG_TRACES)   818     std::cerr << yellow << 
"done.\n" << white;
   823   template <
typename Po
int_indices_range>
   824   void refresh_tangential_complex(Point_indices_range 
const &perturbed_points_indices) {
   825 #if defined(DEBUG_TRACES) || defined(GUDHI_TC_PROFILING)   826     std::cerr << yellow << 
"\nRefreshing TC... " << white;
   829 #ifdef GUDHI_TC_PROFILING   834     Points_ds updated_pts_ds(m_points, perturbed_points_indices);
   838     if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value) {
   839       tbb::parallel_for(tbb::blocked_range<size_t>(0, m_points.size()),
   840                         Refresh_tangent_triangulation(*
this, updated_pts_ds));
   842 #endif  // GUDHI_USE_TBB   844       for (std::size_t i = 0; i < m_points.size(); ++i) refresh_tangent_triangulation(i, updated_pts_ds);
   847 #endif  // GUDHI_USE_TBB   849 #ifdef GUDHI_TC_PROFILING   851     std::cerr << yellow << 
"done in " << t.num_seconds() << 
" seconds.\n" << white;
   852 #elif defined(DEBUG_TRACES)   853     std::cerr << yellow << 
"done.\n" << white;
   857   void export_inconsistent_stars_to_OFF_files(std::string 
const &filename_base)
 const {
   859     for (std::size_t idx = 0; idx < m_points.size(); ++idx) {
   861       Simplicial_complex sc;
   863       bool is_inconsistent = 
false;
   864       Star::const_iterator it_inc_simplex = m_stars[idx].begin();
   865       Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
   866       for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
   868         if (is_infinite(*it_inc_simplex)) 
continue;
   870         Simplex c = *it_inc_simplex;
   876         if (!is_inconsistent && !is_simplex_consistent(c)) is_inconsistent = 
true;
   879       if (is_inconsistent) {
   881         std::stringstream output_filename;
   882         output_filename << filename_base << 
"_" << idx << 
".off";
   883         std::ofstream off_stream(output_filename.str().c_str());
   884         export_to_off(sc, off_stream);
   889   class Compare_distance_to_ref_point {
   891     Compare_distance_to_ref_point(Point 
const &ref, K 
const &k) : m_ref(ref), m_k(k) {}
   893     bool operator()(Point 
const &p1, Point 
const &p2) {
   894       typename K::Squared_distance_d sqdist = m_k.squared_distance_d_object();
   895       return sqdist(p1, m_ref) < sqdist(p2, m_ref);
   905   class Compute_tangent_triangulation {
   913     Compute_tangent_triangulation(
const Compute_tangent_triangulation &ctt) : m_tc(ctt.m_tc) {}
   916     void operator()(
const tbb::blocked_range<size_t> &r)
 const {
   917       for (
size_t i = r.begin(); i != r.end(); ++i) m_tc.compute_tangent_triangulation(i);
   922   class Refresh_tangent_triangulation {
   924     Points_ds 
const &m_updated_pts_ds;
   928     Refresh_tangent_triangulation(
Tangential_complex &tc, Points_ds 
const &updated_pts_ds)
   929         : m_tc(tc), m_updated_pts_ds(updated_pts_ds) {}
   932     Refresh_tangent_triangulation(
const Refresh_tangent_triangulation &ctt)
   933         : m_tc(ctt.m_tc), m_updated_pts_ds(ctt.m_updated_pts_ds) {}
   936     void operator()(
const tbb::blocked_range<size_t> &r)
 const {
   937       for (
size_t i = r.begin(); i != r.end(); ++i) m_tc.refresh_tangent_triangulation(i, m_updated_pts_ds);
   940 #endif  // GUDHI_USE_TBB   942   bool is_infinite(Simplex 
const &s)
 const { 
return *s.rbegin() == (std::numeric_limits<std::size_t>::max)(); }
   947   Tr_vertex_handle compute_star(std::size_t i, 
const Point ¢er_pt, 
const Tangent_space_basis &tsb,
   948                                 Triangulation &triangulation, 
bool verbose = 
false) {
   949     int tangent_space_dim = tsb.dimension();
   950     const Tr_traits &local_tr_traits = triangulation.geom_traits();
   953     typename K::Squared_distance_d k_sqdist = m_k.squared_distance_d_object();
   956     typename Tr_traits::Compute_weight_d point_weight = local_tr_traits.compute_weight_d_object();
   957     typename Tr_traits::Power_center_d power_center = local_tr_traits.power_center_d_object();
   966     if (i == tsb.origin()) {
   968       proj_wp = local_tr_traits.construct_weighted_point_d_object()(
   969           local_tr_traits.construct_point_d_object()(tangent_space_dim, CGAL::ORIGIN), m_weights[i]);
   971       const Weighted_point &wp = compute_perturbed_weighted_point(i);
   972       proj_wp = project_point_and_compute_weight(wp, tsb, local_tr_traits);
   975     Tr_vertex_handle center_vertex = triangulation.insert(proj_wp);
   976     center_vertex->data() = i;
   977     if (verbose) std::cerr << 
"* Inserted point #" << i << 
"\n";
   979 #ifdef GUDHI_TC_VERY_VERBOSE   980     std::size_t num_attempts_to_insert_points = 1;
   981     std::size_t num_inserted_points = 1;
   985     INS_range ins_range = m_points_ds.incremental_nearest_neighbors(center_pt);
   993     boost::optional<FT> squared_star_sphere_radius_plus_margin = m_max_squared_edge_length;
   996     for (
auto nn_it = ins_range.begin(); nn_it != ins_range.end(); ++nn_it) {
   997       std::size_t neighbor_point_idx = nn_it->first;
  1000       if (neighbor_point_idx != i) {
  1005         compute_perturbed_weighted_point(neighbor_point_idx, neighbor_pt, neighbor_weight);
  1006         GUDHI_CHECK(!m_max_squared_edge_length ||
  1007                     squared_star_sphere_radius_plus_margin.value() <= m_max_squared_edge_length.value(),
  1008                     std::invalid_argument(
"Tangential_complex::compute_star - set a bigger value with set_max_squared_edge_length."));
  1009         if (squared_star_sphere_radius_plus_margin &&
  1010             k_sqdist(center_pt, neighbor_pt) > squared_star_sphere_radius_plus_margin.value()) {
  1011           GUDHI_CHECK(triangulation.current_dimension() >= tangent_space_dim,
  1012                       std::invalid_argument(
"Tangential_complex::compute_star - Dimension of the star is only " + \
  1013                                             std::to_string(triangulation.current_dimension())));
  1017         Tr_point proj_pt = project_point_and_compute_weight(neighbor_pt, neighbor_weight, tsb, local_tr_traits);
  1019 #ifdef GUDHI_TC_VERY_VERBOSE  1020         ++num_attempts_to_insert_points;
  1023         Tr_vertex_handle vh = triangulation.insert_if_in_star(proj_pt, center_vertex);
  1025         if (vh != Tr_vertex_handle() && vh->data() == (std::numeric_limits<std::size_t>::max)()) {
  1026 #ifdef GUDHI_TC_VERY_VERBOSE  1027           ++num_inserted_points;
  1029           if (verbose) std::cerr << 
"* Inserted point #" << neighbor_point_idx << 
"\n";
  1031           vh->data() = neighbor_point_idx;
  1034           if (triangulation.current_dimension() >= tangent_space_dim) {
  1035             squared_star_sphere_radius_plus_margin = boost::none;
  1037             std::vector<Tr_full_cell_handle> incident_cells;
  1038             triangulation.incident_full_cells(center_vertex, std::back_inserter(incident_cells));
  1039             for (
typename std::vector<Tr_full_cell_handle>::iterator cit = incident_cells.begin();
  1040                  cit != incident_cells.end(); ++cit) {
  1041               Tr_full_cell_handle cell = *cit;
  1042               if (triangulation.is_infinite(cell)) {
  1043                 squared_star_sphere_radius_plus_margin = boost::none;
  1049                     power_center(boost::make_transform_iterator(cell->vertices_begin(),
  1050                                                                 vertex_handle_to_point<Tr_point, Tr_vertex_handle>),
  1051                                  boost::make_transform_iterator(cell->vertices_end(),
  1052                                                                 vertex_handle_to_point<Tr_point, Tr_vertex_handle>));
  1054                 FT sq_power_sphere_diam = 4 * point_weight(c);
  1056                 if (!squared_star_sphere_radius_plus_margin ||
  1057                     sq_power_sphere_diam > squared_star_sphere_radius_plus_margin.value()) {
  1058                   squared_star_sphere_radius_plus_margin = sq_power_sphere_diam;
  1065             if (squared_star_sphere_radius_plus_margin) {
  1067               squared_star_sphere_radius_plus_margin =
  1068                   CGAL::square(std::sqrt(squared_star_sphere_radius_plus_margin.value()) + 2 * m_last_max_perturb);
  1071               if (m_max_squared_edge_length && squared_star_sphere_radius_plus_margin.value() > m_max_squared_edge_length.value()) {
  1072                 squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value();
  1076               m_squared_star_spheres_radii_incl_margin[i] = squared_star_sphere_radius_plus_margin.value();
  1078               if (m_max_squared_edge_length) {
  1079                 squared_star_sphere_radius_plus_margin = m_max_squared_edge_length.value();
  1080                 m_squared_star_spheres_radii_incl_margin[i] = m_max_squared_edge_length.value();
  1082                 m_squared_star_spheres_radii_incl_margin[i] = FT(-1);
  1090     return center_vertex;
  1093   void refresh_tangent_triangulation(std::size_t i, Points_ds 
const &updated_pts_ds, 
bool verbose = 
false) {
  1094     if (verbose) std::cerr << 
"** Refreshing tangent tri #" << i << 
" **\n";
  1096     if (m_squared_star_spheres_radii_incl_margin[i] == FT(-1)) 
return compute_tangent_triangulation(i, verbose);
  1098     Point center_point = compute_perturbed_point(i);
  1100     std::size_t closest_pt_index = updated_pts_ds.
k_nearest_neighbors(center_point, 1, 
false).begin()->first;
  1102     typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object();
  1103     typename K::Power_distance_d k_power_dist = m_k.power_distance_d_object();
  1106     Weighted_point star_sphere = k_constr_wp(compute_perturbed_point(i), m_squared_star_spheres_radii_incl_margin[i]);
  1107     Weighted_point closest_updated_point = compute_perturbed_weighted_point(closest_pt_index);
  1110     if (k_power_dist(star_sphere, closest_updated_point) <= FT(0)) compute_tangent_triangulation(i, verbose);
  1113   void compute_tangent_triangulation(std::size_t i, 
bool verbose = 
false) {
  1114     if (verbose) std::cerr << 
"** Computing tangent tri #" << i << 
" **\n";
  1119     const Point center_pt = compute_perturbed_point(i);
  1120     Tangent_space_basis &tsb = m_tangent_spaces[i];
  1123     if (!m_are_tangent_spaces_computed[i]) {
  1124 #ifdef GUDHI_TC_EXPORT_NORMALS  1125       tsb = compute_tangent_space(center_pt, i, 
true , &m_orth_spaces[i]);
  1127       tsb = compute_tangent_space(center_pt, i);
  1131 #if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)  1134     int tangent_space_dim = tangent_basis_dim(i);
  1135     Triangulation &local_tr = m_triangulations[i].construct_triangulation(tangent_space_dim);
  1137     m_triangulations[i].center_vertex() = compute_star(i, center_pt, tsb, local_tr, verbose);
  1139 #if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)  1141     std::cerr << 
"  - triangulation construction: " << t.num_seconds() << 
" s.\n";
  1145 #ifdef GUDHI_TC_VERY_VERBOSE  1146     std::cerr << 
"Inserted " << num_inserted_points << 
" points / " << num_attempts_to_insert_points
  1147               << 
" attemps to compute the star\n";
  1152 #if defined(GUDHI_TC_PROFILING) && defined(GUDHI_TC_VERY_VERBOSE)  1154     std::cerr << 
"  - update_star: " << t.num_seconds() << 
" s.\n";
  1160   void update_star(std::size_t i) {
  1161     Star &star = m_stars[i];
  1163     Triangulation &local_tr = m_triangulations[i].tr();
  1164     Tr_vertex_handle center_vertex = m_triangulations[i].center_vertex();
  1165     int cur_dim_plus_1 = local_tr.current_dimension() + 1;
  1167     std::vector<Tr_full_cell_handle> incident_cells;
  1168     local_tr.incident_full_cells(center_vertex, std::back_inserter(incident_cells));
  1170     typename std::vector<Tr_full_cell_handle>::const_iterator it_c = incident_cells.begin();
  1171     typename std::vector<Tr_full_cell_handle>::const_iterator it_c_end = incident_cells.end();
  1173     for (; it_c != it_c_end; ++it_c) {
  1175       Incident_simplex incident_simplex;
  1176       for (
int j = 0; j < cur_dim_plus_1; ++j) {
  1177         std::size_t index = (*it_c)->vertex(j)->data();
  1178         if (index != i) incident_simplex.insert(index);
  1180       GUDHI_CHECK(incident_simplex.size() == cur_dim_plus_1 - 1,
  1181                   std::logic_error(
"update_star: wrong size of incident simplex"));
  1182       star.push_back(incident_simplex);
  1188   Tangent_space_basis compute_tangent_space(
const Point &p, 
const std::size_t i, 
bool normalize_basis = 
true,
  1189                                             Orthogonal_space_basis *p_orth_space_basis = NULL) {
  1190     unsigned int num_pts_for_pca =
  1191         (std::min)(static_cast<unsigned int>(std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim)),
  1192                    static_cast<unsigned int>(m_points.size()));
  1195     typename K::Construct_vector_d constr_vec = m_k.construct_vector_d_object();
  1196     typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
  1198 #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM  1199     KNS_range kns_range = m_points_ds_for_tse.k_nearest_neighbors(p, num_pts_for_pca, 
false);
  1200     const Points &points_for_pca = m_points_for_tse;
  1202     KNS_range kns_range = m_points_ds.k_nearest_neighbors(p, num_pts_for_pca, 
false);
  1203     const Points &points_for_pca = m_points;
  1207     Eigen::MatrixXd mat_points(num_pts_for_pca, m_ambient_dim);
  1208     auto nn_it = kns_range.begin();
  1209     for (
unsigned int j = 0; j < num_pts_for_pca && nn_it != kns_range.end(); ++j, ++nn_it) {
  1210       for (
int i = 0; i < m_ambient_dim; ++i) {
  1211         mat_points(j, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i));
  1214     Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean();
  1215     Eigen::MatrixXd cov = centered.adjoint() * centered;
  1216     Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov);
  1218     Tangent_space_basis tsb(i);  
  1222     for (
int j = m_ambient_dim - 1; j >= m_ambient_dim - m_intrinsic_dim; --j) {
  1223       if (normalize_basis) {
  1224         Vector v = constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1225                               eig.eigenvectors().col(j).data() + m_ambient_dim);
  1226         tsb.push_back(normalize_vector(v, m_k));
  1228         tsb.push_back(constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1229                                  eig.eigenvectors().col(j).data() + m_ambient_dim));
  1233     if (p_orth_space_basis) {
  1234       p_orth_space_basis->set_origin(i);
  1235       for (
int j = m_ambient_dim - m_intrinsic_dim - 1; j >= 0; --j) {
  1236         if (normalize_basis) {
  1237           Vector v = constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1238                                 eig.eigenvectors().col(j).data() + m_ambient_dim);
  1239           p_orth_space_basis->push_back(normalize_vector(v, m_k));
  1241           p_orth_space_basis->push_back(constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1242                                                    eig.eigenvectors().col(j).data() + m_ambient_dim));
  1247     m_are_tangent_spaces_computed[i] = 
true;
  1257   Tangent_space_basis compute_tangent_space(
const Simplex &s, 
bool normalize_basis = 
true) {
  1258     unsigned int num_pts_for_pca =
  1259         (std::min)(static_cast<unsigned int>(std::pow(GUDHI_TC_BASE_VALUE_FOR_PCA, m_intrinsic_dim)),
  1260                    static_cast<unsigned int>(m_points.size()));
  1263     typename K::Construct_vector_d constr_vec = m_k.construct_vector_d_object();
  1264     typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
  1265     typename K::Squared_length_d sqlen = m_k.squared_length_d_object();
  1266     typename K::Scaled_vector_d scaled_vec = m_k.scaled_vector_d_object();
  1267     typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object();
  1268     typename K::Difference_of_vectors_d diff_vec = m_k.difference_of_vectors_d_object();
  1271     Eigen::MatrixXd mat_points(s.size() * num_pts_for_pca, m_ambient_dim);
  1272     unsigned int current_row = 0;
  1274     for (Simplex::const_iterator it_index = s.begin(); it_index != s.end(); ++it_index) {
  1275       const Point &p = m_points[*it_index];
  1277 #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM  1278       KNS_range kns_range = m_points_ds_for_tse.k_nearest_neighbors(p, num_pts_for_pca, 
false);
  1279       const Points &points_for_pca = m_points_for_tse;
  1281       KNS_range kns_range = m_points_ds.k_nearest_neighbors(p, num_pts_for_pca, 
false);
  1282       const Points &points_for_pca = m_points;
  1285       auto nn_it = kns_range.begin();
  1286       for (; current_row < num_pts_for_pca && nn_it != kns_range.end(); ++current_row, ++nn_it) {
  1287         for (
int i = 0; i < m_ambient_dim; ++i) {
  1288           mat_points(current_row, i) = CGAL::to_double(coord(points_for_pca[nn_it->first], i));
  1292     Eigen::MatrixXd centered = mat_points.rowwise() - mat_points.colwise().mean();
  1293     Eigen::MatrixXd cov = centered.adjoint() * centered;
  1294     Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eig(cov);
  1296     Tangent_space_basis tsb;
  1300     for (
int j = m_ambient_dim - 1; j >= m_ambient_dim - m_intrinsic_dim; --j) {
  1301       if (normalize_basis) {
  1302         Vector v = constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1303                               eig.eigenvectors().col(j).data() + m_ambient_dim);
  1304         tsb.push_back(normalize_vector(v, m_k));
  1306         tsb.push_back(constr_vec(m_ambient_dim, eig.eigenvectors().col(j).data(),
  1307                                  eig.eigenvectors().col(j).data() + m_ambient_dim));
  1316   int tangent_basis_dim(std::size_t i)
 const { 
return m_tangent_spaces[i].dimension(); }
  1318   Point compute_perturbed_point(std::size_t pt_idx)
 const {
  1319 #ifdef GUDHI_TC_PERTURB_POSITION  1320     return m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]);
  1322     return m_points[pt_idx];
  1326   void compute_perturbed_weighted_point(std::size_t pt_idx, Point &p, FT &w)
 const {
  1327 #ifdef GUDHI_TC_PERTURB_POSITION  1328     p = m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]);
  1330     p = m_points[pt_idx];
  1332     w = m_weights[pt_idx];
  1335   Weighted_point compute_perturbed_weighted_point(std::size_t pt_idx)
 const {
  1336     typename K::Construct_weighted_point_d k_constr_wp = m_k.construct_weighted_point_d_object();
  1338     Weighted_point wp = k_constr_wp(
  1339 #ifdef GUDHI_TC_PERTURB_POSITION
  1340         m_k.translated_point_d_object()(m_points[pt_idx], m_translations[pt_idx]),
  1349   Point unproject_point(
const Tr_point &p, 
const Tangent_space_basis &tsb, 
const Tr_traits &tr_traits)
 const {
  1350     typename K::Translated_point_d k_transl = m_k.translated_point_d_object();
  1351     typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object();
  1352     typename Tr_traits::Compute_coordinate_d coord = tr_traits.compute_coordinate_d_object();
  1354     Point global_point = compute_perturbed_point(tsb.origin());
  1355     for (
int i = 0; i < m_intrinsic_dim; ++i) global_point = k_transl(global_point, k_scaled_vec(tsb[i], coord(p, i)));
  1357     return global_point;
  1362   Tr_bare_point project_point(
const Point &p, 
const Tangent_space_basis &tsb, 
const Tr_traits &tr_traits)
 const {
  1363     typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object();
  1364     typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object();
  1366     Vector v = diff_points(p, compute_perturbed_point(tsb.origin()));
  1368     std::vector<FT> coords;
  1370     coords.reserve(tsb.dimension());
  1371     for (std::size_t i = 0; i < m_intrinsic_dim; ++i) {
  1373       FT coord = scalar_pdct(v, tsb[i]);
  1374       coords.push_back(coord);
  1377     return tr_traits.construct_point_d_object()(
static_cast<int>(coords.size()), coords.begin(), coords.end());
  1384   Tr_point project_point_and_compute_weight(
const Weighted_point &wp, 
const Tangent_space_basis &tsb,
  1385                                             const Tr_traits &tr_traits)
 const {
  1386     typename K::Point_drop_weight_d k_drop_w = m_k.point_drop_weight_d_object();
  1387     typename K::Compute_weight_d k_point_weight = m_k.compute_weight_d_object();
  1388     return project_point_and_compute_weight(k_drop_w(wp), k_point_weight(wp), tsb, tr_traits);
  1392   Tr_point project_point_and_compute_weight(
const Point &p, 
const FT w, 
const Tangent_space_basis &tsb,
  1393                                             const Tr_traits &tr_traits)
 const {
  1394     const int point_dim = m_k.point_dimension_d_object()(p);
  1396     typename K::Construct_point_d constr_pt = m_k.construct_point_d_object();
  1397     typename K::Scalar_product_d scalar_pdct = m_k.scalar_product_d_object();
  1398     typename K::Difference_of_points_d diff_points = m_k.difference_of_points_d_object();
  1399     typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
  1400     typename K::Construct_cartesian_const_iterator_d ccci = m_k.construct_cartesian_const_iterator_d_object();
  1402     Point origin = compute_perturbed_point(tsb.origin());
  1403     Vector v = diff_points(p, origin);
  1406     bool same_dim = (point_dim == tsb.dimension());
  1408     std::vector<FT> coords;
  1410     std::vector<FT> p_proj(ccci(origin), ccci(origin, 0));
  1411     coords.reserve(tsb.dimension());
  1412     for (
int i = 0; i < tsb.dimension(); ++i) {
  1414       FT c = scalar_pdct(v, tsb[i]);
  1415       coords.push_back(c);
  1419         for (
int j = 0; j < point_dim; ++j) p_proj[j] += c * coord(tsb[i], j);
  1424     FT sq_dist_to_proj_pt = 0;
  1426       Point projected_pt = constr_pt(point_dim, p_proj.begin(), p_proj.end());
  1427       sq_dist_to_proj_pt = m_k.squared_distance_d_object()(p, projected_pt);
  1430     return tr_traits.construct_weighted_point_d_object()(
  1431         tr_traits.construct_point_d_object()(
static_cast<int>(coords.size()), coords.begin(), coords.end()),
  1432         w - sq_dist_to_proj_pt);
  1437   template <
typename Indexed_po
int_range>
  1438   std::vector<Tr_point> project_points_and_compute_weights(
const Indexed_point_range &point_indices,
  1439                                                            const Tangent_space_basis &tsb,
  1440                                                            const Tr_traits &tr_traits)
 const {
  1441     std::vector<Tr_point> ret;
  1442     for (
typename Indexed_point_range::const_iterator it = point_indices.begin(), it_end = point_indices.end();
  1443          it != it_end; ++it) {
  1444       ret.push_back(project_point_and_compute_weight(compute_perturbed_weighted_point(*it), tsb, tr_traits));
  1451   bool is_simplex_consistent(Tr_full_cell_handle fch, 
int cur_dim)
 const {
  1453     for (
int i = 0; i < cur_dim + 1; ++i) {
  1454       std::size_t data = fch->vertex(i)->data();
  1457     return is_simplex_consistent(c);
  1463   bool is_simplex_consistent(Simplex 
const &simplex)
 const {
  1465     Simplex::const_iterator it_point_idx = simplex.begin();
  1468     for (; it_point_idx != simplex.end(); ++it_point_idx) {
  1469       std::size_t point_idx = *it_point_idx;
  1471       if (point_idx == (std::numeric_limits<std::size_t>::max)()) 
continue;
  1473       Star 
const &star = m_stars[point_idx];
  1476       Incident_simplex is_to_find = simplex;
  1477       is_to_find.erase(point_idx);
  1480       if (std::find(star.begin(), star.end(), is_to_find) == star.end()) 
return false;
  1492   template <
typename OutputIterator>  
  1493   bool is_simplex_consistent(std::size_t center_point,
  1494                              Incident_simplex 
const &s,  
  1495                              OutputIterator points_whose_star_does_not_contain_s,
  1496                              bool check_also_in_non_maximal_faces = 
false)
 const {
  1497     Simplex full_simplex = s;
  1498     full_simplex.insert(center_point);
  1501     Incident_simplex::const_iterator it_point_idx = s.begin();
  1504     for (; it_point_idx != s.end(); ++it_point_idx) {
  1505       std::size_t point_idx = *it_point_idx;
  1507       if (point_idx == (std::numeric_limits<std::size_t>::max)()) 
continue;
  1509       Star 
const &star = m_stars[point_idx];
  1512       Incident_simplex is_to_find = full_simplex;
  1513       is_to_find.erase(point_idx);
  1515       if (check_also_in_non_maximal_faces) {
  1519         for (Star::const_iterator is = star.begin(), is_end = star.end(); !found && is != is_end; ++is) {
  1520           if (std::includes(is->begin(), is->end(), is_to_find.begin(), is_to_find.end())) found = 
true;
  1523         if (!found) *points_whose_star_does_not_contain_s++ = point_idx;
  1526         if (std::find(star.begin(), star.end(), is_to_find) == star.end())
  1527           *points_whose_star_does_not_contain_s++ = point_idx;
  1537   bool is_simplex_in_star(std::size_t p, Incident_simplex 
const &s, 
bool check_also_in_non_maximal_faces = 
true)
 const {
  1538     Star 
const &star = m_stars[p];
  1540     if (check_also_in_non_maximal_faces) {
  1544       for (Star::const_iterator is = star.begin(), is_end = star.end(); !found && is != is_end; ++is) {
  1545         if (std::includes(is->begin(), is->end(), s.begin(), s.end())) found = 
true;
  1550       return !(std::find(star.begin(), star.end(), s) == star.end());
  1554 #ifdef GUDHI_USE_TBB  1556   class Try_to_solve_inconsistencies_in_a_local_triangulation {
  1558     double m_max_perturb;
  1559     tbb::combinable<std::size_t> &m_num_inconsistencies;
  1560     tbb::combinable<std::vector<std::size_t> > &m_updated_points;
  1564     Try_to_solve_inconsistencies_in_a_local_triangulation(
Tangential_complex &tc, 
double max_perturb,
  1565                                                           tbb::combinable<std::size_t> &num_inconsistencies,
  1566                                                           tbb::combinable<std::vector<std::size_t> > &updated_points)
  1568           m_max_perturb(max_perturb),
  1569           m_num_inconsistencies(num_inconsistencies),
  1570           m_updated_points(updated_points) {}
  1573     Try_to_solve_inconsistencies_in_a_local_triangulation(
  1574         const Try_to_solve_inconsistencies_in_a_local_triangulation &tsilt)
  1576           m_max_perturb(tsilt.m_max_perturb),
  1577           m_num_inconsistencies(tsilt.m_num_inconsistencies),
  1578           m_updated_points(tsilt.m_updated_points) {}
  1581     void operator()(
const tbb::blocked_range<size_t> &r)
 const {
  1582       for (
size_t i = r.begin(); i != r.end(); ++i) {
  1583         m_num_inconsistencies.local() += m_tc.try_to_solve_inconsistencies_in_a_local_triangulation(
  1584             i, m_max_perturb, std::back_inserter(m_updated_points.local()));
  1588 #endif  // GUDHI_USE_TBB  1590   void perturb(std::size_t point_idx, 
double max_perturb) {
  1591     const Tr_traits &local_tr_traits = m_triangulations[point_idx].tr().geom_traits();
  1592     typename Tr_traits::Compute_coordinate_d coord = local_tr_traits.compute_coordinate_d_object();
  1593     typename K::Translated_point_d k_transl = m_k.translated_point_d_object();
  1594     typename K::Construct_vector_d k_constr_vec = m_k.construct_vector_d_object();
  1595     typename K::Scaled_vector_d k_scaled_vec = m_k.scaled_vector_d_object();
  1597     CGAL::Random_points_in_ball_d<Tr_bare_point> tr_point_in_ball_generator(
  1598         m_intrinsic_dim, m_random_generator.get_double(0., max_perturb));
  1600     Tr_point local_random_transl =
  1601         local_tr_traits.construct_weighted_point_d_object()(*tr_point_in_ball_generator++, 0);
  1602     Translation_for_perturb global_transl = k_constr_vec(m_ambient_dim);
  1603     const Tangent_space_basis &tsb = m_tangent_spaces[point_idx];
  1604     for (
int i = 0; i < m_intrinsic_dim; ++i) {
  1605       global_transl = k_transl(global_transl, k_scaled_vec(tsb[i], coord(local_random_transl, i)));
  1608 #if defined(GUDHI_USE_TBB)  1609     m_p_perturb_mutexes[point_idx].lock();
  1610     m_translations[point_idx] = global_transl;
  1611     m_p_perturb_mutexes[point_idx].unlock();
  1614     m_translations[point_idx] = global_transl;
  1619   template <
typename OutputIt>
  1620   bool try_to_solve_inconsistencies_in_a_local_triangulation(
  1621       std::size_t tr_index, 
double max_perturb, OutputIt perturbed_pts_indices = CGAL::Emptyset_iterator()) {
  1622     bool is_inconsistent = 
false;
  1624     Star 
const &star = m_stars[tr_index];
  1627     Star::const_iterator it_inc_simplex = star.begin();
  1628     Star::const_iterator it_inc_simplex_end = star.end();
  1629     for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
  1630       const Incident_simplex &incident_simplex = *it_inc_simplex;
  1633       if (is_infinite(incident_simplex)) 
continue;
  1635       Simplex c = incident_simplex;
  1639       if (!is_simplex_consistent(c)) {
  1640         is_inconsistent = 
true;
  1642         std::size_t idx = tr_index;
  1644         perturb(tr_index, max_perturb);
  1645         *perturbed_pts_indices++ = idx;
  1652     return is_inconsistent;
  1657   std::ostream &export_point_set(std::ostream &os, 
bool use_perturbed_points = 
false,
  1658                                  const char *coord_separator = 
" ")
 const {
  1659     if (use_perturbed_points) {
  1660       std::vector<Point> perturbed_points;
  1661       perturbed_points.reserve(m_points.size());
  1662       for (std::size_t i = 0; i < m_points.size(); ++i) perturbed_points.push_back(compute_perturbed_point(i));
  1664       return export_point_set(m_k, perturbed_points, os, coord_separator);
  1666       return export_point_set(m_k, m_points, os, coord_separator);
  1670   template <
typename ProjectionFunctor = CGAL::Identity<Po
int> >
  1671   std::ostream &export_vertices_to_off(std::ostream &os, std::size_t &num_vertices, 
bool use_perturbed_points = 
false,
  1672                                        ProjectionFunctor 
const &point_projection = ProjectionFunctor())
 const {
  1673     if (m_points.empty()) {
  1681     const int N = (m_intrinsic_dim == 1 ? 2 : 1);
  1684     typename K::Compute_coordinate_d coord = m_k.compute_coordinate_d_object();
  1686 #ifdef GUDHI_TC_EXPORT_ALL_COORDS_IN_OFF  1687     int num_coords = m_ambient_dim;
  1689     int num_coords = (std::min)(m_ambient_dim, 3);
  1692 #ifdef GUDHI_TC_EXPORT_NORMALS  1693     OS_container::const_iterator it_os = m_orth_spaces.begin();
  1695     typename Points::const_iterator it_p = m_points.begin();
  1696     typename Points::const_iterator it_p_end = m_points.end();
  1698     for (std::size_t i = 0; it_p != it_p_end; ++it_p, ++i) {
  1699       Point p = point_projection(use_perturbed_points ? compute_perturbed_point(i) : *it_p);
  1700       for (
int ii = 0; ii < N; ++ii) {
  1702         for (; j < num_coords; ++j) os << CGAL::to_double(coord(p, j)) << 
" ";
  1703         if (j == 2) os << 
"0";
  1705 #ifdef GUDHI_TC_EXPORT_NORMALS  1706         for (j = 0; j < num_coords; ++j) os << 
" " << CGAL::to_double(coord(*it_os->begin(), j));
  1710 #ifdef GUDHI_TC_EXPORT_NORMALS  1715     num_vertices = N * m_points.size();
  1719   std::ostream &export_simplices_to_off(std::ostream &os, std::size_t &num_OFF_simplices,
  1720                                         bool color_inconsistencies = 
false,
  1721                                         Simplex_set 
const *p_simpl_to_color_in_red = NULL,
  1722                                         Simplex_set 
const *p_simpl_to_color_in_green = NULL,
  1723                                         Simplex_set 
const *p_simpl_to_color_in_blue = NULL)
 const {
  1726     num_OFF_simplices = 0;
  1727     std::size_t num_maximal_simplices = 0;
  1728     std::size_t num_inconsistent_maximal_simplices = 0;
  1729     std::size_t num_inconsistent_stars = 0;
  1730     typename Tr_container::const_iterator it_tr = m_triangulations.begin();
  1731     typename Tr_container::const_iterator it_tr_end = m_triangulations.end();
  1733     for (std::size_t idx = 0; it_tr != it_tr_end; ++it_tr, ++idx) {
  1734       bool is_star_inconsistent = 
false;
  1736       Triangulation 
const &tr = it_tr->tr();
  1738       if (tr.current_dimension() < m_intrinsic_dim) 
continue;
  1741       std::stringstream color;
  1743       color << 128 << 
" " << 128 << 
" " << 128;
  1746       typedef std::vector<std::pair<Simplex, int> > Star_using_triangles;
  1747       Star_using_triangles star_using_triangles;
  1750       Star::const_iterator it_inc_simplex = m_stars[idx].begin();
  1751       Star::const_iterator it_inc_simplex_end = m_stars[idx].end();
  1752       for (; it_inc_simplex != it_inc_simplex_end; ++it_inc_simplex) {
  1753         Simplex c = *it_inc_simplex;
  1755         std::size_t num_vertices = c.size();
  1756         ++num_maximal_simplices;
  1758         int color_simplex = -1;  
  1759         if (color_inconsistencies && !is_simplex_consistent(c)) {
  1760           ++num_inconsistent_maximal_simplices;
  1762           is_star_inconsistent = 
true;
  1764           if (p_simpl_to_color_in_red && std::find(p_simpl_to_color_in_red->begin(), p_simpl_to_color_in_red->end(),
  1765                                                    c) != p_simpl_to_color_in_red->end()) {
  1767           } 
else if (p_simpl_to_color_in_green &&
  1768                      std::find(p_simpl_to_color_in_green->begin(), p_simpl_to_color_in_green->end(), c) !=
  1769                          p_simpl_to_color_in_green->end()) {
  1771           } 
else if (p_simpl_to_color_in_blue &&
  1772                      std::find(p_simpl_to_color_in_blue->begin(), p_simpl_to_color_in_blue->end(), c) !=
  1773                          p_simpl_to_color_in_blue->end()) {
  1782         if (m_intrinsic_dim == 1) {
  1784           Simplex::iterator it = c.begin();
  1785           for (; it != c.end(); ++it) tmp_c.insert(*it * 2);
  1786           if (num_vertices == 2) tmp_c.insert(*tmp_c.rbegin() + 1);
  1791         if (num_vertices <= 3) {
  1792           star_using_triangles.push_back(std::make_pair(c, color_simplex));
  1795           std::vector<bool> booleans(num_vertices, 
false);
  1796           std::fill(booleans.begin() + num_vertices - 3, booleans.end(), 
true);
  1799             Simplex::iterator it = c.begin();
  1800             for (
int i = 0; it != c.end(); ++i, ++it) {
  1801               if (booleans[i]) triangle.insert(*it);
  1803             star_using_triangles.push_back(std::make_pair(triangle, color_simplex));
  1804           } 
while (std::next_permutation(booleans.begin(), booleans.end()));
  1809       Star_using_triangles::const_iterator it_simplex = star_using_triangles.begin();
  1810       Star_using_triangles::const_iterator it_simplex_end = star_using_triangles.end();
  1811       for (; it_simplex != it_simplex_end; ++it_simplex) {
  1812         const Simplex &c = it_simplex->first;
  1815         if (is_infinite(c)) 
continue;
  1817         int color_simplex = it_simplex->second;
  1819         std::stringstream sstr_c;
  1821         Simplex::const_iterator it_point_idx = c.begin();
  1822         for (; it_point_idx != c.end(); ++it_point_idx) {
  1823           sstr_c << *it_point_idx << 
" ";
  1826         os << 3 << 
" " << sstr_c.str();
  1827         if (color_inconsistencies || p_simpl_to_color_in_red || p_simpl_to_color_in_green || p_simpl_to_color_in_blue) {
  1828           switch (color_simplex) {
  1842               os << 
" " << color.str();
  1846         ++num_OFF_simplices;
  1849       if (is_star_inconsistent) ++num_inconsistent_stars;
  1853     std::cerr << 
"\n==========================================================\n"  1854               << 
"Export from list of stars to OFF:\n"  1855               << 
"  * Number of vertices: " << m_points.size() << 
"\n"  1856               << 
"  * Total number of maximal simplices: " << num_maximal_simplices << 
"\n";
  1857     if (color_inconsistencies) {
  1858       std::cerr << 
"  * Number of inconsistent stars: " << num_inconsistent_stars << 
" ("  1859                 << (m_points.size() > 0 ? 100. * num_inconsistent_stars / m_points.size() : 0.) << 
"%)\n"  1860                 << 
"  * Number of inconsistent maximal simplices: " << num_inconsistent_maximal_simplices << 
" ("  1861                 << (num_maximal_simplices > 0 ? 100. * num_inconsistent_maximal_simplices / num_maximal_simplices : 0.)
  1864     std::cerr << 
"==========================================================\n";
  1871   std::ostream &export_simplices_to_off(
const Simplicial_complex &complex, std::ostream &os,
  1872                                         std::size_t &num_OFF_simplices,
  1873                                         Simplex_set 
const *p_simpl_to_color_in_red = NULL,
  1874                                         Simplex_set 
const *p_simpl_to_color_in_green = NULL,
  1875                                         Simplex_set 
const *p_simpl_to_color_in_blue = NULL)
 const {
  1876     typedef Simplicial_complex::Simplex Simplex;
  1877     typedef Simplicial_complex::Simplex_set Simplex_set;
  1881     num_OFF_simplices = 0;
  1882     std::size_t num_maximal_simplices = 0;
  1884     typename Simplex_set::const_iterator it_s = complex.simplex_range().begin();
  1885     typename Simplex_set::const_iterator it_s_end = complex.simplex_range().end();
  1887     for (; it_s != it_s_end; ++it_s) {
  1889       ++num_maximal_simplices;
  1891       int color_simplex = -1;  
  1892       if (p_simpl_to_color_in_red && std::find(p_simpl_to_color_in_red->begin(), p_simpl_to_color_in_red->end(), c) !=
  1893                                          p_simpl_to_color_in_red->end()) {
  1895       } 
else if (p_simpl_to_color_in_green &&
  1896                  std::find(p_simpl_to_color_in_green->begin(), p_simpl_to_color_in_green->end(), c) !=
  1897                      p_simpl_to_color_in_green->end()) {
  1899       } 
else if (p_simpl_to_color_in_blue &&
  1900                  std::find(p_simpl_to_color_in_blue->begin(), p_simpl_to_color_in_blue->end(), c) !=
  1901                      p_simpl_to_color_in_blue->end()) {
  1906       typedef std::vector<Simplex> Triangles;
  1907       Triangles triangles;
  1909       int num_vertices = 
static_cast<int>(c.size());
  1911       if (num_vertices < m_intrinsic_dim + 1) 
continue;
  1917       if (m_intrinsic_dim == 1) {
  1919         Simplex::iterator it = c.begin();
  1920         for (; it != c.end(); ++it) tmp_c.insert(*it * 2);
  1921         if (num_vertices == 2) tmp_c.insert(*tmp_c.rbegin() + 1);
  1926       if (num_vertices <= 3) {
  1927         triangles.push_back(c);
  1930         std::vector<bool> booleans(num_vertices, 
false);
  1931         std::fill(booleans.begin() + num_vertices - 3, booleans.end(), 
true);
  1934           Simplex::iterator it = c.begin();
  1935           for (
int i = 0; it != c.end(); ++i, ++it) {
  1936             if (booleans[i]) triangle.insert(*it);
  1938           triangles.push_back(triangle);
  1939         } 
while (std::next_permutation(booleans.begin(), booleans.end()));
  1943       Triangles::const_iterator it_tri = triangles.begin();
  1944       Triangles::const_iterator it_tri_end = triangles.end();
  1945       for (; it_tri != it_tri_end; ++it_tri) {
  1947         if (is_infinite(*it_tri)) 
continue;
  1950         Simplex::const_iterator it_point_idx = it_tri->begin();
  1951         for (; it_point_idx != it_tri->end(); ++it_point_idx) {
  1952           os << *it_point_idx << 
" ";
  1955         if (p_simpl_to_color_in_red || p_simpl_to_color_in_green || p_simpl_to_color_in_blue) {
  1956           switch (color_simplex) {
  1970               os << 
" 128 128 128";
  1975         ++num_OFF_simplices;
  1981     std::cerr << 
"\n==========================================================\n"  1982               << 
"Export from complex to OFF:\n"  1983               << 
"  * Number of vertices: " << m_points.size() << 
"\n"  1984               << 
"  * Total number of maximal simplices: " << num_maximal_simplices << 
"\n"  1985               << 
"==========================================================\n";
  2002   const int m_intrinsic_dim;
  2003   const int m_ambient_dim;
  2007 #ifdef GUDHI_TC_PERTURB_POSITION  2008   Translations_for_perturb m_translations;
  2009 #if defined(GUDHI_USE_TBB)  2010   Mutex_for_perturb *m_p_perturb_mutexes;
  2014   Points_ds m_points_ds;
  2015   double m_last_max_perturb;
  2016   std::vector<bool> m_are_tangent_spaces_computed;
  2017   TS_container m_tangent_spaces;
  2018 #ifdef GUDHI_TC_EXPORT_NORMALS  2019   OS_container m_orth_spaces;
  2021   Tr_container m_triangulations;  
  2023   Stars_container m_stars;
  2024   std::vector<FT> m_squared_star_spheres_radii_incl_margin;
  2025   boost::optional<FT> m_max_squared_edge_length;
  2027 #ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM  2028   Points m_points_for_tse;
  2029   Points_ds m_points_ds_for_tse;
  2032   mutable CGAL::Random m_random_generator;
  2038 #endif  // TANGENTIAL_COMPLEX_H_ 
std::size_t num_inconsistent_simplices
Number of inconsistent simplices. 
Definition: Tangential_complex.h:543
void set_max_squared_edge_length(FT max_squared_edge_length)
Sets the maximal possible squared edge length for the edges in the triangulations. 
Definition: Tangential_complex.h:1998
Type returned by Tangential_complex::fix_inconsistencies_using_perturbation. 
Definition: Tangential_complex.h:377
Point get_point(std::size_t vertex) const
Returns the point corresponding to the vertex given as parameter. 
Definition: Tangential_complex.h:291
Tangential complex data structure. 
Definition: Tangential_complex.h:125
Incremental_neighbor_search INS_range
The range returned by an incremental nearest or furthest neighbor search. Its value type is std::pair...
Definition: Kd_tree_search.h:111
K_neighbor_search KNS_range
The range returned by a k-nearest or k-furthest neighbor search. Its value type is std::pair<std::siz...
Definition: Kd_tree_search.h:103
KNS_range k_nearest_neighbors(Point const &p, unsigned int k, bool sorted=true, FT eps=FT(0)) const
Search for the k-nearest neighbors from a query point. 
Definition: Kd_tree_search.h:175
std::size_t final_num_inconsistent_stars
final number of inconsistent stars 
Definition: Tangential_complex.h:387
Definition: SimplicialComplexForAlpha.h:14
~Tangential_complex()
Destructor. 
Definition: Tangential_complex.h:272
std::size_t num_simplices
Total number of simplices in stars (including duplicates that appear in several stars) ...
Definition: Tangential_complex.h:541
std::size_t best_num_inconsistent_stars
best number of inconsistent stars during the process 
Definition: Tangential_complex.h:385
std::size_t num_inconsistent_stars
Number of stars containing at least one inconsistent simplex. 
Definition: Tangential_complex.h:545
int create_complex(Simplex_tree_ &tree, bool export_inconsistent_simplices=true) const
Exports the complex into a Simplex_tree. 
Definition: Tangential_complex.h:610
Fix_inconsistencies_info fix_inconsistencies_using_perturbation(double max_perturb, double time_limit=-1.)
Attempts to fix inconsistencies by perturbing the point positions. 
Definition: Tangential_complex.h:395
std::size_t initial_num_inconsistent_stars
initial number of inconsistent stars 
Definition: Tangential_complex.h:383
Tangential_complex(Point_range points, int intrinsic_dimension, const K &k=K())
Constructor from a range of points. Points are copied into the instance, and a search data structure ...
Definition: Tangential_complex.h:240
Num_inconsistencies number_of_inconsistent_simplices(bool verbose=false) const
Definition: Tangential_complex.h:551
bool success
true if all inconsistencies could be removed, false if the time limit has been reached before ...
Definition: Tangential_complex.h:379
int intrinsic_dimension() const
Returns the intrinsic dimension of the manifold. 
Definition: Tangential_complex.h:279
Definition: Intro_spatial_searching.h:16
void compute_tangential_complex()
Computes the tangential complex. 
Definition: Tangential_complex.h:330
int ambient_dimension() const
Returns the ambient dimension. 
Definition: Tangential_complex.h:282
Type returned by Tangential_complex::number_of_inconsistent_simplices. 
Definition: Tangential_complex.h:539
std::size_t number_of_vertices() const
Returns the number of vertices. 
Definition: Tangential_complex.h:302
unsigned int num_steps
number of steps performed 
Definition: Tangential_complex.h:381
Point get_perturbed_point(std::size_t vertex) const
Returns the perturbed position of the point corresponding to the vertex given as parameter. 
Definition: Tangential_complex.h:298